tizen 2.4 release accepted/tizen/2.4/mobile/20151029.033127 submit/tizen_2.4/20151028.064154 tizen_2.4_mobile_release
authorjk7744.park <jk7744.park@samsung.com>
Mon, 26 Oct 2015 06:46:01 +0000 (15:46 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Mon, 26 Oct 2015 06:46:01 +0000 (15:46 +0900)
877 files changed:
.gitignore [new file with mode: 0644]
LICENSE [new file with mode: 0644]
README [new file with mode: 0644]
automated-tests/.gitignore [new file with mode: 0644]
automated-tests/.gitignore-with-autogenerated-files [new file with mode: 0644]
automated-tests/.gitignore-without-autogenerated-files [new file with mode: 0644]
automated-tests/CMakeLists.txt [new file with mode: 0644]
automated-tests/README.md [new file with mode: 0644]
automated-tests/build.sh [new file with mode: 0755]
automated-tests/coverage.sh [new file with mode: 0755]
automated-tests/execute.sh [new file with mode: 0755]
automated-tests/packaging/core-dali-tests.spec [new file with mode: 0644]
automated-tests/scripts/add_all_smack_rule.sh [new file with mode: 0755]
automated-tests/scripts/add_smack_rule.sh [new file with mode: 0755]
automated-tests/scripts/add_style.pl [new file with mode: 0755]
automated-tests/scripts/all_smack.rule [new file with mode: 0644]
automated-tests/scripts/autocompletion.sh [new file with mode: 0755]
automated-tests/scripts/init.sh [new file with mode: 0755]
automated-tests/scripts/retriever.sh [new file with mode: 0755]
automated-tests/scripts/summarize.pl [new file with mode: 0755]
automated-tests/scripts/tcbuild.sh [new file with mode: 0755]
automated-tests/scripts/tcheadgen.sh [new file with mode: 0755]
automated-tests/scripts/tcpackageslistsgen.sh [new file with mode: 0755]
automated-tests/scripts/tctestsgen.sh [new file with mode: 0755]
automated-tests/src/CMakeLists.txt [new file with mode: 0644]
automated-tests/src/common/assert.h [new file with mode: 0644]
automated-tests/src/common/signal-helper.h [new file with mode: 0644]
automated-tests/src/common/testcase.h [new file with mode: 0644]
automated-tests/src/dali-devel/CMakeLists.txt [new file with mode: 0644]
automated-tests/src/dali-devel/tct-dali-devel-core.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Actor.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Atlas.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Context.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-CullFace.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Geometry.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Hash.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Material.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Mutex.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Renderer.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Sampler.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Scripting.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-Shader.cpp [new file with mode: 0644]
automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/CMakeLists.txt [new file with mode: 0644]
automated-tests/src/dali-internal/tct-dali-internal-core.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp [new file with mode: 0644]
automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp [new file with mode: 0644]
automated-tests/src/dali/CMakeLists.txt [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-application.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-application.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-harness.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-native-image.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp [new file with mode: 0644]
automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h [new file with mode: 0644]
automated-tests/src/dali/tct-dali-core.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Actor.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-AlphaFunction.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-AngleAxis.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Animation.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Any.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-BaseHandle.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-BufferImage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-CameraActor.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Constrainer.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Constraint.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ConstraintSource.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Constraints.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-CustomActor.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Degree.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Gesture.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-GestureDetector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Handle.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-HoverProcessing.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Image.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ImageActor.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-KeyEvent.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Layer.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-LongPressGesture.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-MathUtils.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Matrix.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Matrix3.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-MeshMaterial.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-NativeImage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-NinePatchImages.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PanGesture.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Path.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PinchGesture.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Pixel.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PropertyArray.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PropertyMap.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PropertyNotification.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PropertyTypes.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-PropertyValue.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Quaternion.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Radian.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Random.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Rect.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-RenderTask.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-RenderTaskList.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ResourceImage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-ShaderEffect.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-SignalTemplates.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Stage.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-TapGesture.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-TouchProcessing.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-TypeRegistry.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Uint16Pair.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Vector.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Vector2.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Vector3.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-Vector4.cpp [new file with mode: 0644]
automated-tests/src/dali/utc-Dali-WheelEvent.cpp [new file with mode: 0644]
automated-tests/style/back_top.png [new file with mode: 0644]
automated-tests/style/blue.jpg [new file with mode: 0644]
automated-tests/style/gray.jpg [new file with mode: 0644]
automated-tests/style/jquery.min.js [new file with mode: 0644]
automated-tests/style/orange.jpg [new file with mode: 0644]
automated-tests/style/popup.js [new file with mode: 0644]
automated-tests/style/red.jpg [new file with mode: 0644]
automated-tests/style/summary.xsl [new file with mode: 0644]
automated-tests/style/testresult.xsl [new file with mode: 0644]
automated-tests/style/tests.css [new file with mode: 0644]
automated-tests/tcbuild [new symlink]
automated-tests/templates/tct-package/README [new file with mode: 0644]
automated-tests/templates/tct-package/inst.sh [new file with mode: 0755]
build/scripts/dali_env [new file with mode: 0755]
build/scripts/generate-shader-strings.pl [new file with mode: 0755]
build/tizen/.gitignore [new file with mode: 0644]
build/tizen/Makefile.am [new file with mode: 0644]
build/tizen/configure.ac [new file with mode: 0644]
build/tizen/dali-core.pc.in [new file with mode: 0644]
build/tizen/dali-core/Makefile.am [new file with mode: 0644]
build/tizen/dali-core/linker-test.cpp [new file with mode: 0644]
dali.manifest [new file with mode: 0644]
dali/.gitignore [new file with mode: 0644]
dali/devel-api/animation/path-constrainer.cpp [new file with mode: 0644]
dali/devel-api/animation/path-constrainer.h [new file with mode: 0644]
dali/devel-api/common/hash.cpp [new file with mode: 0644]
dali/devel-api/common/hash.h [new file with mode: 0644]
dali/devel-api/common/map-wrapper.h [new file with mode: 0644]
dali/devel-api/common/mutex.cpp [new file with mode: 0644]
dali/devel-api/common/mutex.h [new file with mode: 0644]
dali/devel-api/common/ref-counted-dali-vector.h [new file with mode: 0644]
dali/devel-api/common/set-wrapper.h [new file with mode: 0644]
dali/devel-api/events/hit-test-algorithm.cpp [new file with mode: 0644]
dali/devel-api/events/hit-test-algorithm.h [new file with mode: 0644]
dali/devel-api/file.list [new file with mode: 0644]
dali/devel-api/images/atlas.cpp [new file with mode: 0644]
dali/devel-api/images/atlas.h [new file with mode: 0644]
dali/devel-api/images/distance-field.cpp [new file with mode: 0644]
dali/devel-api/images/distance-field.h [new file with mode: 0644]
dali/devel-api/object/property-buffer.cpp [new file with mode: 0644]
dali/devel-api/object/property-buffer.h [new file with mode: 0644]
dali/devel-api/object/type-registry-helper.h [new file with mode: 0644]
dali/devel-api/object/weak-handle.cpp [new file with mode: 0644]
dali/devel-api/object/weak-handle.h [new file with mode: 0644]
dali/devel-api/rendering/cull-face.cpp [new file with mode: 0644]
dali/devel-api/rendering/cull-face.h [new file with mode: 0644]
dali/devel-api/rendering/geometry.cpp [new file with mode: 0644]
dali/devel-api/rendering/geometry.h [new file with mode: 0644]
dali/devel-api/rendering/material.cpp [new file with mode: 0644]
dali/devel-api/rendering/material.h [new file with mode: 0644]
dali/devel-api/rendering/renderer.cpp [new file with mode: 0644]
dali/devel-api/rendering/renderer.h [new file with mode: 0644]
dali/devel-api/rendering/sampler.cpp [new file with mode: 0644]
dali/devel-api/rendering/sampler.h [new file with mode: 0644]
dali/devel-api/rendering/shader.cpp [new file with mode: 0644]
dali/devel-api/rendering/shader.h [new file with mode: 0644]
dali/devel-api/scripting/scripting.cpp [new file with mode: 0644]
dali/devel-api/scripting/scripting.h [new file with mode: 0644]
dali/integration-api/bitmap.cpp [new file with mode: 0644]
dali/integration-api/bitmap.h [new file with mode: 0644]
dali/integration-api/context-notifier.h [new file with mode: 0644]
dali/integration-api/core.cpp [new file with mode: 0644]
dali/integration-api/core.h [new file with mode: 0644]
dali/integration-api/debug.cpp [new file with mode: 0644]
dali/integration-api/debug.h [new file with mode: 0644]
dali/integration-api/events/event.cpp [new file with mode: 0644]
dali/integration-api/events/event.h [new file with mode: 0644]
dali/integration-api/events/gesture-event.cpp [new file with mode: 0644]
dali/integration-api/events/gesture-event.h [new file with mode: 0644]
dali/integration-api/events/gesture-requests.h [new file with mode: 0644]
dali/integration-api/events/hover-event-integ.cpp [new file with mode: 0644]
dali/integration-api/events/hover-event-integ.h [new file with mode: 0644]
dali/integration-api/events/key-event-integ.cpp [new file with mode: 0644]
dali/integration-api/events/key-event-integ.h [new file with mode: 0644]
dali/integration-api/events/long-press-gesture-event.cpp [new file with mode: 0644]
dali/integration-api/events/long-press-gesture-event.h [new file with mode: 0644]
dali/integration-api/events/multi-point-event-integ.cpp [new file with mode: 0644]
dali/integration-api/events/multi-point-event-integ.h [new file with mode: 0644]
dali/integration-api/events/pan-gesture-event.cpp [new file with mode: 0644]
dali/integration-api/events/pan-gesture-event.h [new file with mode: 0644]
dali/integration-api/events/pinch-gesture-event.cpp [new file with mode: 0644]
dali/integration-api/events/pinch-gesture-event.h [new file with mode: 0644]
dali/integration-api/events/tap-gesture-event.cpp [new file with mode: 0644]
dali/integration-api/events/tap-gesture-event.h [new file with mode: 0644]
dali/integration-api/events/touch-data.h [new file with mode: 0644]
dali/integration-api/events/touch-event-combiner.cpp [new file with mode: 0644]
dali/integration-api/events/touch-event-combiner.h [new file with mode: 0644]
dali/integration-api/events/touch-event-integ.cpp [new file with mode: 0644]
dali/integration-api/events/touch-event-integ.h [new file with mode: 0644]
dali/integration-api/events/wheel-event-integ.cpp [new file with mode: 0644]
dali/integration-api/events/wheel-event-integ.h [new file with mode: 0644]
dali/integration-api/file.list [new file with mode: 0644]
dali/integration-api/gesture-manager.h [new file with mode: 0644]
dali/integration-api/gl-abstraction.h [new file with mode: 0644]
dali/integration-api/gl-defines.h [new file with mode: 0644]
dali/integration-api/gl-sync-abstraction.h [new file with mode: 0644]
dali/integration-api/image-data.cpp [new file with mode: 0644]
dali/integration-api/image-data.h [new file with mode: 0644]
dali/integration-api/input-options.cpp [new file with mode: 0644]
dali/integration-api/input-options.h [new file with mode: 0644]
dali/integration-api/lockless-buffer.cpp [new file with mode: 0644]
dali/integration-api/lockless-buffer.h [new file with mode: 0644]
dali/integration-api/platform-abstraction.h [new file with mode: 0644]
dali/integration-api/profiling.cpp [new file with mode: 0644]
dali/integration-api/profiling.h [new file with mode: 0644]
dali/integration-api/render-controller.h [new file with mode: 0644]
dali/integration-api/resource-cache.h [new file with mode: 0644]
dali/integration-api/resource-declarations.h [new file with mode: 0644]
dali/integration-api/resource-policies.h [new file with mode: 0644]
dali/integration-api/resource-request.h [new file with mode: 0644]
dali/integration-api/resource-types.h [new file with mode: 0644]
dali/integration-api/system-overlay.cpp [new file with mode: 0644]
dali/integration-api/system-overlay.h [new file with mode: 0644]
dali/internal/common/blending-options.cpp [new file with mode: 0644]
dali/internal/common/blending-options.h [new file with mode: 0644]
dali/internal/common/buffer-index.h [new file with mode: 0644]
dali/internal/common/core-impl.cpp [new file with mode: 0644]
dali/internal/common/core-impl.h [new file with mode: 0644]
dali/internal/common/fixed-size-memory-pool.cpp [new file with mode: 0644]
dali/internal/common/fixed-size-memory-pool.h [new file with mode: 0644]
dali/internal/common/image-attributes.cpp [new file with mode: 0644]
dali/internal/common/image-attributes.h [new file with mode: 0644]
dali/internal/common/image-sampler.cpp [new file with mode: 0644]
dali/internal/common/image-sampler.h [new file with mode: 0644]
dali/internal/common/internal-constants.cpp [new file with mode: 0644]
dali/internal/common/internal-constants.h [new file with mode: 0644]
dali/internal/common/memory-pool-object-allocator.h [new file with mode: 0644]
dali/internal/common/message-buffer.cpp [new file with mode: 0644]
dali/internal/common/message-buffer.h [new file with mode: 0644]
dali/internal/common/message.h [new file with mode: 0644]
dali/internal/common/owner-container.h [new file with mode: 0644]
dali/internal/common/owner-pointer.h [new file with mode: 0644]
dali/internal/common/shader-data.h [new file with mode: 0644]
dali/internal/common/shader-saver.h [new file with mode: 0644]
dali/internal/common/text-vertex-2d.h [new file with mode: 0644]
dali/internal/common/type-abstraction-enums.h [new file with mode: 0644]
dali/internal/common/type-abstraction.h [new file with mode: 0644]
dali/internal/event/actor-attachments/actor-attachment-declarations.h [new file with mode: 0644]
dali/internal/event/actor-attachments/actor-attachment-impl.cpp [new file with mode: 0644]
dali/internal/event/actor-attachments/actor-attachment-impl.h [new file with mode: 0644]
dali/internal/event/actor-attachments/camera-attachment-impl.cpp [new file with mode: 0644]
dali/internal/event/actor-attachments/camera-attachment-impl.h [new file with mode: 0644]
dali/internal/event/actor-attachments/image-attachment-impl.cpp [new file with mode: 0644]
dali/internal/event/actor-attachments/image-attachment-impl.h [new file with mode: 0644]
dali/internal/event/actor-attachments/renderable-attachment-impl.cpp [new file with mode: 0644]
dali/internal/event/actor-attachments/renderable-attachment-impl.h [new file with mode: 0644]
dali/internal/event/actor-attachments/renderer-attachment-impl.cpp [new file with mode: 0644]
dali/internal/event/actor-attachments/renderer-attachment-impl.h [new file with mode: 0644]
dali/internal/event/actors/actor-declarations.h [new file with mode: 0644]
dali/internal/event/actors/actor-impl.cpp [new file with mode: 0644]
dali/internal/event/actors/actor-impl.h [new file with mode: 0644]
dali/internal/event/actors/camera-actor-impl.cpp [new file with mode: 0644]
dali/internal/event/actors/camera-actor-impl.h [new file with mode: 0644]
dali/internal/event/actors/custom-actor-internal.cpp [new file with mode: 0644]
dali/internal/event/actors/custom-actor-internal.h [new file with mode: 0644]
dali/internal/event/actors/image-actor-impl.cpp [new file with mode: 0644]
dali/internal/event/actors/image-actor-impl.h [new file with mode: 0644]
dali/internal/event/actors/layer-impl.cpp [new file with mode: 0644]
dali/internal/event/actors/layer-impl.h [new file with mode: 0644]
dali/internal/event/actors/layer-list.cpp [new file with mode: 0644]
dali/internal/event/actors/layer-list.h [new file with mode: 0644]
dali/internal/event/animation/animation-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/animation-impl.h [new file with mode: 0644]
dali/internal/event/animation/animation-playlist-declarations.h [new file with mode: 0644]
dali/internal/event/animation/animation-playlist.cpp [new file with mode: 0644]
dali/internal/event/animation/animation-playlist.h [new file with mode: 0644]
dali/internal/event/animation/animator-connector-base.h [new file with mode: 0644]
dali/internal/event/animation/animator-connector.h [new file with mode: 0644]
dali/internal/event/animation/constrainer.cpp [new file with mode: 0644]
dali/internal/event/animation/constrainer.h [new file with mode: 0644]
dali/internal/event/animation/constraint-base.cpp [new file with mode: 0644]
dali/internal/event/animation/constraint-base.h [new file with mode: 0644]
dali/internal/event/animation/constraint-impl.h [new file with mode: 0644]
dali/internal/event/animation/constraint-source-impl.h [new file with mode: 0644]
dali/internal/event/animation/key-frame-channel.h [new file with mode: 0644]
dali/internal/event/animation/key-frames-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/key-frames-impl.h [new file with mode: 0644]
dali/internal/event/animation/linear-constrainer-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/linear-constrainer-impl.h [new file with mode: 0644]
dali/internal/event/animation/path-constrainer-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/path-constrainer-impl.h [new file with mode: 0644]
dali/internal/event/animation/path-impl.cpp [new file with mode: 0644]
dali/internal/event/animation/path-impl.h [new file with mode: 0644]
dali/internal/event/animation/progress-value.h [new file with mode: 0644]
dali/internal/event/animation/property-constraint-ptr.h [new file with mode: 0644]
dali/internal/event/animation/property-constraint.h [new file with mode: 0644]
dali/internal/event/animation/property-input-accessor.h [new file with mode: 0644]
dali/internal/event/animation/property-input-indexer.h [new file with mode: 0644]
dali/internal/event/common/complete-notification-interface.h [new file with mode: 0644]
dali/internal/event/common/connectable.h [new file with mode: 0644]
dali/internal/event/common/demangler.cpp [new file with mode: 0644]
dali/internal/event/common/demangler.h [new file with mode: 0644]
dali/internal/event/common/event-thread-services.cpp [new file with mode: 0644]
dali/internal/event/common/event-thread-services.h [new file with mode: 0644]
dali/internal/event/common/notification-manager.cpp [new file with mode: 0644]
dali/internal/event/common/notification-manager.h [new file with mode: 0644]
dali/internal/event/common/object-connector.h [new file with mode: 0644]
dali/internal/event/common/object-impl-helper.h [new file with mode: 0644]
dali/internal/event/common/object-impl.cpp [new file with mode: 0644]
dali/internal/event/common/object-impl.h [new file with mode: 0644]
dali/internal/event/common/object-registry-impl.cpp [new file with mode: 0644]
dali/internal/event/common/object-registry-impl.h [new file with mode: 0644]
dali/internal/event/common/projection.cpp [new file with mode: 0644]
dali/internal/event/common/projection.h [new file with mode: 0644]
dali/internal/event/common/property-buffer-impl.cpp [new file with mode: 0644]
dali/internal/event/common/property-buffer-impl.h [new file with mode: 0644]
dali/internal/event/common/property-conditions-impl.cpp [new file with mode: 0644]
dali/internal/event/common/property-conditions-impl.h [new file with mode: 0644]
dali/internal/event/common/property-helper.h [new file with mode: 0644]
dali/internal/event/common/property-input-impl.h [new file with mode: 0644]
dali/internal/event/common/property-metadata.h [new file with mode: 0644]
dali/internal/event/common/property-notification-impl.cpp [new file with mode: 0644]
dali/internal/event/common/property-notification-impl.h [new file with mode: 0644]
dali/internal/event/common/property-notification-manager.cpp [new file with mode: 0644]
dali/internal/event/common/property-notification-manager.h [new file with mode: 0644]
dali/internal/event/common/property-notifier.h [new file with mode: 0644]
dali/internal/event/common/stage-def.h [new file with mode: 0644]
dali/internal/event/common/stage-impl.cpp [new file with mode: 0644]
dali/internal/event/common/stage-impl.h [new file with mode: 0644]
dali/internal/event/common/system-overlay-impl.cpp [new file with mode: 0644]
dali/internal/event/common/system-overlay-impl.h [new file with mode: 0644]
dali/internal/event/common/thread-local-storage.cpp [new file with mode: 0644]
dali/internal/event/common/thread-local-storage.h [new file with mode: 0644]
dali/internal/event/common/type-info-impl.cpp [new file with mode: 0644]
dali/internal/event/common/type-info-impl.h [new file with mode: 0644]
dali/internal/event/common/type-registry-impl.cpp [new file with mode: 0644]
dali/internal/event/common/type-registry-impl.h [new file with mode: 0644]
dali/internal/event/effects/shader-declarations.h [new file with mode: 0644]
dali/internal/event/effects/shader-effect-impl.cpp [new file with mode: 0644]
dali/internal/event/effects/shader-effect-impl.h [new file with mode: 0644]
dali/internal/event/effects/shader-factory.cpp [new file with mode: 0644]
dali/internal/event/effects/shader-factory.h [new file with mode: 0644]
dali/internal/event/events/actor-gesture-data.cpp [new file with mode: 0644]
dali/internal/event/events/actor-gesture-data.h [new file with mode: 0644]
dali/internal/event/events/actor-observer.cpp [new file with mode: 0644]
dali/internal/event/events/actor-observer.h [new file with mode: 0644]
dali/internal/event/events/event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/event-processor.h [new file with mode: 0644]
dali/internal/event/events/gesture-detector-impl.cpp [new file with mode: 0644]
dali/internal/event/events/gesture-detector-impl.h [new file with mode: 0644]
dali/internal/event/events/gesture-event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/gesture-event-processor.h [new file with mode: 0644]
dali/internal/event/events/gesture-processor.cpp [new file with mode: 0644]
dali/internal/event/events/gesture-processor.h [new file with mode: 0644]
dali/internal/event/events/hit-test-algorithm-impl.cpp [new file with mode: 0644]
dali/internal/event/events/hit-test-algorithm-impl.h [new file with mode: 0644]
dali/internal/event/events/hover-event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/hover-event-processor.h [new file with mode: 0644]
dali/internal/event/events/key-event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/key-event-processor.h [new file with mode: 0644]
dali/internal/event/events/long-press-gesture-detector-impl.cpp [new file with mode: 0644]
dali/internal/event/events/long-press-gesture-detector-impl.h [new file with mode: 0644]
dali/internal/event/events/long-press-gesture-processor.cpp [new file with mode: 0644]
dali/internal/event/events/long-press-gesture-processor.h [new file with mode: 0644]
dali/internal/event/events/multi-point-event-util.cpp [new file with mode: 0644]
dali/internal/event/events/multi-point-event-util.h [new file with mode: 0644]
dali/internal/event/events/pan-gesture-detector-impl.cpp [new file with mode: 0644]
dali/internal/event/events/pan-gesture-detector-impl.h [new file with mode: 0644]
dali/internal/event/events/pan-gesture-processor.cpp [new file with mode: 0644]
dali/internal/event/events/pan-gesture-processor.h [new file with mode: 0644]
dali/internal/event/events/pinch-gesture-detector-impl.cpp [new file with mode: 0644]
dali/internal/event/events/pinch-gesture-detector-impl.h [new file with mode: 0644]
dali/internal/event/events/pinch-gesture-processor.cpp [new file with mode: 0644]
dali/internal/event/events/pinch-gesture-processor.h [new file with mode: 0644]
dali/internal/event/events/tap-gesture-detector-impl.cpp [new file with mode: 0644]
dali/internal/event/events/tap-gesture-detector-impl.h [new file with mode: 0644]
dali/internal/event/events/tap-gesture-processor.cpp [new file with mode: 0644]
dali/internal/event/events/tap-gesture-processor.h [new file with mode: 0644]
dali/internal/event/events/touch-event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/touch-event-processor.h [new file with mode: 0644]
dali/internal/event/events/wheel-event-processor.cpp [new file with mode: 0644]
dali/internal/event/events/wheel-event-processor.h [new file with mode: 0644]
dali/internal/event/images/atlas-impl.cpp [new file with mode: 0644]
dali/internal/event/images/atlas-impl.h [new file with mode: 0644]
dali/internal/event/images/bitmap-compressed.cpp [new file with mode: 0644]
dali/internal/event/images/bitmap-compressed.h [new file with mode: 0644]
dali/internal/event/images/bitmap-external.cpp [new file with mode: 0644]
dali/internal/event/images/bitmap-external.h [new file with mode: 0644]
dali/internal/event/images/bitmap-packed-pixel.cpp [new file with mode: 0644]
dali/internal/event/images/bitmap-packed-pixel.h [new file with mode: 0644]
dali/internal/event/images/buffer-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/buffer-image-impl.h [new file with mode: 0644]
dali/internal/event/images/context-recovery-interface.h [new file with mode: 0644]
dali/internal/event/images/encoded-buffer-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/encoded-buffer-image-impl.h [new file with mode: 0644]
dali/internal/event/images/frame-buffer-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/frame-buffer-image-impl.h [new file with mode: 0644]
dali/internal/event/images/image-connector.cpp [new file with mode: 0644]
dali/internal/event/images/image-connector.h [new file with mode: 0644]
dali/internal/event/images/image-factory-cache.cpp [new file with mode: 0644]
dali/internal/event/images/image-factory-cache.h [new file with mode: 0644]
dali/internal/event/images/image-factory.cpp [new file with mode: 0644]
dali/internal/event/images/image-factory.h [new file with mode: 0644]
dali/internal/event/images/image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/image-impl.h [new file with mode: 0644]
dali/internal/event/images/native-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/native-image-impl.h [new file with mode: 0644]
dali/internal/event/images/nine-patch-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/nine-patch-image-impl.h [new file with mode: 0644]
dali/internal/event/images/resource-image-impl.cpp [new file with mode: 0644]
dali/internal/event/images/resource-image-impl.h [new file with mode: 0644]
dali/internal/event/object/custom-object-internal.cpp [new file with mode: 0644]
dali/internal/event/object/custom-object-internal.h [new file with mode: 0644]
dali/internal/event/render-tasks/render-task-defaults.h [new file with mode: 0644]
dali/internal/event/render-tasks/render-task-impl.cpp [new file with mode: 0644]
dali/internal/event/render-tasks/render-task-impl.h [new file with mode: 0644]
dali/internal/event/render-tasks/render-task-list-impl.cpp [new file with mode: 0644]
dali/internal/event/render-tasks/render-task-list-impl.h [new file with mode: 0644]
dali/internal/event/rendering/geometry-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/geometry-impl.h [new file with mode: 0644]
dali/internal/event/rendering/material-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/material-impl.h [new file with mode: 0644]
dali/internal/event/rendering/renderer-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/renderer-impl.h [new file with mode: 0644]
dali/internal/event/rendering/sampler-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/sampler-impl.h [new file with mode: 0644]
dali/internal/event/rendering/shader-impl.cpp [new file with mode: 0644]
dali/internal/event/rendering/shader-impl.h [new file with mode: 0644]
dali/internal/event/resources/archive.cpp [new file with mode: 0644]
dali/internal/event/resources/archive.h [new file with mode: 0644]
dali/internal/event/resources/image-ticket.cpp [new file with mode: 0644]
dali/internal/event/resources/image-ticket.h [new file with mode: 0644]
dali/internal/event/resources/resource-client-declarations.h [new file with mode: 0644]
dali/internal/event/resources/resource-client.cpp [new file with mode: 0644]
dali/internal/event/resources/resource-client.h [new file with mode: 0644]
dali/internal/event/resources/resource-ticket-lifetime-observer.h [new file with mode: 0644]
dali/internal/event/resources/resource-ticket-observer.h [new file with mode: 0644]
dali/internal/event/resources/resource-ticket.cpp [new file with mode: 0644]
dali/internal/event/resources/resource-ticket.h [new file with mode: 0644]
dali/internal/event/resources/resource-type-path.cpp [new file with mode: 0644]
dali/internal/event/resources/resource-type-path.h [new file with mode: 0644]
dali/internal/event/size-negotiation/memory-pool-relayout-container.cpp [new file with mode: 0644]
dali/internal/event/size-negotiation/memory-pool-relayout-container.h [new file with mode: 0644]
dali/internal/event/size-negotiation/relayout-controller-impl.cpp [new file with mode: 0644]
dali/internal/event/size-negotiation/relayout-controller-impl.h [new file with mode: 0644]
dali/internal/file.list [new file with mode: 0644]
dali/internal/render/common/culling-algorithms.cpp [new file with mode: 0644]
dali/internal/render/common/culling-algorithms.h [new file with mode: 0644]
dali/internal/render/common/performance-monitor.h [new file with mode: 0644]
dali/internal/render/common/post-process-resource-dispatcher.h [new file with mode: 0644]
dali/internal/render/common/render-algorithms.cpp [new file with mode: 0644]
dali/internal/render/common/render-algorithms.h [new file with mode: 0644]
dali/internal/render/common/render-debug.cpp [new file with mode: 0644]
dali/internal/render/common/render-debug.h [new file with mode: 0644]
dali/internal/render/common/render-instruction-container.cpp [new file with mode: 0644]
dali/internal/render/common/render-instruction-container.h [new file with mode: 0644]
dali/internal/render/common/render-instruction.cpp [new file with mode: 0644]
dali/internal/render/common/render-instruction.h [new file with mode: 0644]
dali/internal/render/common/render-item.cpp [new file with mode: 0644]
dali/internal/render/common/render-item.h [new file with mode: 0644]
dali/internal/render/common/render-list.h [new file with mode: 0644]
dali/internal/render/common/render-manager.cpp [new file with mode: 0644]
dali/internal/render/common/render-manager.h [new file with mode: 0644]
dali/internal/render/common/render-tracker-debug.h [new file with mode: 0644]
dali/internal/render/common/render-tracker.cpp [new file with mode: 0644]
dali/internal/render/common/render-tracker.h [new file with mode: 0644]
dali/internal/render/common/rendering-types.h [new file with mode: 0644]
dali/internal/render/common/texture-cache-dispatcher.cpp [new file with mode: 0644]
dali/internal/render/common/texture-cache-dispatcher.h [new file with mode: 0644]
dali/internal/render/common/uv-rect.h [new file with mode: 0644]
dali/internal/render/common/vertex.h [new file with mode: 0644]
dali/internal/render/data-providers/geometry-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/material-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/node-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/property-buffer-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/render-data-provider.cpp [new file with mode: 0644]
dali/internal/render/data-providers/render-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/sampler-data-provider.h [new file with mode: 0644]
dali/internal/render/data-providers/uniform-map-data-provider.h [new file with mode: 0644]
dali/internal/render/gl-resources/bitmap-texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/bitmap-texture.h [new file with mode: 0644]
dali/internal/render/gl-resources/compressed-bitmap-texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/compressed-bitmap-texture.h [new file with mode: 0644]
dali/internal/render/gl-resources/context.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/context.h [new file with mode: 0644]
dali/internal/render/gl-resources/frame-buffer-state-cache.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/frame-buffer-state-cache.h [new file with mode: 0644]
dali/internal/render/gl-resources/frame-buffer-texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/frame-buffer-texture.h [new file with mode: 0644]
dali/internal/render/gl-resources/gl-call-debug.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/gl-call-debug.h [new file with mode: 0644]
dali/internal/render/gl-resources/gl-resource-owner.h [new file with mode: 0644]
dali/internal/render/gl-resources/gpu-buffer.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/gpu-buffer.h [new file with mode: 0644]
dali/internal/render/gl-resources/native-frame-buffer-texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/native-frame-buffer-texture.h [new file with mode: 0644]
dali/internal/render/gl-resources/native-texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/native-texture.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture-cache.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/texture-cache.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture-declarations.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture-factory.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/texture-factory.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture-observer.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture-units.h [new file with mode: 0644]
dali/internal/render/gl-resources/texture.cpp [new file with mode: 0644]
dali/internal/render/gl-resources/texture.h [new file with mode: 0644]
dali/internal/render/queue/render-queue.cpp [new file with mode: 0644]
dali/internal/render/queue/render-queue.h [new file with mode: 0644]
dali/internal/render/renderers/render-geometry.cpp [new file with mode: 0644]
dali/internal/render/renderers/render-geometry.h [new file with mode: 0644]
dali/internal/render/renderers/render-renderer-property-buffer.cpp [new file with mode: 0644]
dali/internal/render/renderers/render-renderer-property-buffer.h [new file with mode: 0644]
dali/internal/render/renderers/render-renderer.cpp [new file with mode: 0644]
dali/internal/render/renderers/render-renderer.h [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-image-renderer.cpp [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-image-renderer.h [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer-debug.cpp [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer-debug.h [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer-declarations.h [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer.cpp [new file with mode: 0644]
dali/internal/render/renderers/scene-graph-renderer.h [new file with mode: 0644]
dali/internal/render/shader-source/README [new file with mode: 0644]
dali/internal/render/shader-source/image.txt [new file with mode: 0644]
dali/internal/render/shaders/custom-uniform.cpp [new file with mode: 0644]
dali/internal/render/shaders/custom-uniform.h [new file with mode: 0644]
dali/internal/render/shaders/program-cache.h [new file with mode: 0644]
dali/internal/render/shaders/program-controller.cpp [new file with mode: 0644]
dali/internal/render/shaders/program-controller.h [new file with mode: 0644]
dali/internal/render/shaders/program.cpp [new file with mode: 0644]
dali/internal/render/shaders/program.h [new file with mode: 0644]
dali/internal/render/shaders/scene-graph-shader.cpp [new file with mode: 0644]
dali/internal/render/shaders/scene-graph-shader.h [new file with mode: 0644]
dali/internal/render/shaders/uniform-meta.h [new file with mode: 0644]
dali/internal/update/animation/property-accessor.h [new file with mode: 0644]
dali/internal/update/animation/property-component-accessor.h [new file with mode: 0644]
dali/internal/update/animation/scene-graph-animation.cpp [new file with mode: 0644]
dali/internal/update/animation/scene-graph-animation.h [new file with mode: 0644]
dali/internal/update/animation/scene-graph-animator.h [new file with mode: 0644]
dali/internal/update/animation/scene-graph-constraint-base.cpp [new file with mode: 0644]
dali/internal/update/animation/scene-graph-constraint-base.h [new file with mode: 0644]
dali/internal/update/animation/scene-graph-constraint-declarations.h [new file with mode: 0644]
dali/internal/update/animation/scene-graph-constraint.h [new file with mode: 0644]
dali/internal/update/common/animatable-property.h [new file with mode: 0644]
dali/internal/update/common/discard-queue.cpp [new file with mode: 0644]
dali/internal/update/common/discard-queue.h [new file with mode: 0644]
dali/internal/update/common/double-buffered-property.h [new file with mode: 0644]
dali/internal/update/common/double-buffered.h [new file with mode: 0644]
dali/internal/update/common/inherited-property.h [new file with mode: 0644]
dali/internal/update/common/property-base.cpp [new file with mode: 0644]
dali/internal/update/common/property-base.h [new file with mode: 0644]
dali/internal/update/common/property-boolean.h [new file with mode: 0644]
dali/internal/update/common/property-condition-functions.cpp [new file with mode: 0644]
dali/internal/update/common/property-condition-functions.h [new file with mode: 0644]
dali/internal/update/common/property-condition-step-functions.cpp [new file with mode: 0644]
dali/internal/update/common/property-condition-step-functions.h [new file with mode: 0644]
dali/internal/update/common/property-condition-variable-step-functions.cpp [new file with mode: 0644]
dali/internal/update/common/property-condition-variable-step-functions.h [new file with mode: 0644]
dali/internal/update/common/property-owner-messages.cpp [new file with mode: 0644]
dali/internal/update/common/property-owner-messages.h [new file with mode: 0644]
dali/internal/update/common/property-owner.cpp [new file with mode: 0644]
dali/internal/update/common/property-owner.h [new file with mode: 0644]
dali/internal/update/common/property-vector3.h [new file with mode: 0644]
dali/internal/update/common/scene-graph-buffers.cpp [new file with mode: 0644]
dali/internal/update/common/scene-graph-buffers.h [new file with mode: 0644]
dali/internal/update/common/scene-graph-connection-change-propagator.cpp [new file with mode: 0644]
dali/internal/update/common/scene-graph-connection-change-propagator.h [new file with mode: 0644]
dali/internal/update/common/scene-graph-property-buffer.cpp [new file with mode: 0644]
dali/internal/update/common/scene-graph-property-buffer.h [new file with mode: 0644]
dali/internal/update/common/scene-graph-property-notification.cpp [new file with mode: 0644]
dali/internal/update/common/scene-graph-property-notification.h [new file with mode: 0644]
dali/internal/update/common/uniform-map.cpp [new file with mode: 0644]
dali/internal/update/common/uniform-map.h [new file with mode: 0644]
dali/internal/update/controllers/render-message-dispatcher.cpp [new file with mode: 0644]
dali/internal/update/controllers/render-message-dispatcher.h [new file with mode: 0644]
dali/internal/update/controllers/scene-controller-impl.cpp [new file with mode: 0644]
dali/internal/update/controllers/scene-controller-impl.h [new file with mode: 0644]
dali/internal/update/controllers/scene-controller.h [new file with mode: 0644]
dali/internal/update/gestures/gesture-properties.h [new file with mode: 0644]
dali/internal/update/gestures/pan-gesture-profiling.cpp [new file with mode: 0644]
dali/internal/update/gestures/pan-gesture-profiling.h [new file with mode: 0644]
dali/internal/update/gestures/scene-graph-pan-gesture.cpp [new file with mode: 0644]
dali/internal/update/gestures/scene-graph-pan-gesture.h [new file with mode: 0644]
dali/internal/update/manager/object-owner-container.h [new file with mode: 0644]
dali/internal/update/manager/prepare-render-algorithms.cpp [new file with mode: 0644]
dali/internal/update/manager/prepare-render-algorithms.h [new file with mode: 0644]
dali/internal/update/manager/prepare-render-instructions.cpp [new file with mode: 0644]
dali/internal/update/manager/prepare-render-instructions.h [new file with mode: 0644]
dali/internal/update/manager/process-render-tasks.cpp [new file with mode: 0644]
dali/internal/update/manager/process-render-tasks.h [new file with mode: 0644]
dali/internal/update/manager/sorted-layers.h [new file with mode: 0644]
dali/internal/update/manager/update-algorithms.cpp [new file with mode: 0644]
dali/internal/update/manager/update-algorithms.h [new file with mode: 0644]
dali/internal/update/manager/update-manager-debug.cpp [new file with mode: 0644]
dali/internal/update/manager/update-manager-debug.h [new file with mode: 0644]
dali/internal/update/manager/update-manager.cpp [new file with mode: 0644]
dali/internal/update/manager/update-manager.h [new file with mode: 0644]
dali/internal/update/node-attachments/node-attachment-declarations.h [new file with mode: 0644]
dali/internal/update/node-attachments/node-attachment.cpp [new file with mode: 0644]
dali/internal/update/node-attachments/node-attachment.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-camera-attachment.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-image-attachment.cpp [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-image-attachment.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-renderable-attachment-declarations.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-renderable-attachment.cpp [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-renderable-attachment.h [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp [new file with mode: 0644]
dali/internal/update/node-attachments/scene-graph-renderer-attachment.h [new file with mode: 0644]
dali/internal/update/nodes/node-declarations.h [new file with mode: 0644]
dali/internal/update/nodes/node-messages.cpp [new file with mode: 0644]
dali/internal/update/nodes/node-messages.h [new file with mode: 0644]
dali/internal/update/nodes/node.cpp [new file with mode: 0644]
dali/internal/update/nodes/node.h [new file with mode: 0644]
dali/internal/update/nodes/scene-graph-layer.cpp [new file with mode: 0644]
dali/internal/update/nodes/scene-graph-layer.h [new file with mode: 0644]
dali/internal/update/queue/update-message-queue.cpp [new file with mode: 0644]
dali/internal/update/queue/update-message-queue.h [new file with mode: 0644]
dali/internal/update/render-tasks/scene-graph-render-task-debug.h [new file with mode: 0644]
dali/internal/update/render-tasks/scene-graph-render-task-list.cpp [new file with mode: 0644]
dali/internal/update/render-tasks/scene-graph-render-task-list.h [new file with mode: 0644]
dali/internal/update/render-tasks/scene-graph-render-task.cpp [new file with mode: 0644]
dali/internal/update/render-tasks/scene-graph-render-task.h [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-geometry.cpp [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-geometry.h [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-material.cpp [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-material.h [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-sampler.cpp [new file with mode: 0644]
dali/internal/update/rendering/scene-graph-sampler.h [new file with mode: 0644]
dali/internal/update/resources/bitmap-metadata.cpp [new file with mode: 0644]
dali/internal/update/resources/bitmap-metadata.h [new file with mode: 0644]
dali/internal/update/resources/complete-status-manager-debug.h [new file with mode: 0644]
dali/internal/update/resources/complete-status-manager.cpp [new file with mode: 0644]
dali/internal/update/resources/complete-status-manager.h [new file with mode: 0644]
dali/internal/update/resources/resource-manager-declarations.h [new file with mode: 0644]
dali/internal/update/resources/resource-manager.cpp [new file with mode: 0644]
dali/internal/update/resources/resource-manager.h [new file with mode: 0644]
dali/internal/update/resources/resource-tracker-debug.h [new file with mode: 0644]
dali/internal/update/resources/resource-tracker.cpp [new file with mode: 0644]
dali/internal/update/resources/resource-tracker.h [new file with mode: 0644]
dali/internal/update/resources/sync-resource-tracker.cpp [new file with mode: 0644]
dali/internal/update/resources/sync-resource-tracker.h [new file with mode: 0644]
dali/internal/update/touch/history.h [new file with mode: 0644]
dali/internal/update/touch/touch-resampler.cpp [new file with mode: 0644]
dali/internal/update/touch/touch-resampler.h [new file with mode: 0644]
dali/public-api/actors/actor-enumerations.h [new file with mode: 0644]
dali/public-api/actors/actor.cpp [new file with mode: 0644]
dali/public-api/actors/actor.h [new file with mode: 0644]
dali/public-api/actors/blending.cpp [new file with mode: 0644]
dali/public-api/actors/blending.h [new file with mode: 0644]
dali/public-api/actors/camera-actor.cpp [new file with mode: 0644]
dali/public-api/actors/camera-actor.h [new file with mode: 0644]
dali/public-api/actors/custom-actor-impl.cpp [new file with mode: 0644]
dali/public-api/actors/custom-actor-impl.h [new file with mode: 0644]
dali/public-api/actors/custom-actor.cpp [new file with mode: 0644]
dali/public-api/actors/custom-actor.h [new file with mode: 0644]
dali/public-api/actors/draw-mode.h [new file with mode: 0644]
dali/public-api/actors/image-actor.cpp [new file with mode: 0644]
dali/public-api/actors/image-actor.h [new file with mode: 0644]
dali/public-api/actors/layer.cpp [new file with mode: 0644]
dali/public-api/actors/layer.h [new file with mode: 0644]
dali/public-api/actors/sampling.h [new file with mode: 0644]
dali/public-api/animation/alpha-function.cpp [new file with mode: 0644]
dali/public-api/animation/alpha-function.h [new file with mode: 0644]
dali/public-api/animation/animation.cpp [new file with mode: 0644]
dali/public-api/animation/animation.h [new file with mode: 0644]
dali/public-api/animation/constraint-source.cpp [new file with mode: 0644]
dali/public-api/animation/constraint-source.h [new file with mode: 0644]
dali/public-api/animation/constraint.cpp [new file with mode: 0644]
dali/public-api/animation/constraint.h [new file with mode: 0644]
dali/public-api/animation/constraints.h [new file with mode: 0644]
dali/public-api/animation/key-frames.cpp [new file with mode: 0644]
dali/public-api/animation/key-frames.h [new file with mode: 0644]
dali/public-api/animation/linear-constrainer.cpp [new file with mode: 0644]
dali/public-api/animation/linear-constrainer.h [new file with mode: 0644]
dali/public-api/animation/path.cpp [new file with mode: 0644]
dali/public-api/animation/path.h [new file with mode: 0644]
dali/public-api/animation/time-period.cpp [new file with mode: 0644]
dali/public-api/animation/time-period.h [new file with mode: 0644]
dali/public-api/common/compile-time-assert.h [new file with mode: 0644]
dali/public-api/common/constants.cpp [new file with mode: 0644]
dali/public-api/common/constants.h [new file with mode: 0644]
dali/public-api/common/dali-common.cpp [new file with mode: 0644]
dali/public-api/common/dali-common.h [new file with mode: 0644]
dali/public-api/common/dali-vector.cpp [new file with mode: 0644]
dali/public-api/common/dali-vector.h [new file with mode: 0644]
dali/public-api/common/intrusive-ptr.h [new file with mode: 0644]
dali/public-api/common/loading-state.h [new file with mode: 0644]
dali/public-api/common/stage.cpp [new file with mode: 0644]
dali/public-api/common/stage.h [new file with mode: 0644]
dali/public-api/common/type-traits.h [new file with mode: 0644]
dali/public-api/common/vector-wrapper.h [new file with mode: 0644]
dali/public-api/common/view-mode.h [new file with mode: 0644]
dali/public-api/dali-core-version.cpp [new file with mode: 0644]
dali/public-api/dali-core-version.h [new file with mode: 0644]
dali/public-api/dali-core.h [new file with mode: 0644]
dali/public-api/events/gesture-detector.cpp [new file with mode: 0644]
dali/public-api/events/gesture-detector.h [new file with mode: 0644]
dali/public-api/events/gesture.cpp [new file with mode: 0644]
dali/public-api/events/gesture.h [new file with mode: 0644]
dali/public-api/events/hover-event.cpp [new file with mode: 0644]
dali/public-api/events/hover-event.h [new file with mode: 0644]
dali/public-api/events/key-event.cpp [new file with mode: 0644]
dali/public-api/events/key-event.h [new file with mode: 0644]
dali/public-api/events/long-press-gesture-detector.cpp [new file with mode: 0644]
dali/public-api/events/long-press-gesture-detector.h [new file with mode: 0644]
dali/public-api/events/long-press-gesture.cpp [new file with mode: 0644]
dali/public-api/events/long-press-gesture.h [new file with mode: 0644]
dali/public-api/events/pan-gesture-detector.cpp [new file with mode: 0644]
dali/public-api/events/pan-gesture-detector.h [new file with mode: 0644]
dali/public-api/events/pan-gesture.cpp [new file with mode: 0644]
dali/public-api/events/pan-gesture.h [new file with mode: 0644]
dali/public-api/events/pinch-gesture-detector.cpp [new file with mode: 0644]
dali/public-api/events/pinch-gesture-detector.h [new file with mode: 0644]
dali/public-api/events/pinch-gesture.cpp [new file with mode: 0644]
dali/public-api/events/pinch-gesture.h [new file with mode: 0644]
dali/public-api/events/tap-gesture-detector.cpp [new file with mode: 0644]
dali/public-api/events/tap-gesture-detector.h [new file with mode: 0644]
dali/public-api/events/tap-gesture.cpp [new file with mode: 0644]
dali/public-api/events/tap-gesture.h [new file with mode: 0644]
dali/public-api/events/touch-event.cpp [new file with mode: 0644]
dali/public-api/events/touch-event.h [new file with mode: 0644]
dali/public-api/events/touch-point.cpp [new file with mode: 0644]
dali/public-api/events/touch-point.h [new file with mode: 0644]
dali/public-api/events/wheel-event.cpp [new file with mode: 0644]
dali/public-api/events/wheel-event.h [new file with mode: 0644]
dali/public-api/file.list [new file with mode: 0644]
dali/public-api/images/buffer-image.cpp [new file with mode: 0644]
dali/public-api/images/buffer-image.h [new file with mode: 0644]
dali/public-api/images/encoded-buffer-image.cpp [new file with mode: 0644]
dali/public-api/images/encoded-buffer-image.h [new file with mode: 0644]
dali/public-api/images/frame-buffer-image.cpp [new file with mode: 0644]
dali/public-api/images/frame-buffer-image.h [new file with mode: 0644]
dali/public-api/images/image-operations.h [new file with mode: 0644]
dali/public-api/images/image.cpp [new file with mode: 0644]
dali/public-api/images/image.h [new file with mode: 0644]
dali/public-api/images/native-image-interface.h [new file with mode: 0644]
dali/public-api/images/native-image.cpp [new file with mode: 0644]
dali/public-api/images/native-image.h [new file with mode: 0644]
dali/public-api/images/nine-patch-image.cpp [new file with mode: 0644]
dali/public-api/images/nine-patch-image.h [new file with mode: 0644]
dali/public-api/images/pixel.cpp [new file with mode: 0644]
dali/public-api/images/pixel.h [new file with mode: 0644]
dali/public-api/images/resource-image.cpp [new file with mode: 0644]
dali/public-api/images/resource-image.h [new file with mode: 0644]
dali/public-api/math/angle-axis.h [new file with mode: 0644]
dali/public-api/math/compile-time-math.cpp [new file with mode: 0644]
dali/public-api/math/compile-time-math.h [new file with mode: 0644]
dali/public-api/math/degree.cpp [new file with mode: 0644]
dali/public-api/math/degree.h [new file with mode: 0644]
dali/public-api/math/math-utils.h [new file with mode: 0644]
dali/public-api/math/matrix.cpp [new file with mode: 0644]
dali/public-api/math/matrix.h [new file with mode: 0644]
dali/public-api/math/matrix3.cpp [new file with mode: 0644]
dali/public-api/math/matrix3.h [new file with mode: 0644]
dali/public-api/math/quaternion.cpp [new file with mode: 0644]
dali/public-api/math/quaternion.h [new file with mode: 0644]
dali/public-api/math/radian.h [new file with mode: 0644]
dali/public-api/math/random.h [new file with mode: 0644]
dali/public-api/math/rect.h [new file with mode: 0644]
dali/public-api/math/uint-16-pair.h [new file with mode: 0644]
dali/public-api/math/vector2.cpp [new file with mode: 0644]
dali/public-api/math/vector2.h [new file with mode: 0644]
dali/public-api/math/vector3.cpp [new file with mode: 0644]
dali/public-api/math/vector3.h [new file with mode: 0644]
dali/public-api/math/vector4.cpp [new file with mode: 0644]
dali/public-api/math/vector4.h [new file with mode: 0644]
dali/public-api/math/viewport.h [new file with mode: 0644]
dali/public-api/object/any.cpp [new file with mode: 0644]
dali/public-api/object/any.h [new file with mode: 0644]
dali/public-api/object/base-handle.cpp [new file with mode: 0644]
dali/public-api/object/base-handle.h [new file with mode: 0644]
dali/public-api/object/base-object.cpp [new file with mode: 0644]
dali/public-api/object/base-object.h [new file with mode: 0644]
dali/public-api/object/handle.cpp [new file with mode: 0644]
dali/public-api/object/handle.h [new file with mode: 0644]
dali/public-api/object/object-registry.cpp [new file with mode: 0644]
dali/public-api/object/object-registry.h [new file with mode: 0644]
dali/public-api/object/property-array.cpp [new file with mode: 0644]
dali/public-api/object/property-array.h [new file with mode: 0644]
dali/public-api/object/property-conditions.cpp [new file with mode: 0644]
dali/public-api/object/property-conditions.h [new file with mode: 0644]
dali/public-api/object/property-index-ranges.h [new file with mode: 0644]
dali/public-api/object/property-input.cpp [new file with mode: 0644]
dali/public-api/object/property-input.h [new file with mode: 0644]
dali/public-api/object/property-map.cpp [new file with mode: 0644]
dali/public-api/object/property-map.h [new file with mode: 0644]
dali/public-api/object/property-notification-declarations.h [new file with mode: 0644]
dali/public-api/object/property-notification.cpp [new file with mode: 0644]
dali/public-api/object/property-notification.h [new file with mode: 0644]
dali/public-api/object/property-types.cpp [new file with mode: 0644]
dali/public-api/object/property-types.h [new file with mode: 0644]
dali/public-api/object/property-value.cpp [new file with mode: 0644]
dali/public-api/object/property-value.h [new file with mode: 0644]
dali/public-api/object/property.cpp [new file with mode: 0644]
dali/public-api/object/property.h [new file with mode: 0644]
dali/public-api/object/ref-object.cpp [new file with mode: 0644]
dali/public-api/object/ref-object.h [new file with mode: 0644]
dali/public-api/object/type-info.cpp [new file with mode: 0644]
dali/public-api/object/type-info.h [new file with mode: 0644]
dali/public-api/object/type-registry.cpp [new file with mode: 0644]
dali/public-api/object/type-registry.h [new file with mode: 0644]
dali/public-api/render-tasks/render-task-list.cpp [new file with mode: 0644]
dali/public-api/render-tasks/render-task-list.h [new file with mode: 0644]
dali/public-api/render-tasks/render-task.cpp [new file with mode: 0644]
dali/public-api/render-tasks/render-task.h [new file with mode: 0644]
dali/public-api/shader-effects/shader-effect.cpp [new file with mode: 0644]
dali/public-api/shader-effects/shader-effect.h [new file with mode: 0644]
dali/public-api/signals/base-signal.cpp [new file with mode: 0644]
dali/public-api/signals/base-signal.h [new file with mode: 0644]
dali/public-api/signals/callback.cpp [new file with mode: 0644]
dali/public-api/signals/callback.h [new file with mode: 0644]
dali/public-api/signals/connection-tracker-interface.cpp [new file with mode: 0644]
dali/public-api/signals/connection-tracker-interface.h [new file with mode: 0644]
dali/public-api/signals/connection-tracker.cpp [new file with mode: 0644]
dali/public-api/signals/connection-tracker.h [new file with mode: 0644]
dali/public-api/signals/dali-signal.h [new file with mode: 0644]
dali/public-api/signals/functor-delegate.cpp [new file with mode: 0644]
dali/public-api/signals/functor-delegate.h [new file with mode: 0644]
dali/public-api/signals/signal-slot-connections.cpp [new file with mode: 0644]
dali/public-api/signals/signal-slot-connections.h [new file with mode: 0644]
dali/public-api/signals/signal-slot-observers.cpp [new file with mode: 0644]
dali/public-api/signals/signal-slot-observers.h [new file with mode: 0644]
dali/public-api/signals/slot-delegate.h [new file with mode: 0644]
dali/public-api/size-negotiation/relayout-container.h [new file with mode: 0644]
doc/dali_doc.h [new file with mode: 0644]
docs/README [new file with mode: 0644]
docs/api_footer.html [new file with mode: 0644]
docs/coding-convention.html [new file with mode: 0644]
docs/coding-style.html [new file with mode: 0644]
docs/dali_internal.doxy [new file with mode: 0644]
docs/templates/example-class-internal.cpp [new file with mode: 0644]
docs/templates/example-class-internal.h [new file with mode: 0644]
packaging/dali.spec [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..caf34e7
--- /dev/null
@@ -0,0 +1,39 @@
+.cproject
+.project
+.settings
+.directory
+Makefile.in
+Makefile
+BROWSE
+*~
+*.pc
+*.o
+*.o.d
+*.lo
+*.loT
+*.la
+*.so
+*.orig
+*.odt
+*.fodt
+*.test
+*.example
+*.a
+*.apk
+*.ap_
+*.class
+*.classpath
+*.dex
+*.gcno
+*.gcda
+*.gcov
+.deps
+.libs
+*.swp
+*.creator
+*.creator.user
+/docs/generated/*
+/build/tizen/doc
+/build/tizen/.cov
+/build/desktop
+/packaging/home*
diff --git a/LICENSE b/LICENSE
new file mode 100644 (file)
index 0000000..dc0510e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,70 @@
+Apache License
+
+Version 2.0, January 2004
+
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+You must give any other recipients of the Work or Derivative Works a copy of this License; and
+You must cause any modified files to carry prominent notices stating that You changed the files; and
+You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
\ No newline at end of file
diff --git a/README b/README
new file mode 100644 (file)
index 0000000..d6d395a
--- /dev/null
+++ b/README
@@ -0,0 +1,75 @@
+T.O.C.
+======
+
+ 1.   GBS Builds
+ 1.1. NON-SMACK Targets
+ 1.2. SMACK enabled Targets
+ 2.   Building for Ubuntu desktop
+ 2.1. Minimum Requirements
+ 2.2. Creating a DALi Environment
+ 2.3. Building the Repository
+
+
+
+1. GBS Builds
+=============
+
+1.1. NON-SMACK Targets
+----------------------
+
+ gbs build -A [TARGET_ARCH]
+
+1.2. SMACK enabled Targets
+--------------------------
+
+ gbs build -A [TARGET_ARCH] --define "%enable_dali_smack_rules 1"
+
+
+
+2. Building for Ubuntu desktop
+==============================
+
+2.1. Minimum Requirements
+------------------------
+
+ - Ubuntu 14.04
+
+2.2. Creating a DALi Environment
+-------------------------------
+
+To build for desktop first ensure ALL sources are selected:
+ - Go to Ubuntu Settings and then to "Software & Updates"
+ - In the "Ubuntu Software" tab, ensure ALL software sources are ticked
+   (This is required because we install some community-maintained free & open-source software)
+
+Then you can create a dali-env folder in your home folder with:
+
+ dali-core/build/scripts/dali_env -c
+
+This will also download any dependencies that the dali repositories require.
+
+You can save the environment variables to a file:
+
+ dali-env/opt/bin/dali_env -s > setenv
+
+This process only needs to be done once.
+
+Next source these variables:
+
+ . setenv
+
+You will have to source these variables every time you open up a new terminal (or you can add to .bashrc if you prefer).
+
+2.3. Building the Repository
+----------------------------
+
+To build the repository enter the 'build/tizen' folder:
+
+ cd dali-core/build/tizen
+
+Then run the following commands:
+
+ autoreconf --install
+ ./configure --prefix=$DESKTOP_PREFIX
+ make install -j8
+
diff --git a/automated-tests/.gitignore b/automated-tests/.gitignore
new file mode 100644 (file)
index 0000000..39d9377
--- /dev/null
@@ -0,0 +1,5 @@
+*.xml
+build
+build.log
+tct*core.h
+results_xml.*
diff --git a/automated-tests/.gitignore-with-autogenerated-files b/automated-tests/.gitignore-with-autogenerated-files
new file mode 100644 (file)
index 0000000..f039d8a
--- /dev/null
@@ -0,0 +1,4 @@
+*.xml
+build
+build.log
+tct*core.h
diff --git a/automated-tests/.gitignore-without-autogenerated-files b/automated-tests/.gitignore-without-autogenerated-files
new file mode 100644 (file)
index 0000000..8f3f9e2
--- /dev/null
@@ -0,0 +1,3 @@
+*.xml
+build
+build.log
diff --git a/automated-tests/CMakeLists.txt b/automated-tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..c27852a
--- /dev/null
@@ -0,0 +1,13 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(tct_coreapi_utc)
+
+INCLUDE(FindPkgConfig)
+SET(BIN_DIR "/opt/usr/bin")
+
+INCLUDE_DIRECTORIES(
+       src/common
+)
+
+ADD_SUBDIRECTORY(src)
+
+SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ")
diff --git a/automated-tests/README.md b/automated-tests/README.md
new file mode 100644 (file)
index 0000000..8db6f2c
--- /dev/null
@@ -0,0 +1,221 @@
+Testing environment   {#auto_testing}
+===================
+
+The new test environment from Tizen is the Web-TCT test suite. This was written for testing web components, but can easily be used for testing Dali.
+
+Each of the DALi repositories, **dali-core**, **dali-adaptor** and **dali-toolkit**, have their own test suites under the `automated-tests` folder. Within the src folder are a number of secondary folders - these correspond to 'API' tests  and internal (for desktop testing only)
+
+Installation
+------------
+
+There are usage instructions and installation instructions on the Tizen.org website [here](http://download.tizen.org/tct/2.2.1/Manual/Web_TCT_2.2.1_User_Guide_v1.0.pdf)
+
+These are device specific instructions, however, installing the test suite will also provide the relevant packages for running tests on Ubuntu ( follow the first block of quickstart instructions below ).
+
+If you are planning on running tests on device, then flash your handset with latest image, or turn off ssh: `set_usb_debug.sh --mtp-sdb` and plug it in, then follow the quickstart instructions repeated below.
+
+Quickstart
+----------
+
+For target or desktop testing:
+
+    cd ~/Packages
+    wget http://download.tizen.org/tct/2.2.1/2.2.1_r1/web-tct_2.2.1_r1.tar.gz
+    sudo tar xzf web-tct_2.2.1_r1.tar.gz
+    cd web-tct_2.2.1_r1/tools
+    sudo -E ./tct-config-host.sh
+
+
+If you are planning on running tests on device, then plug in your freshly flashed device and run the following commands:
+
+    sudo apt-get install sdb
+    ./tct-config-device.sh
+
+**NOTE:** After flashing a handset, you will need to run this step of the installation again.
+
+Testing on desktop
+==================
+
+Building libraries with coverage options
+----------------------------------------
+
+Building dali core:
+
+    cd dali-core  # the location of your dali-core repository
+    cd build/tizen
+    export CC=gcc
+    export CXX=g++
+    git clean -fxd . # Only do this in the build folder
+    autoreconf --install
+    CXXFLAGS='-g -O0 --coverage' LDFLAGS='--coverage' ./configure --prefix=$DESKTOP_PREFIX --enable-debug
+    make -j8 install
+
+Repeat for dali-adaptor and toolkit.
+
+Note, you __must__ use a local build and not a distributed build, and you __must__ also build with debug enabled to allow *DALI_ASSERT_DEBUG* to trigger on wrong behaviour ( Which should always be a test case failure! )
+
+Building the tests
+------------------
+
+Run the following commands:
+
+    cd automated-tests
+    ./build.sh
+
+This will build dali and dali-internal test sets.
+
+Test sets can be built individually:
+
+    ./build.sh dali
+
+They can also be built without regenerating test case scripts (Useful for quicker rebuilds)
+
+    ./build.sh -n dali-internal
+
+Or without cleaning down the build area (Useful for fast build/run/debug cycles)
+
+    ./build.sh -n -r dali-internal
+
+
+Executing the tests
+-------------------
+
+To execute tests, cd into automated-tests and run
+
+    ./execute.sh
+
+This will execute dali and dali-internal test sets. Note that the output summary for the first will be printed before running the second.
+
+By default the tests execute in parallel, which is faster but does not produce a single output file (summary.xml).  Use this to execute the tests in series:
+
+    ./execute.sh -s
+
+To see the summary.xml results, execute the tests in series and open as follows:
+
+    firefox --new-window summary.xml
+
+To see a list of all of the options:
+
+    ./execute.sh -h
+
+To execute a subset of tests, you can run individual test sets, e.g.
+
+    ./execute.sh dali
+
+To get coverage output, run
+
+    ./coverage.sh
+
+
+Testing on target
+=================
+
+To build for target, first build and install dali-core, dali-adaptor and dali-toolkit, then build dali-capi without --keep-packs option.
+
+You will need to install libconfig-tiny-perl:
+
+sudo apt-get install libconfig-tiny-perl
+
+If you use a non-standard `GBS_ROOT` then you will need to edit the tcbuild script to match your configuration - change line 96 and add a -B option with your GBS-ROOT path (line 96 = `gbs build -A armv7l --spec core-$1-tests.spec --include-all --keep-packs` ).
+To install on device from a non-standard GBS_ROOT, also modify line 28 (`RPM_DIR="$HOME/GBS-ROOT/local/repos/$PROFILE/armv7l/RPMS"`).
+
+For core Dali cd into automated-tests, and use:
+
+sudo ./tcbuild build dali
+
+    sudo ./tcbuild build dali
+    ./tcbuild install dali
+
+For Dali Adaptor, cd into automated-tests, and use:
+
+    sudo ./tcbuild build dali-adaptor
+    sudo ./tcbuild build dali-platform-abstraction
+    ./tcbuild install dali-adaptor
+    ./tcbuild install dali-platform-abstraction
+
+Ensure your handset's filesystem is writable:
+
+    sdb shell su -c "change-booting-mode.sh --update"
+
+To execute tests, cd into automated-tests and run
+
+    tct-mgr
+
+This will bring up the java test suite program. You should see the Plan pane with a list of all tests in. Select the tct-dali-core-tests. and you will be offered a dialog to choose a test plan: either create a new one or use temp.
+Select dali test suite, and click Run, then "Create a new plan", and call it "Dali-Core" or some such. It will now run the dali-test suite.
+
+You can find the output files under /opt/tct/manager/result/
+
+
+Adding tests
+============
+
+To Managed API
+--------------
+
+If you are adding test cases for new or existing managed API (CAPI), you need to add your changes to the src/dali mirror, and copy your change to the managed test suite in core-api. You need to inform HQ of your update.
+
+For internal API
+----------------
+
+If you are adding tests for internal API, then this will only work on desktop, and you should add your tests to the src/dali-internal test suite.
+
+General
+-------
+
+If you are adding test cases to existing files, then all you need to do is create functions with the method signature
+
+    int UtcTestcase(void)
+    {
+      TestApplication application;
+      ...
+      END_TEST;
+    }
+
+
+Note that **there must be no extra whitespace in the method signature** (i.e., it must violate our coding convention and follow __exactly__ this pattern: `int UtcDaliMyTestcaseName(void)`), as it's parsed by an awk script to auto-generate the testcase arrays in the main header file.
+
+You can contine to use the TET api, e.g. `tet_infoline`, `tet_result` and our test check methods `DALI_TEST_CHECK`, `DALI_TEST_EQUALS`, etc.
+
+If you need any non-test methods or variables, ensure they are wrapped in an anonymous namespace.
+
+If you are adding new test files, then you need to add the filename to the SET(TC_SOURCES...
+section of CMakeLists.txt (this is also parsed by an awk script prior to building)
+
+Debugging
+=========
+
+On desktop, you can debug the tests by running gdb on the test program:
+
+    $ cd automated-tests
+    $ gdb build/src/dali/tct-dali-core
+    gdb> r <TestCase>
+
+replace `<TestCase>` with the name of the failing testcase.
+
+For example, using testcase UtcDaliNinePatch01 from the dali-core test suite:
+
+    $ gdb build/src/dali/tct-dali-core
+    gdb> r UtcDaliNinePatch01
+
+
+On target, you can re-install the test RPM and associated debug RPMs manually using
+
+    sdb push <test-package>.rpm /tmp
+
+After installing the rpm and it's debug RPMs, you can find the executable in /opt/usr/bin/tct-dali-core. First ensure you have smack permissions set:
+
+    chsmack -e "^" /usr/bin/gdb
+    chsmack -e "^" /opt/usr/bin/tct-dali-core/tct-dali-core
+
+then run it under gdb as above.
+
+
+Troubleshooting
+===============
+
+If when running tct-mgr tests, if "Health-Check get" fails and leaves a white screen on the device, you will need to run `tct-config-device.sh` from your `web-tct/tools` directory (wherever you untarred it) and power cycle your handset. If that still fails, you can work-around the issue by running "`mkdir â€“p /opt/usr/media/Documents/tct/`" on target â€“ you may also need to kill the getCapabilities app from App Manager on the handset)
+
+If the test results show that the test cases fail with "Undefined reference to XXX", it means you have probably failed to update the dali packages on target.
+
+If all the tests are failing then make sure that you have enabled the engineering mode on the target with the 'change-booting-mode.sh --update' command in sdb shell, as the tests may not have installed correctly
diff --git a/automated-tests/build.sh b/automated-tests/build.sh
new file mode 100755 (executable)
index 0000000..7c7584b
--- /dev/null
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+
+TEMP=`getopt -o rn --long rebuild,no-gen \
+     -n 'genmake' -- "$@"`
+
+if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+opt_rebuild=false
+opt_generate=true
+
+while true ; do
+    case "$1" in
+        -r|--rebuild) opt_rebuild=true ; shift ;;
+        -n|--no-gen)  opt_generate=false ; shift ;;
+        --) shift ; break ;;
+        *) shift ;;   # Ignore
+    esac
+done
+
+if [ false == $opt_rebuild -o ! -d "build" ] ; then
+    rm -rf build
+    mkdir build
+fi
+
+function build
+{
+    if [ $opt_generate == true -o $opt_rebuild == false ] ; then
+        (cd src/$1; ../../scripts/tcheadgen.sh tct-$1-core.h)
+        if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+    fi
+    (cd build ; cmake .. -DMODULE=$1 ; make -j7 )
+}
+
+if [ -n "$1" ] ; then
+  echo BUILDING ONLY $1
+  build $1
+else
+  for mod in `ls -1 src/ | grep -v CMakeList `
+  do
+    if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+        echo BUILDING $mod
+        build $mod
+        if [ $? -ne 0 ]; then echo "Build failed" ; exit 1; fi
+    fi
+  done
+fi
diff --git a/automated-tests/coverage.sh b/automated-tests/coverage.sh
new file mode 100755 (executable)
index 0000000..c5fbed7
--- /dev/null
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+( cd ../build/tizen ; make cov_data )
+
+# From lcov version 1.10 onwards, branch coverage is off by default and earlier versions do not support the rc option
+LCOV_OPTS=`if [ \`printf "\\\`lcov --version | cut -d' ' -f4\\\`\n1.10\n" | sort -V | head -n 1\` = 1.10 ] ; then echo "--rc lcov_branch_coverage=1" ; fi`
+
+for i in `find . -name "*.dir"` ; do
+    (
+        cd $i
+        echo `pwd`
+        covs=( `ls *.gcda 2>/dev/null` )
+        if [[ $? -eq 0 ]]
+        then
+            lcov $LCOV_OPTS --directory . -c -o dali.info
+            lcov $LCOV_OPTS --remove dali.info "/usr/include/*" "*/automated-tests/*" "*/dali-env/*" -o dali.info
+            if [ ! -s dali.info ]
+            then
+              rm -f dali.info
+            fi
+        fi
+    )
+done
+
+(
+    cd .. ;
+    genhtml $LCOV_OPTS -o build/tizen/doc/coverage `find . -name dali.info`
+)
+
+echo "Coverage output: ../build/tizen/doc/coverage/index.html"
diff --git a/automated-tests/execute.sh b/automated-tests/execute.sh
new file mode 100755 (executable)
index 0000000..04dbd1f
--- /dev/null
@@ -0,0 +1,106 @@
+#!/bin/bash
+
+TEMP=`getopt -o hsr --long help,serial,rerun -n 'execute.sh' -- "$@"`
+
+if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+function usage
+{
+    echo -e "Usage: execute.sh\t\tExecute test cases from all modules in parallel"
+    echo -e "       execute.sh <testmodule>\tExecute test cases from the given module in parallel"
+    echo -e "       execute.sh -s\t\tExecute test cases in serial using Testkit-Lite"
+    echo -e "       execute.sh -r\t\tExecute test cases in parallel, re-running failed test cases in serial afterwards"
+    echo -e "       execute.sh <testcase>\tFind and execute the given test case"
+    exit 2
+}
+
+opt_serial=0
+opt_rerun=""
+while true ; do
+    case "$1" in
+        -h|--help)     usage ;;
+        -s|--serial)   opt_serial=1 ; shift ;;
+        -r|--rerun)    opt_rerun="-r" ; shift ;;
+        --) shift; break;;
+        *) echo "Internal error $1!" ; exit 1 ;;
+    esac
+done
+
+function execute
+{
+    scripts/tctestsgen.sh $1 `pwd` desktop $2
+    testkit-lite -f `pwd`/tests.xml -o tct-${1}-core-tests.xml  -A --comm localhost
+    scripts/add_style.pl $1
+}
+
+
+
+# Clean up old test results
+rm -f tct*core-tests.xml
+
+# Clean up old coverage data
+if [ -d ../build/tizen ] ; then
+    rm -f ../build/tizen/dali-core/.libs/*.gcda
+fi
+
+find build \( -name "*.gcda" \) -exec rm '{}' \;
+
+ASCII_BOLD="\e[1m"
+ASCII_RESET="\e[0m"
+
+if [ $opt_serial = 1 ] ; then
+    # Run all test case executables serially, create XML output
+    if [ -n "$1" ] ; then
+        execute $1 $*
+    else
+        for mod in `ls -1 src/ | grep -v CMakeList `
+        do
+            if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+
+                echo -ne "$ASCII_BOLD"
+                echo -e "Executing $mod$ASCII_RESET"
+                execute $mod $*
+            fi
+        done
+    fi
+
+    scripts/summarize.pl
+else
+    # if $1 is an executable filename, execute it·
+
+    if [ -z "$1" ] ; then
+        # No arguments:
+        # Execute each test executable in turn, using parallel execution
+        for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual`
+        do
+            echo -e "$ASCII_BOLD"
+            echo -e "Executing $mod$ASCII_RESET"
+            build/src/$mod/tct-$mod-core $opt_rerun
+        done
+
+    elif [ -f "build/src/$1/tct-$1-core" ] ; then
+        # First argument is an executable filename - execute only that with any
+        # remaining arguments
+        module=$1
+        shift;
+        build/src/$module/tct-$module-core $opt_rerun $*
+
+    else
+       # First argument is not an executable. Is it a test case name?
+       # Try executing each executable with the test case name until success/known failure
+        for mod in `ls -1 src/ | grep -v CMakeList | grep -v common | grep -v manual`
+        do
+            output=`build/src/$mod/tct-$mod-core $1`
+            ret=$?
+            if [ $ret -ne 6 ] ; then
+               echo $output
+               if [ $ret -eq 0 ] ; then echo -e "\nPassed" ; fi
+               exit $ret
+            fi
+        done
+        echo $1 not found
+    fi
+fi
diff --git a/automated-tests/packaging/core-dali-tests.spec b/automated-tests/packaging/core-dali-tests.spec
new file mode 100644 (file)
index 0000000..e5127bb
--- /dev/null
@@ -0,0 +1,51 @@
+%define MODULE_NAME dali
+%define MODULE_LIBNAME dali
+Name:       core-%{MODULE_NAME}-tests
+Summary:    Core API unit TC (%{name})
+Version:    0.1
+Release:    0
+Group:      Development/Tools
+License:    Apache License, Version 2.0, Samsung Properietary
+Source0:    %{name}-%{version}.tar.gz
+Requires: dali
+BuildRequires:  dali-integration-devel
+BuildRequires:  pkgconfig(dali-core)
+BuildRequires:  pkgconfig(dali)
+BuildRequires:  cmake
+
+%description
+Core API unit TC (%{name})
+
+%prep
+%setup -q
+
+%build
+
+%define PREFIX "%{_libdir}/%{name}"
+
+export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed"
+cd automated-tests
+cmake . -DMODULE="%{MODULE_NAME}" -DCMAKE_INSTALL_PREFIX=%{_prefix}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+cd automated-tests
+%make_install
+mkdir -p %{buildroot}/opt/usr/share/license
+cp %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/opt/usr/share/license/%{name}
+mkdir -p %{buildroot}/tmp/
+cp %{_builddir}/%{name}-%{version}/automated-tests/scripts/add_all_smack_rule.sh %{buildroot}/tmp/
+cp %{_builddir}/%{name}-%{version}/automated-tests/scripts/all_smack.rule %{buildroot}/tmp/
+
+%post
+
+%postun
+
+
+%files
+/opt/usr/bin/*
+/opt/usr/share/license/%{name}
+/tmp/add_all_smack_rule.sh
+/tmp/all_smack.rule
diff --git a/automated-tests/scripts/add_all_smack_rule.sh b/automated-tests/scripts/add_all_smack_rule.sh
new file mode 100755 (executable)
index 0000000..8efb158
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+SCRIPTDIR=`dirname $(readlink -f $0)`
+SMACK_FILE=$SCRIPTDIR/all_smack.rule
+       
+echo ""
+echo "Add smack rule in $SMACK_FILE"
+echo "==================================================="
+echo ""
+
+while read rule; do
+       NO_BLANK=$(echo $rule | sed 's/ //g' | sed 's/  //g')
+       if [ ${#NO_BLANK} -lt 1 ]; then
+               echo "Blank"
+               continue
+       elif [ `echo $NO_BLANK|cut -c1-1` = '#' ]; then
+               echo "Comment"
+               continue
+       fi
+
+       echo "echo \"$rule\" > /smack/load2"
+       echo "$rule" > /smack/load2
+done < $SMACK_FILE
+
+echo "==================================================="
+echo ""
diff --git a/automated-tests/scripts/add_smack_rule.sh b/automated-tests/scripts/add_smack_rule.sh
new file mode 100755 (executable)
index 0000000..22fe5ee
--- /dev/null
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+SCRIPTDIR=`dirname $(readlink -f $0)`
+SMACK_FILE=$SCRIPTDIR/all_smack.rule
+       
+echo ""
+echo "Add smack rule in $SMACK_FILE"
+echo "==================================================="
+
+echo "sdb root on"
+sdb root on
+
+while read rule; do
+       NO_BLANK=$(echo $rule | sed 's/ //g' | sed 's/  //g')
+       if [ ${#NO_BLANK} -lt 1 ]; then
+               #echo "Blank"
+               continue
+       elif [ `echo $NO_BLANK|cut -c1-1` = '#' ]; then
+               #echo "Comment"
+               continue
+       fi
+
+       echo "sdb shell \"echo $rule > /smack/load2\""
+       sdb shell "echo $rule > /smack/load2"
+done < $SMACK_FILE
+
+echo "==================================================="
+echo ""
diff --git a/automated-tests/scripts/add_style.pl b/automated-tests/scripts/add_style.pl
new file mode 100755 (executable)
index 0000000..e958842
--- /dev/null
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+
+use strict;
+use Encode;
+use Getopt::Long;
+use Cwd;
+
+my $pwd = getcwd;
+my $MOD_NAME = $ARGV[0];
+my $results_xml = "tct-$MOD_NAME-core-tests.xml";
+my $results_out = "results_xml.$$";
+
+# Copy $results_xml, writing new stylesheet line:
+# Write <?xml-stylesheet type="text/xsl" href="./style/testresult.xsl"?> as second line
+open RESULTS, "<$results_xml" || die "Can't open $results_xml for reading:$!\n";
+open RESULTS_OUT, ">$results_out" || die "Can't open $results_out for writing:$!\n";
+my $fline = readline RESULTS;
+print RESULTS_OUT $fline;
+print RESULTS_OUT "<?xml-stylesheet type=\"text/xsl\" href=\"./style/testresult.xsl\"?>\n";
+while(<RESULTS>)
+{
+    if( ! /xml-stylesheet/ )
+    {
+        print RESULTS_OUT $_;
+    }
+}
+close RESULTS_OUT;
+close RESULTS;
+unlink $results_xml;
+print `mv $results_out $results_xml`;
diff --git a/automated-tests/scripts/all_smack.rule b/automated-tests/scripts/all_smack.rule
new file mode 100644 (file)
index 0000000..93f2b67
--- /dev/null
@@ -0,0 +1,28 @@
+# calendar-service
+_ calendar-service::svc rwx
+
+# capi-appfw-application
+_ alarm-server::alarm rw
+_ aul::launch x
+_ aul::terminate x
+
+# capi-network-bluetooth
+_ bt-service::admin w
+_ bt-service::manager w
+_ bt-service::gap w
+_ bt-service::spp w
+_ bt:service::opp w
+
+# capi-network-nfc
+_ nfc-manager rwx
+_ nfc-manager::tag rwx
+_ nfc-manager::p2p rwx
+_ nfc-manager::admin rwx
+_ nfc-manager::common rwx
+
+# capi-location-*
+_ location::maps rw
+_ location::client rw
+
+# libmdm
+_ mdm-server::eas rw
diff --git a/automated-tests/scripts/autocompletion.sh b/automated-tests/scripts/autocompletion.sh
new file mode 100755 (executable)
index 0000000..d952c73
--- /dev/null
@@ -0,0 +1,18 @@
+#!/bin/bash
+if [ -z "$TC_PROJECT_DIR" ]; then
+    echo "CoreAPI project directory can't be found. `basename $0` exitting..."
+    exit 1
+fi
+
+_tcbuild () {
+    local cur
+    cur=${COMP_WORDS[$COMP_CWORD]}
+    if [ $COMP_CWORD -eq 1 ]; then
+        COMPREPLY=( $( compgen -W "addmod build install rmmod" -- $cur ) )
+    else #if [ $COMP_CWORD -eq 2 ]; then
+        COMPREPLY=( $( cd $TC_PROJECT_DIR/src; compgen -d -X "common" -- $cur ) )
+    fi
+    return 0
+}
+
+complete -F _tcbuild tcbuild
diff --git a/automated-tests/scripts/init.sh b/automated-tests/scripts/init.sh
new file mode 100755 (executable)
index 0000000..1ccd9ea
--- /dev/null
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+PROJECT_DIR="$(cd "$(dirname $0)" && cd .. && pwd)"
+
+ln -s $PROJECT_DIR/scripts/tcbuild.sh $PROJECT_DIR/tcbuild
+
+echo "" >> $HOME/.bashrc
+echo "# CoreAPI-tests convenience helpers" >> $HOME/.bashrc
+echo "export TC_PROJECT_DIR=\"$PROJECT_DIR\"" >> $HOME/.bashrc
+echo "source $PROJECT_DIR/scripts/autocompletion.sh" >> $HOME/.bashrc
diff --git a/automated-tests/scripts/retriever.sh b/automated-tests/scripts/retriever.sh
new file mode 100755 (executable)
index 0000000..c1d466d
--- /dev/null
@@ -0,0 +1,212 @@
+#!/bin/bash
+
+USAGE=$(cat <<EOF
+Usage note: retriever.sh [option] [directory]
+Options:
+  none    retrieve TC names with corresponding startup and cleanup functions
+  -f      retrieveve TC name with corresponding "set" and "purpose" clauses
+  -anum   retrieve automatic TC number
+  -mnum   retrieve manual TC number
+
+In case of TC in form of "int tc_name()" script will abort.
+("int tc_name(void)" is a proper function signature)
+EOF
+)
+
+function get_tc_files {
+    CMAKE_FILE="$DIR/CMakeLists.txt"
+    if [ ! -e $CMAKE_FILE ]; then
+        echo "File $CMAKE_FILE not found. Aborting..."
+        exit 1
+    fi
+
+    TC_FILES=$(cat $CMAKE_FILE | awk -vDIR="$DIR" '
+    BEGIN {
+        flag = 0;
+        files = "";
+    }
+    /^SET\(TC_SOURCES/ {
+        flag = 1;
+        next;
+    }
+    /\)/ {
+        if (flag == 1)
+            exit;
+    }
+    !/^ *#/ {
+        if (flag == 1) {
+            if (files == "")
+                files = DIR "/" $1;
+            else
+                files = files " " DIR "/" $1;
+        }
+    }
+    END {
+        print files;
+    }')
+}
+
+function tc_names {
+    if [[ -z "$1" ]]; then
+        exit
+    fi
+
+    awk '
+    BEGIN {
+        OFS = ",";
+        start_fun = "NULL";
+        clean_fun = "NULL";
+        err_flag = 0;
+        tc_list = "";
+    }
+    /^void .*startup\(void\)/ {
+        gsub(/^void /, "");
+        gsub(/\(void\)$/,"");
+        start_fun = $0
+    }
+    /^void .*cleanup\(void\)/ {
+        gsub(/^void /, "");
+        gsub(/\(void\)$/,"");
+        clean_fun = $0
+    }
+    /^int .*\(\)/ {
+        print "Warning: function with empty argument list -- \"" $0 "\" in " FILENAME ":" FNR;
+        err_flag = 1;
+    }
+    /^int .*\(void\)/ {
+        gsub(/^int /, "");
+        gsub(/\(void\).*/,"");
+        if (tc_list != "") tc_list = tc_list "\n";
+        tc_list = tc_list $0 OFS start_fun OFS clean_fun
+    }
+    END {
+        if (err_flag) {
+            exit 1
+        } else {
+            print tc_list
+        }
+    }
+    ' $*
+}
+
+function tc_anum {
+    awk '
+    BEGIN {
+        count = 0;
+        err_flag = 0;
+    }
+    /^int .*\(\)/ {
+        print "Warning: function with empty argument list -- \"" $0 "\" in " FILENAME ":" FNR;
+        err_flag = 1;
+    }
+    /^int .*\(void\)$/ {
+        count++;
+    }
+    END {
+        if (err_flag) {
+            exit 1
+        } else {
+            print count
+        }
+    }
+    ' $*
+}
+
+function tc_mnum {
+    # TODO: fix this hardcoded value
+    echo 0
+}
+
+function tc_fullinfo {
+    awk '
+    BEGIN {
+        OFS=",";
+        purpose = "";
+        set = "default";
+        err_flag = 0;
+        tc_list = "";
+    }
+    /^\/\/& set:/ {
+        set = $3;
+        next;
+    }
+    /^\/\/& purpose:/ {
+        purpose = $3;
+        for (i = 4; i <= NF; i++) {
+            purpose = purpose " " $i;
+        }
+        next;
+    }
+    /^int .*\(\)/ {
+        print "Warning: function with empty argument list -- \"" $0 "\" in " FILENAME ":" FNR;
+        err_flag = 1;
+    }
+    /^int .*\(void\)$/ {
+        gsub(/^int /, "");
+        gsub(/\(void\)$/,"");
+        if (tc_list != "") tc_list = tc_list "\n";
+        tc_list = tc_list $0 OFS set OFS purpose;
+        purpose = "";
+        next
+    }
+    END {
+        if (err_flag) {
+            exit 1
+        } else {
+            print tc_list
+        }
+    }
+    ' $*
+}
+
+
+# usage note and exit:
+# - argument begin with '-' but is not recognised or number of arguments is > 3,
+# - argument doesn't begin with '-' and number of arguments is > 2
+if [[ ( "$1" == -* && ( ! "$1" =~ ^-(anum|mnum|f)$ || $# > 3 ) ) || ( "$1" != -* && $# > 2 ) ]]; then
+    echo -e "$USAGE"
+    exit 1
+fi
+
+# get directory from last argument (or assume current one)
+if [[ ! "$1" =~ ^-(anum|mnum|f)$ ]]; then
+    DIR=${1:-.}
+else
+    DIR=${2:-.}
+fi
+
+# get filename from last argument
+if [[ $# == 3 && -f $DIR/$3 ]] ; then
+    FILE=$3
+elif [[ $# == 2 && -f $DIR/$2 ]] ; then
+    FILE=$2
+fi
+
+#echo "Dir: $DIR  File: $FILE" >& 2
+
+
+# populate $TC_FILES with files declared in CMakeLists.txt
+if [[ -z $FILE ]]; then
+    get_tc_files $DIR
+    if [ $? != 0 ]; then
+        exit 1
+    fi
+    echo "Got all files" >& 2
+else
+    TC_FILES="$DIR/$FILE"
+    echo "TC_FILES: $TC_FILES" >& 2
+fi
+
+
+
+# run appropriate subcommand
+case "$1" in
+    -anum)
+        tc_anum $TC_FILES ;;
+    -mnum)
+        tc_mnum $TC_FILES ;;
+    -f)
+        tc_fullinfo $TC_FILES ;;
+    *)
+        tc_names $TC_FILES ;;
+esac
diff --git a/automated-tests/scripts/summarize.pl b/automated-tests/scripts/summarize.pl
new file mode 100755 (executable)
index 0000000..c90eb89
--- /dev/null
@@ -0,0 +1,109 @@
+#!/usr/bin/perl
+
+use strict;
+use XML::Parser;
+use Encode;
+use Getopt::Long;
+use Cwd;
+
+my $pwd = getcwd;
+my $num_tests=0;
+my $num_passes=0;
+my $num_actual_passes=0;
+my $text = "";
+
+sub handle_start
+{
+    my ($p, $elt, %attrs) = @_;
+
+    if($elt =~ /testcase/)
+    {
+        $num_tests++;
+        if($attrs{"result"} eq "PASS")
+        {
+            $num_passes++;
+        }
+    }
+    if($elt =~ /actual_result/)
+    {
+        $text = "";
+    }
+}
+
+sub handle_end
+{
+  my ($p, $elt) = @_;
+  if($elt =~ /actual_result/)
+  {
+      if($text eq "PASS")
+      {
+          $num_actual_passes++;
+      }
+      $text = "";
+  }
+}
+
+sub handle_char
+{
+  my ($p, $str) = @_;
+  $text .= $str;
+}
+
+my($parser) = new XML::Parser(Handlers => {Start => \&handle_start,
+                                           End   => \&handle_end,
+                                           Char  => \&handle_char});
+
+
+# Write summary.xml:
+open SUMMARY, ">summary.xml" || die "Can't open summary.xml for writing:$!\n";
+print SUMMARY << "EOS";
+<?xml version="1.0" encoding="UTF-8"?>
+<?xml-stylesheet type="text/xsl" href="./style/summary.xsl"?>
+<result_summary plan_name="Core">
+  <other xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string" />
+  <summary test_plan_name="Empty test_plan_name">
+    <start_at>2014-03-21_18_52_41</start_at>
+    <end_at>2014-03-21_18_57_54</end_at>
+  </summary>
+EOS
+
+print "\n\nSummary of all tests:\n";
+my $output_files = `ls tct*core-tests.xml`;
+my $file;
+foreach $file (split /\s+/, $output_files )
+{
+    $num_tests=0;
+    $num_passes=0;
+    $num_actual_passes=0;
+    $text = "";
+
+    $parser->parsefile($file);
+
+    my $pass_rate = sprintf("%5.2f", $num_passes * 100.0 / $num_tests);
+    my $num_fails = $num_tests - $num_passes;
+    my $fail_rate = sprintf("%5.2f", $num_fails * 100.0 / $num_tests);
+
+    my $suite_name = $file;
+    $suite_name =~ s/\.xml$//;
+
+    print "$suite_name: $num_passes tests passed out of $num_tests ( $pass_rate% )\n";
+
+print SUMMARY << "EOS2";
+  <suite name="$suite_name">
+    <total_case>$num_tests</total_case>
+    <pass_case>$num_passes</pass_case>
+    <pass_rate>$pass_rate</pass_rate>
+    <fail_case>$num_fails</fail_case>
+    <fail_rate>$fail_rate</fail_rate>
+    <block_case>0</block_case>
+    <block_rate>0.00</block_rate>
+    <na_case>0</na_case>
+    <na_rate>0.00</na_rate>
+  </suite>
+EOS2
+}
+
+print SUMMARY "</result_summary>\n";
+close SUMMARY;
+
+print "Summary of results written to summary.xml\n";
diff --git a/automated-tests/scripts/tcbuild.sh b/automated-tests/scripts/tcbuild.sh
new file mode 100755 (executable)
index 0000000..b604675
--- /dev/null
@@ -0,0 +1,215 @@
+#!/bin/bash
+
+#---------- DEBUG_BEGIN ----------
+#ARG="-d" # debug-on flag, might be set as $1
+# keyprompt "introductory message" -- wait until any key pressed
+function keyprompt { echo -ne "\n\e[1;31m$1 -- " && read -n 1 && echo -e "\n\e[0m"; }
+# d_bp -- breakpoint at which user need to press any key to proceed
+function d_bp { if [[ "$ARG" == "-d" ]]; then keyprompt "d >> Press any key"; fi }
+# d_showVar VARNAME -- print bash variable name
+function d_showVar { if [ "$ARG" == "-d" -a -n "$1" ]; then echo "d >> ${1} = ${!1}"; fi }
+# d_print "message" -- print a debug message
+function d_print { if [ "$ARG" == "-d" -a -n "$1" ]; then echo -e "d >> $1"; fi }
+#----------  DEBUG_END  ----------
+
+PROJECT_DIR="$(cd "$(dirname $0)" && pwd)"
+d_showVar PROJECT_DIR
+
+function gbs_profile {
+perl -e "
+use Config::Tiny;
+my \$Config = Config::Tiny->read( \"\$ENV{HOME}/.gbs.conf\" );
+my \$profile = \$Config->{general}->{profile};
+\$profile =~ s/profile.//;
+print \$profile;"
+}
+
+PROFILE=`gbs_profile`
+RPM_DIR="$HOME/GBS-ROOT/local/repos/$PROFILE/armv7l/RPMS"
+d_showVar RPM_DIR
+
+function add_module {
+    # argument check
+    if [ -z "$1" ]; then echo "Usage: `basename $0` addmod <module_name> [module_lib_name]"; exit 1; fi
+
+    MODULE_NAME=$1
+    d_showVar MODULE_NAME
+    MODULE_NAME_C=$(echo $MODULE_NAME | sed -e 's/-\([a-z]\)/\U\1/' -e 's/^\([a-z]\)/\U\1/')
+    d_showVar MODULE_NAME_C
+    MODULE_NAME_U=$(echo $MODULE_NAME | sed -e 's/-/_/')
+    d_showVar MODULE_NAME_U
+#    MODULE_LIBNAME=${2:-capi-$MODULE_NAME}
+    MODULE_LIBNAME=$1
+    d_showVar MODULE_LIBNAME
+
+    echo "Adding $MODULE_NAME module to project..."
+    d_bp
+    cd $PROJECT_DIR
+    # prepare .spec file
+    echo "-- Generating packaging/core-$MODULE_NAME-tests.spec file"
+    if [ ! -d packaging ]; then mkdir packaging; fi
+    sed -e "s:\[MODULE_NAME\]:$MODULE_NAME:g" -e "s:\[MODULE_LIBNAME\]:$MODULE_LIBNAME:g" \
+        templates/core-\[module_name\]-tests.spec > packaging/core-$MODULE_NAME-tests.spec
+    # prepare src directory
+    mkdir src/$MODULE_NAME
+    echo "-- Generating src/$MODULE_NAME/CMakeLists.txt file"
+    sed -e "s:%{MODULE_NAME}:$MODULE_NAME:g" -e "s:%{MODULE_LIBNAME}:$MODULE_LIBNAME:g" \
+        templates/src-directory/CMakeLists.txt > src/$MODULE_NAME/CMakeLists.txt
+    echo "-- Generating src/$MODULE_NAME/tct-$MODULE_NAME-core.c file"
+    sed -e "s:%{MODULE_NAME}:$MODULE_NAME:g" \
+        templates/src-directory/tct-\[module_name\]-core.c > src/$MODULE_NAME/tct-$MODULE_NAME-core.c
+    echo "-- Generating src/$MODULE_NAME/utc-$MODULE_NAME.c file"
+    sed -e "s:%{MODULE_NAME_U}:$MODULE_NAME_U:g" -e "s:%{MODULE_NAME_C}:$MODULE_NAME_C:g" \
+        templates/src-directory/utc-\[module_name\].c > src/$MODULE_NAME/utc-$MODULE_NAME.c
+    echo "Task finished successfully"
+}
+
+function rm_module {
+    # argument check
+    if [ -z "$1" ]; then echo "Usage: `basename $0` rmmod <module_name>"; exit 1; fi
+
+    MODULE_NAME=$1
+    d_showVar MODULE_NAME
+
+    echo "Removing $MODULE_NAME module from project..."
+    d_bp
+    echo "---- Updating /opt/tct/packages/package_list.xml"
+    scripts/tcpackageslistsgen.sh $MODULE_NAME /opt/tct/packages/package_list.xml 1
+    if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+   # echo "---- Updating test plans"
+   # scripts/tcpackageslistsgen.sh $MODULE_NAME /opt/tct/manager/plan/*.xml 1
+   # if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+
+    cd $PROJECT_DIR
+    echo "-- Removing packaging/core-$MODULE_NAME-tests.spec file"
+    rm packaging/core-$MODULE_NAME-tests.spec
+    echo "-- Removing src/$MODULE_NAME directory"
+    rm -r src/$MODULE_NAME
+    echo "Task finished successfully"
+}
+
+function build {
+    if [ -n "$1" ]; then
+        (cd src/$1; ../../scripts/tcheadgen.sh tct-$1-core.h)
+        if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+        cp packaging/core-$1-tests.spec ../packaging
+        cp .gitignore-without-autogenerated-files .gitignore
+        gbs build -A armv7l --spec core-$1-tests.spec --include-all --keep-packs | \
+            tee build.log | stdbuf -o0 sed -e 's/error:/\x1b[1;91m&\x1b[0m/' \
+                                           -e 's/warning:/\x1b[93m&\x1b[0m/'
+        rm ../packaging/core-$1-tests.spec
+        cp .gitignore-with-autogenerated-files .gitignore
+    else
+        echo "Build requires a module name"
+        exit 1
+    fi
+}
+
+function inst {
+    if [ -z "$1" ]
+    then
+        for mod in `ls -1 src/ | grep -v CMakeLists`
+        do
+
+       if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+
+            PKG_NAME="core-$mod-tests"
+            d_showVar PKG_NAME
+            VER=$(cat packaging/$PKG_NAME.spec | awk '/^Version:/ { print $2; exit; }')
+            d_showVar VER
+            PKG_VNAME="$PKG_NAME-$VER"
+            d_showVar PKG_VNAME
+            PKG_FNAME="$PKG_VNAME-0.armv7l.rpm"
+            d_showVar PKG_FNAME
+
+            if [ -f "$RPM_DIR/$PKG_FNAME" ]
+            then
+                inst $mod
+                echo ""
+            fi
+       fi
+        done
+    else
+        cd $PROJECT_DIR
+        # setting variables
+        MOD_NAME="$1"
+        d_showVar MOD_NAME
+        PKG_NAME="core-$MOD_NAME-tests"
+        d_showVar PKG_NAME
+        VER=$(cat packaging/$PKG_NAME.spec | awk '/^Version:/ { print $2; exit; }')
+        d_showVar VER
+        PKG_VNAME="$PKG_NAME-$VER"
+        d_showVar PKG_VNAME
+        PKG_FNAME="$PKG_VNAME-0.armv7l.rpm"
+        d_showVar PKG_FNAME
+        TCT_DIR="opt/tct-$MOD_NAME-core-tests"
+        d_showVar TCT_DIR
+
+        echo "Deploying $MOD_NAME suite to tct-mgr..."
+        d_bp
+        # prepare tct directory and files
+        echo "-- Preparing suite .zip file..."
+        echo "---- Creating /tmp/$TCT_DIR directory"
+        rm -r /tmp/opt > /dev/null 2>&1
+        mkdir -p /tmp/$TCT_DIR
+        # README
+        echo "---- Copying /tmp/$TCT_DIR"
+        cp templates/tct-package/README /tmp/$TCT_DIR
+        # rpm
+        echo "---- Copying /tmp/$TCT_DIR package"
+        cp $RPM_DIR/$PKG_FNAME /tmp/$TCT_DIR
+        if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+        # inst.sh
+        echo "---- Generating /tmp/$TCT_DIR/inst.sh file"
+        sed -e "s:%{PKG_NAME}:\"$PKG_NAME\":g" -e "s:%{PKG_FULLNAME}:\"$PKG_FNAME\":g" \
+            -e "s:%{PKG_DIR}:\"/opt/usr/media/tct/$TCT_DIR\":g" \
+            templates/tct-package/inst.sh > /tmp/$TCT_DIR/inst.sh
+        chmod a+x /tmp/$TCT_DIR/inst.sh
+        # tests.xml
+        echo "---- Generating /tmp/$TCT_DIR"
+        scripts/tctestsgen.sh $MOD_NAME /tmp/$TCT_DIR target
+        if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+        # zip
+        echo "---- Preparing /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip file"
+        # clear old zips
+        rm -r /tmp/tct/packages > /dev/null 2>&1
+        mkdir -p /tmp/tct/packages
+        # create new zip
+        ( cd /tmp; zip -r /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip opt > /dev/null 2>&1; )
+        # deployment
+        echo "-- Suite deployment..."
+        echo "---- Copying /opt/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip"
+        cp /tmp/tct/packages/tct-$MOD_NAME-core-tests-2.2.1-1.zip /opt/tct/packages/
+        echo "---- Updating /opt/tct/packages/package_list.xml"
+        scripts/tcpackageslistsgen.sh $MOD_NAME /opt/tct/packages/package_list.xml 0
+        if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+       # echo "---- Updating test plans"
+       # for file in `grep -r tct-$MOD_NAME-core-tests /opt/tct/manager/plan/ | cut -d: -f1 | uniq`
+       # do
+       #     scripts/tcpackageslistsgen.sh $MOD_NAME $file
+       # done
+       # scripts/tcpackageslistsgen.sh $MOD_NAME /opt/tct/manager/plan/Full_test.xml
+       # if [ $? -ne 0 ]; then echo "Aborting..."; exit 1; fi
+        echo "Task finished successfully"
+    fi
+}
+
+if [ -z "$1" ]; then
+    # usage note
+    echo "Usage: `basename $0` <addmod|rmmod|build|install> <module_name> [module_lib_name]"
+    exit 1
+elif [ "addmod" == "$1" ]; then
+    # add new module
+    add_module $2 $3
+elif [ "rmmod" == "$1" ]; then
+    # remove module
+    rm_module $2
+elif [ "build" == "$1" ]; then
+    # build the binary
+    build $2
+elif [ "install" == "$1" ]; then
+    # install
+    inst $2
+else
+    echo "Invalid subcommand: $1"
+fi
diff --git a/automated-tests/scripts/tcheadgen.sh b/automated-tests/scripts/tcheadgen.sh
new file mode 100755 (executable)
index 0000000..c7b7700
--- /dev/null
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+if [[ -z $1 ]]; then
+    echo "Usage note: tcheadgen.sh <header_filename.h>"
+    exit 1
+fi
+
+FILE="$PWD/$1"
+TFILE="/tmp/retr.csv"
+HEADER_NAME=$(echo $1 | tr '[:lower:]' '[:upper:]' | sed -e 's/-/_/g' -e 's/\./_/')
+SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)"
+
+$SCRIPT_DIR/retriever.sh > $TFILE
+if [ $? -ne 0 ]; then cat $TFILE; exit 1; fi
+awk -F',' -v HEADER_NAME="$HEADER_NAME" '
+    BEGIN {
+        OFS = ", ";
+
+        startup_counter = 0;
+        startup_list[0] = "";
+
+        cleanup_counter = 0;
+        cleanup_list[0] = "";
+
+        testcase_counter = 0;
+        testcase_list[0] = "";
+
+        tc_array_counter = 0;
+        tc_array_list[0] = "";
+
+print "#ifndef __" HEADER_NAME "__"
+print "#define __" HEADER_NAME "__"
+print ""
+print "#include \"testcase.h\""
+print ""
+    }
+    {
+        testcase_list[testcase_counter++] = $1;
+
+        if (startup_counter == 0 || startup_list[startup_counter-1] != $2)
+            startup_list[startup_counter++] = $2;
+
+        if (startup_counter == 0 || cleanup_list[cleanup_counter-1] != $3)
+            cleanup_list[cleanup_counter++] = $3;
+
+        tc_array_list[tc_array_counter++] = "\"" $1 "\", " $1 ", " $2 ", " $3;
+    }
+    END {
+        sc_count = (startup_counter > cleanup_counter) ? startup_counter : cleanup_counter;
+        for (i = 0; i < sc_count; i++) {
+            if (i < startup_counter && startup_list[i] != "NULL")
+print "extern void " startup_list[i] "(void);"
+            if (i < cleanup_counter && cleanup_list[i] != "NULL")
+print "extern void " cleanup_list[i] "(void);"
+        }
+
+print ""
+        for (i = 0; i < testcase_counter; i++)
+print "extern int " testcase_list[i] "(void);"
+
+print ""
+print "testcase tc_array[] = {"
+
+        for (i = 0; i < tc_array_counter; i++)
+print "    {" tc_array_list[i] "},"
+
+print "    {NULL, NULL}"
+print "};"
+print ""
+print "#endif // __" HEADER_NAME "__"
+}' $TFILE > $FILE
diff --git a/automated-tests/scripts/tcpackageslistsgen.sh b/automated-tests/scripts/tcpackageslistsgen.sh
new file mode 100755 (executable)
index 0000000..15ea51f
--- /dev/null
@@ -0,0 +1,72 @@
+#!/bin/bash
+
+if [ -z $1 -o -z $2 ]; then
+    echo "Usage note: tcpackageslistsgen.sh <module_name> <output_file.xml>"
+    exit 1
+fi
+
+MODULE_NAME=$1
+FILE=$2
+if [ ! -f $FILE ]; then
+    echo "No such file: $2"
+    exit
+fi
+SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)"
+AUTO_NUM=$(cd $SCRIPT_DIR/..; scripts/retriever.sh -anum src/$MODULE_NAME)
+if [ $? -ne 0 ]; then echo $AUTO_NUM; exit 1; fi
+MAN_NUM=$(cd $SCRIPT_DIR/..; scripts/retriever.sh -mnum src/$MODULE_NAME)
+if [ $? -ne 0 ]; then echo $MAN_NUM; exit 1; fi
+
+TFILE="/tmp/tempfile.xml"
+if [ -f $TFILE ]; then
+    rm $TFILE
+fi
+
+function regen {
+    awk -v RS='\r\n' -v ORS='\r\n' -v MODULE_NAME=$MODULE_NAME -v AUTO_NUM=$AUTO_NUM -v MAN_NUM=$MAN_NUM '    
+    BEGIN {
+        found = 0;
+        replaced = 0;
+    }
+    $0 ~ "<suite name=\"tct-" MODULE_NAME "-core-tests\" category=\"Core APIs\">" {
+        found = 1;
+        next
+    }
+    /<\/suite>/ {
+        if (found == 1) {
+print "  <suite name=\"tct-" MODULE_NAME "-core-tests\" category=\"Core APIs\">";
+print "    <auto_tcn>" AUTO_NUM "</auto_tcn>";
+print "    <manual_tcn>" MAN_NUM "</manual_tcn>";
+print "    <total_tcn>" AUTO_NUM+MAN_NUM "</total_tcn>";
+print "    <pkg_name>tct-" MODULE_NAME "-core-tests-2.2.1-1.zip</pkg_name>";
+print "  </suite>";
+            found = 0;
+            replaced = 1;
+        } else {
+            print $0;
+        }
+        next
+    }
+    /<\/ns3:testplan>/ {
+        if (replaced == 0) {
+print "  <suite name=\"tct-" MODULE_NAME "-core-tests\" category=\"Core APIs\">";
+print "    <auto_tcn>" AUTO_NUM "</auto_tcn>";
+print "    <manual_tcn>" MAN_NUM "</manual_tcn>";
+print "    <total_tcn>" AUTO_NUM+MAN_NUM "</total_tcn>";
+print "    <pkg_name>tct-" MODULE_NAME "-core-tests-2.2.1-1.zip</pkg_name>";
+print "  </suite>";
+print $0
+        } else {
+            print $0
+        }
+        next
+    }
+    {
+        if (found == 0) {
+            print $0;
+        }
+    }' $FILE > $TFILE
+    cat $TFILE > $FILE
+}
+
+regen
diff --git a/automated-tests/scripts/tctestsgen.sh b/automated-tests/scripts/tctestsgen.sh
new file mode 100755 (executable)
index 0000000..1881668
--- /dev/null
@@ -0,0 +1,66 @@
+#!/bin/bash
+
+if [[ -z $1 ]]; then
+    echo "Usage note: tctestsgen.sh <module_name>"
+    exit 1
+fi
+
+MODULE_NAME=$1
+MODULE_NAME_C=$(echo $MODULE_NAME | sed -e 's/-\([a-z]\)/\U\1/' -e 's/^\([a-z]\)/\U\1/')
+SCRIPT_DIR="$(cd "$(dirname $0)" && pwd)"
+TC_DIR="/opt/usr/bin/tct-$1-core"
+if [[ $3 == "desktop" ]] ; then
+  TC_DIR="build/src/$1"
+fi
+
+FILE="$2/tests.xml"
+if [ -a $FILE ]; then
+    rm $FILE
+fi
+TFILE="/tmp/tcs.csv"
+if [ -a $TFILE ]; then
+    rm $TFILE
+fi
+
+function gen {
+    awk -F',' -v MODULE_NAME=$MODULE_NAME -v MODULE_NAME_C=$MODULE_NAME_C -v TC_DIR=$TC_DIR '
+    BEGIN {
+        set = ""
+print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+print "    <?xml-stylesheet type=\"text/xsl\" href=\"./testcase.xsl\"?>";
+print "<test_definition>";
+print "  <suite name=\"tct-"MODULE_NAME"-core-tests\" category=\"Core APIs\">";
+    }
+    {
+        if (set != "" && set != $2) {
+print "    </set>"
+        }
+
+        if (set != $2) {
+            set = $2;
+print "    <set name=\"" set "\">";
+        }
+
+        tcname = $1;
+        tcpurpose = $3
+
+print "      <testcase component=\"CoreAPI/" MODULE_NAME_C "/" set "\" execution_type=\"auto\" id=\"" tcname "\" purpose=\"" tcpurpose "\">";
+print "        <description>";
+
+print "          <test_script_entry test_script_expected_result=\"0\">" TC_DIR "/tct-" MODULE_NAME "-core " tcname "</test_script_entry>";
+print "        </description>";
+print "      </testcase>";
+    }
+    END {
+        if (set != "") {
+print "    </set>"
+        }
+print "  </suite>"
+print "</test_definition>"
+    }' $TFILE > $FILE
+}
+
+(cd $SCRIPT_DIR/..; scripts/retriever.sh -f src/$MODULE_NAME $4 > ${TFILE}_pre)
+if [ $? -ne 0 ]; then cat ${TFILE}_pre; exit 1; fi
+cat ${TFILE}_pre | sort -t',' -k2,2 -s > $TFILE
+gen
diff --git a/automated-tests/src/CMakeLists.txt b/automated-tests/src/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e4f0a2b
--- /dev/null
@@ -0,0 +1,6 @@
+IF( DEFINED MODULE )
+    MESSAGE(STATUS "Building: ${CMAKE_CURRENT_SOURCE_DIR}/${MODULE}")
+    ADD_SUBDIRECTORY(${MODULE})
+ELSE( DEFINED MODULE )
+    MESSAGE(FATAL_ERROR "No module selected to build. Aborting...")
+ENDIF( DEFINED MODULE )
diff --git a/automated-tests/src/common/assert.h b/automated-tests/src/common/assert.h
new file mode 100644 (file)
index 0000000..a5d6cff
--- /dev/null
@@ -0,0 +1,82 @@
+#ifndef _ASSERT_H_
+#define _ASSERT_H_
+#include <stdio.h>
+#include <stdlib.h>
+
+#define assert(exp) \
+    if (!(exp)) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Following expression is not true:\n" \
+                "%s\n", #exp); \
+        return 1; \
+    }
+
+#define assert_eq(var, ref) \
+    if (var != ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Values \"%s\" and \"%s\" are not equal:\n" \
+                "%s == %d, %s == %d\n", \
+            #var, #ref, #var, (int)var, #ref, (int)ref); \
+        return 1; \
+    }
+
+#define assert_neq(var, ref) \
+    if (var == ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Values \"%s\" and \"%s\" are equal:\n" \
+                "%s == %s == %d\n", \
+            #var, #ref, #var, #ref, (int)ref); \
+        return 1; \
+    }
+
+#define assert_gt(var, ref) \
+    if (var <= ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Value \"%s\" is not greater than \"%s\":\n" \
+                "%s == %d, %s == %d\n", \
+            #var, #ref, #var, var, #ref, ref); \
+        return 1; \
+    }
+
+#define assert_geq(var, ref) \
+    if (var < ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Value \"%s\" is not greater or equal to \"%s\":\n" \
+                "%s == %d, %s == %d\n", \
+            #var, #ref, #var, var, #ref, ref); \
+        return 1; \
+    }
+
+#define assert_lt(var, ref) \
+    if (var >= ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Value \"%s\" is not lower than \"%s\":\n" \
+                "%s == %d, %s == %d\n", \
+            #var, #ref, #var, var, #ref, ref); \
+        return 1; \
+    }
+
+#define assert_leq(var, ref) \
+    if (var > ref) { \
+        fprintf(stderr, \
+            "Assert fail in %s:%d\n", __FILE__, __LINE__); \
+        fprintf(stderr, \
+            "Value \"%s\" is not lower or equal to \"%s\":\n" \
+                "%s == %d, %s == %d\n", \
+            #var, #ref, #var, var, #ref, ref); \
+        return 1; \
+    }
+
+#endif //  _ASSERT_H_
diff --git a/automated-tests/src/common/signal-helper.h b/automated-tests/src/common/signal-helper.h
new file mode 100644 (file)
index 0000000..b1f555f
--- /dev/null
@@ -0,0 +1,1082 @@
+#ifndef SIGNAL_HELPER
+#define SIGNAL_HELPER
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Helper classes for testing DALi signal and slots
+
+class TestButton
+{
+public:
+
+  TestButton( unsigned int id )
+  : mId(id)
+  {
+  }
+
+  void Press()
+  {
+    mPanelDown.Emit( *this );
+  }
+
+  void Release()
+  {
+    mPanelUp.Emit( *this );
+  }
+
+  typedef Signal< void (TestButton&) > PanelDownSignal;
+  typedef Signal< void (TestButton&) > PanelUpSignal;
+
+  PanelDownSignal& DownSignal()
+  {
+    return mPanelDown;
+  }
+
+  PanelUpSignal& SignalUp()
+  {
+    return mPanelUp;
+  }
+
+  int GetId()
+  {
+    return mId;
+  }
+
+private:
+
+  int mId;
+  PanelDownSignal mPanelDown;
+  PanelUpSignal   mPanelUp;
+};
+
+class TestApp : public ConnectionTracker
+{
+public:
+
+  TestApp()
+  : mButtonPressed( false ),
+    mVoidFunctionCalled( false )
+  {
+  }
+
+  void OnButtonPress( TestButton& button )
+  {
+    mButtonPressed = true;
+    mButtonId = button.GetId();
+  }
+
+  void OnButtonRelease( TestButton& button )
+  {
+    mButtonPressed = false;
+    mButtonId = button.GetId();
+  }
+
+  int GetButtonPressedId()
+  {
+    return mButtonId;
+  }
+
+  bool BoolReturnTestFalse()
+  {
+    return false;
+  }
+
+  bool BoolReturnTestTrue()
+  {
+    return true;
+  }
+
+  void VoidFunction()
+  {
+    mVoidFunctionCalled = true;
+  }
+
+  bool mButtonPressed;
+  bool mVoidFunctionCalled;
+  int mButtonId;
+};
+
+class TestSignals
+{
+public:
+
+  // Void return, no parameters
+  typedef Signal<void ()> VoidRetNoParamSignal;
+
+  // Void return, 1 value parameter
+  typedef Signal<void (int)> VoidRet1ValueParamSignal;
+
+  // Void return, 1 reference parameter
+  typedef Signal< void (int&)> VoidRet1RefParamSignal;
+
+  // Void return, 2 value parameters
+  typedef Signal<void (int, int)> VoidRet2ValueParamSignal;
+
+  // Void return, 3 value parameters
+  typedef Signal<void (int, int, int)> VoidRet3ValueParamSignal;
+
+  // bool return, 1 value parameter
+  typedef Signal< bool (float)> BoolRet1ValueParamSignal;
+
+  // bool return, 2 value parameter
+  typedef Signal<bool (float, int) > BoolRet2ValueParamSignal;
+
+  // int return, 2 value parameter
+  typedef Signal<int (float, int)> IntRet2ValueParamSignal;
+
+  // float return, 0 parameters
+  typedef Signal< float () > FloatRet0ParamSignal;
+
+  // float return, 1 value parameters
+   typedef Signal< float (float ) > FloatRet1ParamSignal;
+
+  // float return, 2 value parameters
+  typedef Signal<float (float, float) > FloatRet2ValueParamSignal;
+
+  // float return, 3 value parameters
+  typedef Signal<float (float, float, float) > FloatRet3ValueParamSignal;
+
+  // void return, 3 value parameters
+  typedef Signal<void (float, float, float) > VoidSignalTypeFloatValue3;
+
+
+  VoidRetNoParamSignal&       SignalVoidNone()    { return mSignalVoid0;  }
+  VoidRet1RefParamSignal&     SignalVoid1Ref()    { return mSignalVoid1R; }
+  VoidRet1ValueParamSignal&   SignalVoid1Value()  { return mSignalVoid1V; }
+  VoidRet2ValueParamSignal&   SignalVoid2Value()  { return mSignalVoid2V; }
+  VoidRet3ValueParamSignal&   SignalVoid3Value()  { return mSignalVoid3V; }
+
+  BoolRet1ValueParamSignal&   SignalBool1Value()  { return mSignalBool1V;  }
+  BoolRet2ValueParamSignal&   SignalBool2Value()  { return mSignalBool2V;  }
+  IntRet2ValueParamSignal&    SignalInt2Value()   { return mSignalInt2V;   }
+  FloatRet0ParamSignal&       SignalFloat0()      { return mSignalFloat0;  }
+  FloatRet1ParamSignal&       SignalFloat1Value() {return  mSignalFloat1V; }
+  FloatRet2ValueParamSignal&  SignalFloat2Value() { return mSignalFloat2V; }
+
+  VoidSignalTypeFloatValue3&  VoidSignalFloatValue3()  { return mVoidSignalFloatValue3;  }
+  FloatRet3ValueParamSignal& SignalFloat3Value() { return mFloatSignalFloatValue3; }
+
+  TestSignals()
+  {
+  }
+
+  void CheckNoConnections()
+  {
+    DALI_TEST_EQUALS( mSignalVoid0.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalVoid1R.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalVoid1V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalVoid2V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalVoid3V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalBool1V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalBool2V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalInt2V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalFloat0.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalFloat1V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mSignalFloat2V.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mVoidSignalFloatValue3.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mFloatSignalFloatValue3.GetConnectionCount(), 0u, TEST_LOCATION );
+  }
+
+  void EmitVoidSignalVoid()
+  {
+    mSignalVoid0.Emit();
+  }
+
+  void EmitVoidSignalIntRef(int& ref)
+  {
+    mSignalVoid1R.Emit(ref);
+  }
+
+  void EmitVoidSignal1IntValue(int p1)
+  {
+    mSignalVoid1V.Emit(p1);
+  }
+
+  void EmitVoidSignal2IntValue(int p1, int p2)
+  {
+    mSignalVoid2V.Emit(p1,p2);
+  }
+
+  void EmitVoidSignal3IntValue(int p1, int p2, int p3)
+  {
+    mSignalVoid3V.Emit(p1,p2,p3);
+  }
+
+
+  bool EmitBoolSignalFloatValue(float p1)
+  {
+    return mSignalBool1V.Emit(p1);
+  }
+
+  bool EmitBoolSignalFloatValueIntValue(float p1, int p2)
+  {
+    return mSignalBool2V.Emit(p1, p2);
+  }
+
+  int EmitIntSignalFloatValueIntValue(float p1, int p2)
+  {
+    return mSignalInt2V.Emit(p1, p2);
+  }
+
+  float EmitFloat1VSignal(float p1 )
+  {
+    return mSignalFloat1V.Emit(p1 );
+  }
+
+  float EmitFloat2VSignal(float p1, float p2)
+  {
+    return mSignalFloat2V.Emit(p1, p2);
+  }
+
+  float EmitFloat0Signal()
+  {
+    return mSignalFloat0.Emit();
+  }
+
+  void EmitVoidSignalFloatValue3(float p1, float p2, float p3)
+  {
+    mVoidSignalFloatValue3.Emit(p1, p2, p3);
+  }
+
+  float EmitFloat3VSignal(float p1, float p2, float p3)
+  {
+    return mFloatSignalFloatValue3.Emit(p1, p2, p3);
+  }
+
+private:
+
+  VoidRetNoParamSignal         mSignalVoid0;
+  VoidRet1RefParamSignal       mSignalVoid1R;
+  VoidRet1ValueParamSignal     mSignalVoid1V;
+  VoidRet2ValueParamSignal     mSignalVoid2V;
+  VoidRet3ValueParamSignal     mSignalVoid3V;
+
+  BoolRet1ValueParamSignal     mSignalBool1V;
+  BoolRet2ValueParamSignal     mSignalBool2V;
+  IntRet2ValueParamSignal      mSignalInt2V;
+  FloatRet0ParamSignal         mSignalFloat0;
+  FloatRet1ParamSignal         mSignalFloat1V;
+  FloatRet2ValueParamSignal    mSignalFloat2V;
+  VoidSignalTypeFloatValue3    mVoidSignalFloatValue3;
+  FloatRet3ValueParamSignal   mFloatSignalFloatValue3;
+};
+
+/**
+ * A helper class with various slots
+ */
+class TestSlotHandler : public ConnectionTracker
+{
+public:
+
+  TestSlotHandler()
+  : mIntParam1( 0 ),
+    mIntParam2( 0 ),
+    mIntParam3( 0 ),
+    mFloatParam1( 0.0f ),
+    mFloatParam2( 0.0f ),
+    mFloatParam3( 0.0f ),
+    mBoolReturn( false ),
+    mIntReturn( 0 ),
+    mFloatReturn( 0.0f ),
+    mHandled( false ),
+    mHandledCount( 0 )
+  {
+  }
+
+  void Reset()
+  {
+    mIntParam1 = 0;
+    mIntParam2 = 0;
+    mIntParam3 = 0;
+    mFloatParam1 = 0.0f;
+    mFloatParam2 = 0.0f;
+    mFloatParam3 = 0.0f;
+    mBoolReturn = false;
+    mIntReturn = 0;
+    mFloatReturn = 0.0f;
+    mHandled = false;
+  }
+
+  void VoidSlotVoid()
+  {
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotVoidAlternative()
+  {
+     mHandled = true;
+     ++mHandledCount;
+  }
+
+  void VoidSlotIntRef( int& p1 )
+  {
+    mIntParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotIntValue( int p1 )
+  {
+    mIntParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidDuplicateSlotIntValue( int p1 )
+  {
+    mIntParam2 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotIntValueIntValue( int p1, int p2 )
+  {
+    mIntParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  bool BoolSlotFloatValue( float p1 )
+  {
+    mFloatParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+    return mBoolReturn;
+  }
+
+  bool BoolSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mBoolReturn;
+  }
+
+  int IntSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mIntReturn;
+  }
+
+  float FloatSlotVoid()
+  {
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  float FloatSlotFloatValueFloatValue( float p1, float p2 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  void VoidSlotFloatValue3( float p1, float p2, float p3 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mFloatParam3 = p3;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  float FloatSlotFloatValue3( float p1, float p2, float p3 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mFloatParam3 = p3;
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  int mIntParam1, mIntParam2, mIntParam3;
+  float mFloatParam1, mFloatParam2, mFloatParam3;
+  bool mBoolReturn;
+  int mIntReturn;
+  float mFloatReturn;
+  bool mHandled;
+  int mHandledCount;
+};
+
+/**
+ * A version of TestSlotHandler which disconnects during the callback
+ */
+class TestSlotDisconnector : public ConnectionTracker
+{
+public:
+
+  TestSlotDisconnector()
+  : mIntParam1( 0 ),
+    mIntParam2( 0 ),
+    mIntParam3( 0 ),
+    mFloatParam1( 0.0f ),
+    mFloatParam2( 0.0f ),
+    mBoolReturn( false ),
+    mIntReturn( 0 ),
+    mFloatReturn( 0.0f ),
+    mHandled( false )
+  {
+  }
+
+  void Reset()
+  {
+    mIntParam1 = 0;
+    mIntParam2 = 0;
+    mIntParam3 = 0;
+    mFloatParam1 = 0.0f;
+    mFloatParam2 = 0.0f;
+    mBoolReturn = false;
+    mIntReturn = 0;
+    mFloatReturn = 0.0f;
+    mHandled = false;
+  }
+
+  void VoidConnectVoid( TestSignals::VoidRetNoParamSignal& signal )
+  {
+    mVoidSignalVoid = &signal;
+    signal.Connect( this, &TestSlotDisconnector::VoidSlotVoid );
+  }
+
+  void VoidSlotVoid()
+  {
+    mVoidSignalVoid->Disconnect( this, &TestSlotDisconnector::VoidSlotVoid );
+    mHandled = true;
+  }
+
+  void VoidConnectIntRef( TestSignals::VoidRet1RefParamSignal& signal )
+  {
+    mVoidSignalIntRef = &signal;
+    signal.Connect( this, &TestSlotDisconnector::VoidSlotIntRef );
+  }
+
+  void VoidSlotIntRef( int& p1 )
+  {
+    mVoidSignalIntRef->Disconnect( this, &TestSlotDisconnector::VoidSlotIntRef );
+    mIntParam1 = p1;
+    mHandled = true;
+  }
+
+  void VoidSlotIntValue( int p1 )
+  {
+    mIntParam1 = p1;
+    mHandled = true;
+  }
+
+  void VoidSlotIntValueIntValue( int p1, int p2 )
+  {
+    mIntParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+  }
+
+  bool BoolSlotFloatValue( float p1 )
+  {
+    mFloatParam1 = p1;
+    mHandled = true;
+    return mBoolReturn;
+  }
+
+  bool BoolSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    return mBoolReturn;
+  }
+
+  int IntSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    return mIntReturn;
+  }
+
+  float FloatSlotVoid()
+  {
+    mHandled = true;
+    return mFloatReturn;
+  }
+
+  float FloatSlotFloatValueFloatValue( float p1, float p2 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mHandled = true;
+    return mFloatReturn;
+  }
+
+  TestSignals::VoidRetNoParamSignal*   mVoidSignalVoid;
+  TestSignals::VoidRet1RefParamSignal* mVoidSignalIntRef;
+
+  int mIntParam1, mIntParam2, mIntParam3;
+  float mFloatParam1, mFloatParam2;
+  bool mBoolReturn;
+  int mIntReturn;
+  float mFloatReturn;
+  bool mHandled;
+};
+
+/**
+ * A more complicated version of TestSlotDisconnector, which disconnects some but not all callbacks
+ */
+class TestSlotMultiDisconnector : public ConnectionTracker
+{
+public:
+
+  static const int NUM_SLOTS = 10;
+
+  TestSlotMultiDisconnector()
+  : mVoidSignalVoid( NULL )
+  {
+    Reset();
+  }
+
+  void Reset()
+  {
+    for( int i=0; i<NUM_SLOTS; ++i )
+    {
+      mSlotHandled[i] = false;
+    }
+  }
+
+  void ConnectAll( TestSignals::VoidRetNoParamSignal& signal )
+  {
+    mVoidSignalVoid = &signal;
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot0 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot1 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot2 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot3 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot4 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot5 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot6 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot7 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot8 );
+    signal.Connect( this, &TestSlotMultiDisconnector::Slot9 );
+  }
+
+  void Slot0()
+  {
+    mSlotHandled[0] = true;
+  }
+
+  void Slot1()
+  {
+    mSlotHandled[1] = true;
+  }
+
+  void Slot2()
+  {
+    mSlotHandled[2] = true;
+  }
+
+  void Slot3()
+  {
+    mSlotHandled[3] = true;
+
+    // Disconnect the odd numbered lots, because we can
+    mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot1 );
+    mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot3 );
+    mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot5 );
+    mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot7 );
+    mVoidSignalVoid->Disconnect( this, &TestSlotMultiDisconnector::Slot9 );
+  }
+
+  void Slot4()
+  {
+    mSlotHandled[4] = true;
+  }
+
+  void Slot5()
+  {
+    mSlotHandled[5] = true;
+  }
+
+  void Slot6()
+  {
+    mSlotHandled[6] = true;
+  }
+
+  void Slot7()
+  {
+    mSlotHandled[7] = true;
+  }
+
+  void Slot8()
+  {
+    mSlotHandled[8] = true;
+  }
+
+  void Slot9()
+  {
+    mSlotHandled[9] = true;
+  }
+
+  TestSignals::VoidRetNoParamSignal* mVoidSignalVoid;
+
+  bool mSlotHandled[NUM_SLOTS];
+};
+
+
+/**
+ * A version of TestSlotHandler which disconnects during the callback
+ */
+class TestEmitDuringCallback : public ConnectionTracker
+{
+public:
+
+  TestEmitDuringCallback()
+  : mVoidSignalVoid( NULL ),
+    mFloatRet0ParamSignal( NULL),
+    mFloatRet1ParamSignal( NULL ),
+    mFloatRet2ParamSignal( NULL ),
+    mFloatRet3ParamSignal( NULL ),
+    mHandled( false )
+  {
+  }
+
+  void VoidConnectVoid( TestSignals::VoidRetNoParamSignal& signal )
+  {
+    mVoidSignalVoid = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::VoidSlotVoid );
+  }
+
+  void FloatRet0ParamConnect( TestSignals::FloatRet0ParamSignal& signal )
+  {
+    mFloatRet0ParamSignal = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::FloatRet0Param );
+  }
+  void FloatRet1ParamConnect( TestSignals::FloatRet1ParamSignal& signal )
+  {
+    mFloatRet1ParamSignal = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::FloatRet1Param );
+  }
+  void FloatRet2ParamConnect( TestSignals::FloatRet2ValueParamSignal& signal )
+  {
+    mFloatRet2ParamSignal = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::FloatRet2Param );
+  }
+  void FloatRet3ParamConnect( TestSignals::FloatRet3ValueParamSignal& signal )
+  {
+    mFloatRet3ParamSignal = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::FloatRet3Param );
+  }
+
+  void DeleteDuringEmitConnect( TestSignals::VoidRetNoParamSignal& signal )
+  {
+    mVoidSignalVoid = &signal;
+    signal.Connect( this, &TestEmitDuringCallback::DeleteSignalDuringEmit );
+  }
+
+  void VoidSlotVoid()
+  {
+    // Emitting during Emit is very bad!
+    mVoidSignalVoid->Emit();
+    mHandled = true;
+  }
+
+  void DeleteSignalDuringEmit()
+  {
+    // deleting the signal during the emit
+    delete mVoidSignalVoid;
+  }
+
+  float FloatRet0Param()
+  {
+     // Emitting during Emit is very bad!
+    mHandled = true;
+    return mFloatRet0ParamSignal->Emit();
+  }
+  float FloatRet1Param( float x )
+  {
+    // Emitting during Emit is very bad!
+    mHandled = true;
+    return mFloatRet1ParamSignal->Emit(x);
+  }
+  float FloatRet2Param( float x, float y )
+  {
+    // Emitting during Emit is very bad!
+    mHandled = true;
+    return mFloatRet2ParamSignal->Emit( x, y );
+  }
+  float FloatRet3Param( float x, float y, float z)
+  {
+    // Emitting during Emit is very bad!
+    mHandled = true;
+    return mFloatRet3ParamSignal->Emit( x, y, z );
+  }
+
+  TestSignals::VoidRetNoParamSignal* mVoidSignalVoid;
+  TestSignals::FloatRet0ParamSignal*      mFloatRet0ParamSignal;
+  TestSignals::FloatRet1ParamSignal* mFloatRet1ParamSignal;
+  TestSignals::FloatRet2ValueParamSignal* mFloatRet2ParamSignal;
+  TestSignals::FloatRet3ValueParamSignal* mFloatRet3ParamSignal;
+
+
+  bool mHandled;
+};
+
+
+/**
+ * A version of TestSlotHandler which uses SlotDelegate
+ */
+class TestSlotDelegateHandler // This does not inherit from ConnectionTrackerInterface!
+{
+public:
+
+  TestSlotDelegateHandler()
+  : mSlotDelegate( this ),
+    mIntParam1( 0 ),
+    mIntParam2( 0 ),
+    mIntParam3( 0 ),
+    mFloatParam1( 0.0f ),
+    mFloatParam2( 0.0f ),
+    mFloatParam3( 0.0f ),
+    mBoolReturn( false ),
+    mIntReturn( 0 ),
+    mFloatReturn( 0.0f ),
+    mHandled( false ),
+    mHandledCount( 0 )
+  {
+  }
+
+  void Reset()
+  {
+    mIntParam1 = 0;
+    mIntParam2 = 0;
+    mIntParam3 = 0;
+    mFloatParam1 = 0.0f;
+    mFloatParam2 = 0.0f;
+    mFloatParam3 = 0.0f;
+    mBoolReturn = false;
+    mIntReturn = 0;
+    mFloatReturn = 0.0f;
+    mHandled = false;
+  }
+
+  void VoidSlotVoid()
+  {
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void AlternativeVoidSlotVoid()
+  {
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotIntRef( int& p1 )
+  {
+    mIntParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotIntValue( int p1 )
+  {
+    mIntParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidDuplicateSlotIntValue( int p1 )
+  {
+    mIntParam2 = p1;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  void VoidSlotIntValueIntValue( int p1, int p2 )
+  {
+    mIntParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  bool BoolSlotFloatValue( float p1 )
+  {
+    mFloatParam1 = p1;
+    mHandled = true;
+    ++mHandledCount;
+    return mBoolReturn;
+  }
+
+  bool BoolSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mBoolReturn;
+  }
+
+  int IntSlotFloatValueIntValue( float p1, int p2 )
+  {
+    mFloatParam1 = p1;
+    mIntParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mIntReturn;
+  }
+
+  float FloatSlotVoid()
+  {
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  float FloatSlotFloatValueFloatValue( float p1, float p2 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  void VoidSlotFloatValue3( float p1, float p2, float p3 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mFloatParam3 = p3;
+    mHandled = true;
+    ++mHandledCount;
+  }
+
+  float FloatSlotFloatValue3( float p1, float p2, float p3 )
+  {
+    mFloatParam1 = p1;
+    mFloatParam2 = p2;
+    mFloatParam3 = p3;
+    mHandled = true;
+    ++mHandledCount;
+    return mFloatReturn;
+  }
+
+  SlotDelegate<TestSlotDelegateHandler> mSlotDelegate;
+
+  int mIntParam1, mIntParam2, mIntParam3;
+  float mFloatParam1, mFloatParam2, mFloatParam3;
+  bool mBoolReturn;
+  int mIntReturn;
+  float mFloatReturn;
+  bool mHandled;
+  int mHandledCount;
+};
+
+/**
+ * Test that reimplmenting ConnectionTrackerInterface actually works.
+ * This basic connection tracker only allows one callback to be connected.
+ */
+class TestBasicConnectionTrackerInterface : public ConnectionTrackerInterface
+{
+public:
+
+  TestBasicConnectionTrackerInterface()
+  : mCallbackHandled( false ),
+    mCallback( NULL ),
+    mSlotObserver( NULL )
+  {
+  }
+
+  ~TestBasicConnectionTrackerInterface()
+  {
+    if( mSlotObserver && mCallback )
+    {
+      // Notify signal since the slot has been destroyed
+      mSlotObserver->SlotDisconnected( mCallback );
+      // mCallback and mSlotObserver are not owned
+    }
+  }
+
+  /**
+   * An example slot
+   */
+  void VoidSlotVoid()
+  {
+    mCallbackHandled = true;
+  }
+
+  /**
+   * @copydoc ConnectionTrackerInterface::GetConnectionCount
+   */
+  virtual std::size_t GetConnectionCount() const
+  {
+    if( mCallback )
+    {
+      return 1u;
+    }
+
+    return 0u;
+  }
+
+  /**
+   * @copydoc ConnectionTrackerInterface::SignalConnected
+   */
+  virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
+  {
+    DALI_ASSERT_ALWAYS( NULL == mCallback && "Only one connection supported!" );
+
+    mCallback = callback;
+    mSlotObserver = slotObserver;
+  }
+
+  /**
+   * @copydoc ConnectionTrackerInterface::SignalDisconnected
+   */
+  virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback )
+  {
+    if( mSlotObserver == slotObserver )
+    {
+      mSlotObserver = NULL;
+      mCallback = NULL;
+      // mCallback and mSlotObserver are not owned
+    }
+  }
+
+  /**
+   * RemoveNullCallback,
+   * testing what occurs when we pass a callback that doesn't exist
+   */
+  void RemoveNullCallback()
+  {
+    mSlotObserver->SlotDisconnected( NULL );
+  }
+
+private:
+
+  TestBasicConnectionTrackerInterface( const TestBasicConnectionTrackerInterface& );            ///< undefined copy constructor
+  TestBasicConnectionTrackerInterface& operator=( const TestBasicConnectionTrackerInterface& ); ///< undefined assignment operator
+
+public:
+
+  bool mCallbackHandled;
+
+private:
+
+  CallbackBase* mCallback;     ///< callback, has ownership
+  SlotObserver* mSlotObserver; ///< a pointer to the slot observer (not owned)
+};
+
+
+
+
+// for testing static function callbacks
+class StaticFunctionHandlers
+{
+public:
+    StaticFunctionHandlers()
+    {
+      staticFunctionHandled = false;
+    }
+    void Reset()
+    {
+      staticFunctionHandled = false;
+    }
+
+    static void VoidSlotVoid()
+    {
+      staticFunctionHandled = true;
+    }
+    static void VoidSlot1Param( int p1 )
+    {
+      staticFunctionHandled = true;
+    }
+    static void VoidSlot2Param( int p1, int p2 )
+    {
+      staticFunctionHandled = true;
+    }
+    static void VoidSlot3Param( int p1, int p2, int p3 )
+    {
+      staticFunctionHandled = true;
+    }
+
+    static float RetSlot0Param( )
+    {
+      staticFunctionHandled = true;
+      return 0;
+    }
+    static float RetSlot1Param( float p1 )
+    {
+      staticFunctionHandled = true;
+      return 0;
+    }
+    static float RetSlot2Param( float p1, float p2 )
+    {
+      staticFunctionHandled = true;
+      return 0;
+    }
+    static float RetSlot3Param( float p1, float p2, float p3 )
+    {
+      staticFunctionHandled = true;
+      return 0;
+    }
+
+    static bool staticFunctionHandled;
+};
+
+
+/**
+ * test functor, we store a reference to a bool which is outside of the functor
+ * so when the functor is copied, the copy can reference the original data
+ */
+struct TestFunctor
+{
+  TestFunctor( bool& functorCalled):
+    mFunctorCalled( functorCalled )
+  {
+  };
+
+  void operator()()
+  {
+    mFunctorCalled = true;
+  }
+
+  bool& mFunctorCalled;
+};
+
+struct VoidFunctorVoid
+{
+  VoidFunctorVoid( bool& functorCalled):
+    mFunctorCalled( functorCalled )
+  {
+
+  }
+
+  void operator()()
+  {
+    mFunctorCalled = true;
+  }
+
+  bool& mFunctorCalled;
+};
+
+#endif // #define SIGNAL_HELPER
diff --git a/automated-tests/src/common/testcase.h b/automated-tests/src/common/testcase.h
new file mode 100644 (file)
index 0000000..011a452
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _TESTCASE_H_
+#define _TESTCASE_H_
+
+/* pointer to startup/cleanup functions */
+typedef void (*void_fun_ptr)(void);
+
+/* pointer to testcase functions */
+typedef int (*tc_fun_ptr)(void);
+
+/* struct describing specific testcase */
+typedef struct testcase_s {
+    const char* name;
+    tc_fun_ptr function;
+    void_fun_ptr startup;
+    void_fun_ptr cleanup;
+} testcase;
+
+#endif // _TESTCASE_H_
diff --git a/automated-tests/src/dali-devel/CMakeLists.txt b/automated-tests/src/dali-devel/CMakeLists.txt
new file mode 100644 (file)
index 0000000..84d2028
--- /dev/null
@@ -0,0 +1,67 @@
+SET(PKG_NAME "dali-devel")
+
+SET(EXEC_NAME "tct-${PKG_NAME}-core")
+SET(RPM_NAME "core-${PKG_NAME}-tests")
+
+SET(CAPI_LIB "dali-devel")
+
+SET(TC_SOURCES
+        utc-Dali-Actor.cpp
+        utc-Dali-Atlas.cpp
+        utc-Dali-Context.cpp
+        utc-Dali-Constrainer.cpp
+        utc-Dali-CullFace.cpp
+        utc-Dali-DistanceField.cpp
+        utc-Dali-Geometry.cpp
+        utc-Dali-Hash.cpp
+        utc-Dali-HitTestAlgorithm.cpp
+        utc-Dali-Material.cpp
+        utc-Dali-Mutex.cpp
+        utc-Dali-PropertyBuffer.cpp
+        utc-Dali-Renderer.cpp
+        utc-Dali-Sampler.cpp
+        utc-Dali-Scripting.cpp
+        utc-Dali-Shader.cpp
+        utc-Dali-WeakHandle.cpp
+)
+
+LIST(APPEND TC_SOURCES
+        ../dali/dali-test-suite-utils/mesh-builder.cpp
+        ../dali/dali-test-suite-utils/dali-test-suite-utils.cpp
+        ../dali/dali-test-suite-utils/test-harness.cpp
+        ../dali/dali-test-suite-utils/test-application.cpp
+        ../dali/dali-test-suite-utils/test-gesture-manager.cpp
+        ../dali/dali-test-suite-utils/test-gl-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-native-image.cpp
+        ../dali/dali-test-suite-utils/test-platform-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-render-controller.cpp
+        ../dali/dali-test-suite-utils/test-trace-call-stack.cpp
+)
+
+PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
+     dali-core
+)
+
+SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type")
+
+FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
+    SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}")
+ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS})
+
+INCLUDE_DIRECTORIES(
+    ../../..
+    .
+    ${${CAPI_LIB}_INCLUDE_DIRS}
+    ../dali/dali-test-suite-utils
+)
+
+ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES})
+TARGET_LINK_LIBRARIES(${EXEC_NAME}
+    ${${CAPI_LIB}_LIBRARIES}
+    -lpthread
+)
+
+INSTALL(PROGRAMS ${EXEC_NAME}
+    DESTINATION ${BIN_DIR}/${EXEC_NAME}
+)
diff --git a/automated-tests/src/dali-devel/tct-dali-devel-core.cpp b/automated-tests/src/dali-devel/tct-dali-devel-core.cpp
new file mode 100644 (file)
index 0000000..69d3233
--- /dev/null
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <test-harness.h>
+#include "tct-dali-devel-core.h"
+
+int main(int argc, char * const argv[])
+{
+  int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT;
+
+  const char* optString = "r";
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'r':
+        optRerunFailed = true;
+        break;
+      case '?':
+        TestHarness::Usage(argv[0]);
+        exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT);
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optind == argc ) // no testcase name in argument list
+  {
+    result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed);
+  }
+  else
+  {
+    // optind is index of next argument - interpret as testcase name
+    result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]);
+  }
+  return result;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Actor.cpp b/automated-tests/src/dali-devel/utc-Dali-Actor.cpp
new file mode 100644 (file)
index 0000000..7322fa4
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <mesh-builder.h>
+
+//& set: DaliActor
+
+using std::string;
+using namespace Dali;
+
+
+int UtcDaliActorAddRendererP(void)
+{
+  tet_infoline("Testing Actor::AddRenderer");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  actor.AddRenderer( renderer );
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetRendererAt(0), renderer, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorAddRendererN(void)
+{
+  tet_infoline("Testing Actor::AddRenderer");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Renderer renderer;
+
+  // try illegal Add
+  try
+  {
+    actor.AddRenderer( renderer );
+    tet_printf("Assertion test failed - no Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "Renderer handle is empty", TEST_LOCATION);
+    DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliActorAddRendererOnStage(void)
+{
+  tet_infoline("Testing Actor::AddRenderer");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  application.SendNotification();
+  application.Render(0);
+
+  try
+  {
+    actor.AddRenderer( renderer );
+    tet_result(TET_PASS);
+  }
+  catch(...)
+  {
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliActorRemoveRendererP(void)
+{
+  tet_infoline("Testing Actor::RemoveRenderer");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  actor.AddRenderer( renderer );
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetRendererAt(0), renderer, TEST_LOCATION );
+
+  actor.RemoveRenderer(0);
+  DALI_TEST_EQUALS( actor.GetRendererCount(), 0u, TEST_LOCATION );
+
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Atlas.cpp b/automated-tests/src/dali-devel/utc-Dali-Atlas.cpp
new file mode 100644 (file)
index 0000000..ef83df1
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/devel-api/images/atlas.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+
+using namespace Dali;
+
+namespace
+{
+static const char* gTestImageFilename = "icon_wrt.png";
+
+void PrepareResourceImage( TestApplication& application, unsigned int imageHeight, unsigned int imageWidth, Pixel::Format pixelFormat )
+{
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  platform.SetClosestImageSize(Vector2( 16, 16));
+
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat, imageWidth, imageHeight, imageWidth, imageHeight );
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+  unsigned int initialColor = 0xFF;
+  memset( pixbuffer, initialColor, imageHeight*imageWidth*bytesPerPixel);
+
+  Integration::ResourcePointer resourcePtr(bitmap);
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+}
+
+}
+
+void utc_dali_atlas_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_atlas_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+// 1.1
+int UtcDaliAtlasNew01(void)
+{
+  TestApplication application;
+
+  // invoke default handle constructor
+  Atlas atlas;
+
+  DALI_TEST_CHECK( !atlas );
+
+  // initialise handle
+  atlas = Atlas::New( 16, 16 );
+
+  DALI_TEST_CHECK( atlas );
+  END_TEST;
+}
+
+
+// 1.2
+int UtcDaliAtlasUpload01(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using correct pixel format
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( image, 0, 0 ) );
+
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.3
+int UtcDaliAtlasUpload02(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using INCORRECT pixel format
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::A8 );
+  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+  PrepareResourceImage( application, 16, 16, Pixel::A8 );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.4
+int UtcDaliAtlasUpload03(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 10, 10, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using image too big for atlas
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( !atlas.Upload( image, 0, 0 ) );
+
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 0, 0 ) );
+
+  END_TEST;
+}
+
+// 1.5
+int UtcDaliAtlasUpload04(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using valid offsets
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( atlas.Upload( image,  0,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( image, 16,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( image,  0, 16 ) );
+  DALI_TEST_CHECK( atlas.Upload( image, 16, 16 ) );
+
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16,  0 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename,  0, 16 ) );
+  DALI_TEST_CHECK( atlas.Upload( gTestImageFilename, 16, 16 ) );
+
+  END_TEST;
+}
+
+// 1.6
+int UtcDaliAtlasUpload05(void)
+{
+  TestApplication application;
+
+  Atlas atlas = Atlas::New( 32, 32, Pixel::RGBA8888 );
+  DALI_TEST_CHECK( atlas );
+
+  // Using invalid offsets
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New( buffer, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( !atlas.Upload( image,  0, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 17,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 17, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 99,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image,  0, 99 ) );
+  DALI_TEST_CHECK( !atlas.Upload( image, 99, 99 ) );
+
+  PrepareResourceImage( application, 16, 16, Pixel::RGBA8888 );
+
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 17, 17 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99,  0 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename,  0, 99 ) );
+  DALI_TEST_CHECK( !atlas.Upload( gTestImageFilename, 99, 99 ) );
+
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp b/automated-tests/src/dali-devel/utc-Dali-Constrainer.cpp
new file mode 100644 (file)
index 0000000..076a9c2
--- /dev/null
@@ -0,0 +1,546 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/animation/path-constrainer.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Internal;
+
+namespace
+{
+
+static void SetupPath( Dali::Path& path)
+{
+  path.AddPoint(Vector3( 30.0,  80.0, 0.0));
+  path.AddPoint(Vector3( 70.0, 120.0, 0.0));
+  path.AddPoint(Vector3(100.0, 100.0, 0.0));
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0) );
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0) );
+}
+
+static void SetupPathConstrainer( Dali::PathConstrainer& PathConstrainer)
+{
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::FORWARD, Vector3(1.0f,0.0f,0.0f) );
+
+  Dali::Property::Array points;
+  points.Resize(3);
+  points[0] = Vector3( 30.0,  80.0, 0.0);
+  points[1] = Vector3( 70.0, 120.0, 0.0);
+  points[2] = Vector3(100.0, 100.0, 0.0);
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::POINTS, points );
+
+  points.Resize(4);
+  points[0] = Vector3( 39.0,  90.0, 0.0);
+  points[1] = Vector3( 56.0, 119.0, 0.0);
+  points[2] = Vector3( 78.0, 120.0, 0.0);
+  points[3] = Vector3( 93.0, 104.0, 0.0);
+  PathConstrainer.SetProperty( Dali::PathConstrainer::Property::CONTROL_POINTS, points );
+}
+
+static void SetupLinearConstrainerUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.Resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+}
+
+static void SetupLinearConstrainerNonUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.Resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+
+  points[0] = 0.0f;
+  points[1] = 0.25f;
+  points[2] = 1.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::PROGRESS, points );
+}
+
+} // anonymous namespace
+
+//PathConstrainer test cases
+int UtcPathConstrainerApply(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  Vector3 position, tangent;
+  path.Sample(0.2f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+  path.Sample(0.4f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+  path.Sample(0.6f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+  path.Sample(0.8f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 100% progress */);
+  path.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerApplyRange(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 100.0f, 300.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),400.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+
+  Vector3 position, tangent;
+  float tValue;
+  actor.GetProperty(index).Get(tValue);
+  float currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  path.Sample(0.5, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  actor.GetProperty(index).Get(tValue);
+  currentCursor =  ( tValue - range.x ) / (range.y-range.x);
+  path.Sample(currentCursor, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerDestroy(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  {
+    //Create a Path
+    Dali::Path path = Dali::Path::New();
+    SetupPath(path);
+
+    //Create a PathConstrainer
+    Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+    SetupPathConstrainer( pathConstrainer );
+
+    //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+    Vector2 range( 0.0f, 1.0f );
+    pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+    //Test that the constraint is correctly applied
+    actor.SetProperty(index,0.5f);
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(1.0f));
+
+    Vector3 position, tangent;
+    path.Sample(0.5f, position, tangent );
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  }
+
+  //PathConstrainer has been destroyed. Constraint in the actor should have been removed
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcPathConstrainerRemove(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a Path
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //Create a PathConstrainer
+  Dali::PathConstrainer pathConstrainer = Dali::PathConstrainer::New();
+  SetupPathConstrainer( pathConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  pathConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION), Property(actor,index), range );
+
+  //Test that the constraint is correctly applied
+  actor.SetProperty(index,0.5f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  Vector3 position, tangent;
+  path.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  //Remove constraint
+  pathConstrainer.Remove( actor );
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  END_TEST;
+}
+
+//LinearConstrainer test cases
+int UtcLinearConstrainerDownCast(void)
+{
+  TestApplication application;
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+
+  BaseHandle handle( linearConstrainer );
+  Dali::LinearConstrainer linearConstrainer2 = Dali::LinearConstrainer::DownCast( handle );
+  DALI_TEST_EQUALS( (bool)linearConstrainer2, true, TEST_LOCATION );
+
+  BaseHandle handle2;
+  Dali:: LinearConstrainer linearConstrainer3 = Dali::LinearConstrainer::DownCast( handle2 );
+  DALI_TEST_EQUALS( (bool)linearConstrainer3, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerCopyConstructor(void)
+{
+  TestApplication application;
+  Dali::LinearConstrainer linearConstrainer;
+  DALI_TEST_EQUALS( (bool)linearConstrainer, false, TEST_LOCATION );
+
+  linearConstrainer = Dali::LinearConstrainer::New();
+  DALI_TEST_EQUALS( (bool)linearConstrainer, true, TEST_LOCATION );
+
+  // call the copy constructor
+  Dali::LinearConstrainer linearConstrainer2( linearConstrainer );
+  DALI_TEST_EQUALS( (bool)linearConstrainer2, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerApply(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+
+  Dali::Stage::GetCurrent().Add(actor);
+
+
+  //Create a LinearConstrainer without specifying progress for values
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  //Setup a LinearConstrainer specifying the progress for each value
+  linearConstrainer.Remove(actor);
+  SetupLinearConstrainerNonUniformProgress( linearConstrainer );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  actor.SetProperty(index,0.0f);
+  animation.Play();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 2.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerApplyRange(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 100.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a LinearConstrainer
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 100.0f, 300.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),300.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerDestroy(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  {
+    //Create a LinearConstrainer
+    Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+    SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+    //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+    Vector2 range( 0.0f, 1.0f );
+    linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+    //Test that the constraint is correctly applied
+    actor.SetProperty(index,0.5f);
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(1.0f));
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  }
+
+  //LinearConstrainer has been destroyed. Constraint in the actor should have been removed
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcLinearConstrainerRemove(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+  Dali::Stage::GetCurrent().Add(actor);
+
+  //Create a LinearConstrainer
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the path constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  //Test that the constraint is correctly applied
+  actor.SetProperty(index,0.5f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  //Remove constraint
+  linearConstrainer.Remove( actor );
+  actor.SetProperty(index,0.75f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(1.0f));
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Context.cpp b/automated-tests/src/dali-devel/utc-Dali-Context.cpp
new file mode 100644 (file)
index 0000000..bdc5190
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+namespace
+{
+// Size of the VertexAttributeArray enables
+// GLES specification states that there's minimum of
+const unsigned int TEST_MAX_ATTRIBUTE_CACHE_SIZE = 8;
+
+enum TestAttribType
+{
+  ATTRIB_UNKNOWN = -1,
+  ATTRIB_POSITION,
+  ATTRIB_NORMAL,
+  ATTRIB_TEXCOORD,
+  ATTRIB_COLOR,
+  ATTRIB_BONE_WEIGHTS,
+  ATTRIB_BONE_INDICES,
+  ATTRIB_TYPE_LAST
+};
+
+// Create bitmap image
+static BufferImage CreateBufferImage()
+{
+  BufferImage image = BufferImage::New(4,4,Pixel::RGBA8888);
+
+  return image;
+}
+
+static ImageActor CreateImageActor()
+{
+  BufferImage image = CreateBufferImage();
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("Test ImageActor");
+  return actor;
+}
+
+} // anonymous namespace
+
+
+// Positive test case for a method
+int UtcDaliContextVertexAttribStartup(void)
+{
+  tet_infoline("Testing vertex attrib initial state in context");
+
+  TestApplication application;
+
+  // start up
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // context class should initially set the vertex attrib locations to disable
+  // Make sure it has been modified
+  DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged());
+
+  // check the locations
+  for (unsigned int i = 0; i < TEST_MAX_ATTRIBUTE_CACHE_SIZE; i++)
+  {
+    DALI_TEST_CHECK( application.GetGlAbstraction().GetVertexAttribArrayState(i) == false);
+  }
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
+
+// Tests to make the attribs only get set once when continually rendering an image actor
+int UtcDaliContextVertexAttribImageRendering(void)
+{
+  tet_infoline("Testing vertex attrib rendering state in context with images");
+
+  TestApplication application;
+
+  // start up
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // the vertex attribs get modified on startup to set them to disabled
+  // clear the flag to say they've changed
+  application.GetGlAbstraction().ClearVertexAttribArrayChanged();
+
+
+  // create a test image actor
+  ImageActor imageActor(CreateImageActor());
+  Stage::GetCurrent().Add(imageActor);
+
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // check to make sure the state has changed (the image renderer will enable some
+  // locations).
+  DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged());
+
+  // Now check to make sure the state is cached, and isn't being set each frame.
+  application.GetGlAbstraction().ClearVertexAttribArrayChanged();
+
+  application.Render();
+  application.Render();
+  application.Render();
+
+  // if it has changed then the caching has failed
+  DALI_TEST_CHECK(application.GetGlAbstraction().GetVertexAttribArrayChanged() == false);
+
+
+  tet_result(TET_PASS);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-CullFace.cpp b/automated-tests/src/dali-devel/utc-Dali-CullFace.cpp
new file mode 100644 (file)
index 0000000..5d980fe
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/rendering/cull-face.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void cull_face_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void cull_face_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliSetGetCullFaceP(void)
+{
+  TestApplication application;
+
+  ImageActor imageActor = ImageActor::New();
+
+  DALI_TEST_CHECK( CullNone == GetCullFace( imageActor ) );
+
+  SetCullFace( imageActor, CullBack );
+
+  DALI_TEST_CHECK( CullBack == GetCullFace( imageActor ) );
+
+  END_TEST;
+}
+
+int UtcDaliSetCullFaceN(void)
+{
+  TestApplication application;
+
+  try
+  {
+    ImageActor imageActor;
+    SetCullFace( imageActor, CullBack );
+    DALI_TEST_CHECK( false ); // Should not reach here.
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true ); // Should throw
+  }
+  END_TEST;
+}
+
+int UtcDaliGetCullFaceN(void)
+{
+  TestApplication application;
+
+  try
+  {
+    ImageActor imageActor;
+    CullFaceMode mode = GetCullFace( imageActor );
+    (void) mode;
+    DALI_TEST_CHECK( false ); // Should not reach here.
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true ); // Should throw
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp b/automated-tests/src/dali-devel/utc-Dali-DistanceField.cpp
new file mode 100644 (file)
index 0000000..b9ab2da
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+
+#include <stdlib.h>
+
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/images/distance-field.h>
+#include <dali-test-suite-utils.h>
+
+using std::max;
+using namespace Dali;
+
+namespace
+{
+
+static const float ROTATION_EPSILON = 0.0001f;
+
+static unsigned char sourceImage[] =
+{
+ 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+ 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+ 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+ 0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
+};
+
+} // anonymous namespace
+
+
+
+int UtcDaliGenerateDistanceField(void)
+{
+  unsigned char distanceField[4*4];
+
+  GenerateDistanceFieldMap(sourceImage, Size(8.0f, 8.0f), distanceField, Size(4.0f, 4.0f), 0, Size(4.0f, 4.0f));
+
+  if(distanceField[0]  <= distanceField[5] &&
+     distanceField[5]  <= distanceField[10] &&
+     distanceField[10] <= distanceField[15])
+  {
+    tet_result(TET_PASS);
+  }
+  else
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Geometry.cpp b/automated-tests/src/dali-devel/utc-Dali-Geometry.cpp
new file mode 100644 (file)
index 0000000..7933b06
--- /dev/null
@@ -0,0 +1,670 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/devel-api/rendering/renderer.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+void geometry_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void geometry_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.b = 0.0f;
+}
+
+struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+
+PropertyBuffer CreateVertexBuffer( const std::string& aPosition, const std::string& aTexCoord )
+{
+  const float halfQuadSize = .5f;
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+
+  Property::Map vertexFormat;
+  vertexFormat[aPosition] = Property::VECTOR2;
+  vertexFormat[aTexCoord] = Property::VECTOR2;
+
+  PropertyBuffer vertexData = PropertyBuffer::New( vertexFormat, 4 );
+  vertexData.SetData(texturedQuadVertexData);
+
+  return vertexData;
+}
+
+PropertyBuffer CreateIndexBuffer()
+{
+  unsigned short indexData[6] = { 0, 3, 1, 0, 2, 3 };
+  Property::Map indexFormat;
+  indexFormat["indices"] = Property::INTEGER;
+  PropertyBuffer indices = PropertyBuffer::New( indexFormat, 3 );
+  indices.SetData(indexData);
+
+  return indices;
+}
+
+}
+
+
+int UtcDaliGeometryNew01(void)
+{
+  TestApplication application;
+
+  Geometry geometry = Geometry::New();
+
+  DALI_TEST_EQUALS( (bool)geometry, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliGeometryNew02(void)
+{
+  TestApplication application;
+  Geometry geometry;
+  DALI_TEST_EQUALS( (bool)geometry, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliGeometryCopyConstructor(void)
+{
+  TestApplication application;
+
+  Geometry geometry = Geometry::New();
+
+  Geometry geometryCopy(geometry);
+
+  DALI_TEST_EQUALS( (bool)geometryCopy, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliGeometryAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Geometry geometry = Geometry::New();
+
+  Geometry geometry2;
+  DALI_TEST_EQUALS( (bool)geometry2, false, TEST_LOCATION );
+
+  geometry2 = geometry;
+  DALI_TEST_EQUALS( (bool)geometry2, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryDownCast01(void)
+{
+  TestApplication application;
+
+  Geometry geometry = Geometry::New();
+
+  BaseHandle handle(geometry);
+  Geometry geometry2 = Geometry::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)geometry2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliGeometryDownCast02(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New(); // Create a custom object
+  Geometry geometry = Geometry::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)geometry, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliGeometryAddVertexBuffer(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test AddVertexBuffer");
+
+  PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" );
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexBuffer1 );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+        application.GetGlAbstraction().GetBufferDataCalls();
+
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION );
+  }
+
+  // add the second vertex buffer
+  application.GetGlAbstraction().ResetBufferDataCalls();
+
+  PropertyBuffer vertexBuffer2 = CreateVertexBuffer( "aPosition2", "aTexCoord2" );
+  geometry.AddVertexBuffer( vertexBuffer2 );
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+        application.GetGlAbstraction().GetBufferDataCalls();
+
+    //Check that only the new buffer gets uploaded
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliGeometryGetNumberOfVertexBuffers(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetNumberOfVertexBuffers");
+  PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" );
+  PropertyBuffer vertexBuffer2 = CreateVertexBuffer("aPosition2", "aTexCoord2" );
+  PropertyBuffer vertexBuffer3 = CreateVertexBuffer("aPosition3", "aTexCoord3" );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexBuffer1 );
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION );
+
+  geometry.AddVertexBuffer( vertexBuffer2 );
+  geometry.AddVertexBuffer( vertexBuffer3 );
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 3u, TEST_LOCATION );
+
+  geometry.RemoveVertexBuffer( 2u );
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 2u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryRemoveVertexBuffer(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test RemoveVertexBuffer");
+
+  PropertyBuffer vertexBuffer1 = CreateVertexBuffer("aPosition1", "aTexCoord1" );
+  PropertyBuffer vertexBuffer2 = CreateVertexBuffer("aPosition2", "aTexCoord2" );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexBuffer1 );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION );
+
+  geometry.RemoveVertexBuffer( 0 );
+  geometry.AddVertexBuffer( vertexBuffer2 );
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 1u, TEST_LOCATION );
+
+  geometry.RemoveVertexBuffer( 0 );
+  DALI_TEST_EQUALS( geometry.GetNumberOfVertexBuffers(), 0u, TEST_LOCATION );
+
+  //Todo: test by checking the BufferDataCalls
+  // make sure the vertex buffer in actually removed from gl
+
+   END_TEST;
+}
+
+int UtcDaliGeometrySetIndexBuffer(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetIndexBuffer");
+
+  PropertyBuffer vertexBuffer = CreateVertexBuffer("aPosition", "aTexCoord" );
+  PropertyBuffer indexBuffer = CreateIndexBuffer( );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexBuffer );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+        application.GetGlAbstraction().GetBufferDataCalls();
+
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( bufferDataCalls[0], 4*sizeof( TexturedQuadVertex ), TEST_LOCATION );
+  }
+
+  // Set index buffer
+  application.GetGlAbstraction().ResetBufferDataCalls();
+
+  geometry.SetIndexBuffer( indexBuffer );
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+        application.GetGlAbstraction().GetBufferDataCalls();
+
+    //Only the index buffer should be uploaded
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+    // should be unsigned short instead of unsigned int
+    DALI_TEST_EQUALS( bufferDataCalls[0], 6*sizeof( unsigned short ), TEST_LOCATION );
+  }
+
+
+  END_TEST;
+}
+
+int UtcDaliGeometrySetGetGeometryType(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetGeometryType and GetGeometryType");
+
+  unsigned int numVertex = 4u;
+  PropertyBuffer vertexBuffer = CreateVertexBuffer("aPosition", "aTexCoord" );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexBuffer );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  /****************************************************/
+  // Default (TRIANGLES), no index buffer
+  drawTrace.Reset();
+  drawTrace.Enable(true);
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+  drawTrace.Enable( false );
+
+  // Test the default geometry type is GL_TRIANGLE
+  // no index buffer, call glDrawArrays,
+  DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION);
+  std::stringstream out;
+  out << GL_TRIANGLES << ", " << 0 << ", " << numVertex;
+  DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::TRIANGLES, TEST_LOCATION);
+
+  /*********************************************************/
+  // LINES, no index buffer
+  geometry.SetGeometryType( Geometry::LINES );
+
+  drawTrace.Reset();
+  drawTrace.Enable(true);
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+  drawTrace.Enable( false );
+
+  // geometry type is set as GL_LINES
+  // no index buffer, call glDrawArrays,
+  DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION);
+  out.str("");
+  out << GL_LINES << ", " << 0 << ", " << numVertex;
+  DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::LINES, TEST_LOCATION);
+
+  /*****************************************************/
+  //POINTS
+  geometry.SetGeometryType( Geometry::POINTS );
+
+  drawTrace.Reset();
+  drawTrace.Enable(true);
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+  drawTrace.Enable( false );
+
+  // geometry type is set as GL_POINTS
+  // no index buffer, call glDrawArrays,
+  DALI_TEST_EQUALS( drawTrace.CountMethod( "DrawArrays" ), 2, TEST_LOCATION);
+  out.str("");
+  out << GL_POINTS << ", " << 0 << ", " << numVertex;
+  DALI_TEST_EQUALS( drawTrace.TestMethodAndParams(1, "DrawArrays", out.str()), true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS( geometry.GetGeometryType(), Geometry::POINTS, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliGeometrySetGetRequireDepthTesting(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetRequiresDepthTesting, GetRequiresDepthTesting");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( geometry.GetRequiresDepthTesting(), false, TEST_LOCATION );
+
+  geometry.SetRequiresDepthTesting(true);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+  application.SendNotification();
+  application.Render();
+//  TODO: Not supported yes
+//  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+//  std::ostringstream out;
+//  out << GL_DEPTH_TEST;
+//  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", out.str().c_str() ) );
+
+  DALI_TEST_EQUALS( geometry.GetRequiresDepthTesting(), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryPropertyRequiresDepthTest(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetRequiresDepthTesting, GetRequiresDepthTesting");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( geometry.GetProperty<bool>(Geometry::Property::REQUIRES_DEPTH_TEST), false, TEST_LOCATION );
+
+  geometry.SetProperty(Geometry::Property::REQUIRES_DEPTH_TEST, true );
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+  application.SendNotification();
+  application.Render();
+//  TODO: Not supported yes
+//  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+//  std::ostringstream out;
+//  out << GL_DEPTH_TEST;
+//  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", out.str().c_str() ) );
+
+  DALI_TEST_EQUALS( geometry.GetProperty<bool>(Geometry::Property::REQUIRES_DEPTH_TEST), true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryConstraint(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a custom geometry property can be constrained");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( geometry, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect no blue component in either buffer - yellow
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+
+  geometry.RemoveConstraints();
+  geometry.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryConstraint02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map geometry property can be constrained");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( geometry, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+   // Expect no blue component in either buffer - yellow
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  geometry.RemoveConstraints();
+  geometry.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliGeometryAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a custom geometry property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( geometry, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS( geometry.GetProperty<Vector4>(colorIndex), Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliGeometryAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map geometry property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = geometry.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( geometry, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Hash.cpp b/automated-tests/src/dali-devel/utc-Dali-Hash.cpp
new file mode 100644 (file)
index 0000000..79c3881
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <string>
+#include <stdlib.h>
+#include <dali/devel-api/common/hash.h>
+#include <dali-test-suite-utils.h>
+
+void utc_dali_hash_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_hash_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliHash(void)
+{
+  // To fully test the Hash distribution we need to use a tool like http://code.google.com/p/smhasher/
+  // DALi currently uses the hash for variable length strings which come from:
+  // shader vert+frag source, font family + style, image filename.
+  TestApplication application;
+
+  tet_infoline("UtcDaliHash");
+
+  const std::string testString1( "highp vec4 glowColor = vec4( uGlowColor.rgb, uGlowColor.a * clampedColor.a );");
+  const std::string testString2( "lowp vec4 glowColor = vec4( uGlowColor.rgb, uGlowColor.a * clampedColor.a );");
+
+  DALI_TEST_CHECK( Dali::CalculateHash( testString1 ) != Dali::CalculateHash( testString2 ) );
+  DALI_TEST_CHECK( Dali::CalculateHash( testString1, testString2 ) != Dali::CalculateHash( testString2, testString1 ) );
+
+  END_TEST;
+}
+
+int UtcDaliHashNegative(void)
+{
+  // negative test, check hash value == initial value
+  const std::string emptyString;
+
+  DALI_TEST_CHECK( Dali::CalculateHash( emptyString ) != 0 );
+  DALI_TEST_CHECK( Dali::CalculateHash( emptyString, emptyString ) != 0 );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp b/automated-tests/src/dali-devel/utc-Dali-HitTestAlgorithm.cpp
new file mode 100644 (file)
index 0000000..ae04a17
--- /dev/null
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+/**
+ * The functor to be used in the hit-test algorithm to check whether the actor is hittable.
+ */
+bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+  bool hittable = false;
+
+  switch (type)
+  {
+    case Dali::HitTestAlgorithm::CHECK_ACTOR:
+    {
+      // Check whether the actor is visible and not fully transparent.
+      if( actor.IsVisible()
+       && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT
+      {
+        // Check whether the actor has the specific name "HittableActor"
+        if(actor.GetName() == "HittableActor")
+        {
+          hittable = true;
+        }
+      }
+      break;
+    }
+    case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+    {
+      if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
+      {
+        hittable = true;
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return hittable;
+};
+
+
+bool DefaultIsActorTouchableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+  bool hittable = false;
+
+  switch (type)
+  {
+    case Dali::HitTestAlgorithm::CHECK_ACTOR:
+    {
+      if( actor.IsVisible() &&
+          actor.IsSensitive() &&
+          actor.GetCurrentWorldColor().a > 0.01f)
+      {
+        hittable = true;
+      }
+      break;
+    }
+    case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+    {
+      if( actor.IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+          actor.IsSensitive()) // Actor is sensitive, if insensitive none of its children should be hittable either.
+      {
+        hittable = true;
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return hittable;
+};
+
+} // anonymous namespace
+
+
+// Positive test case for a method
+int UtcDaliHitTestAlgorithmWithFunctor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm functor");
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.SetName("NonHittableActor");
+  stage.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Vector2 localCoordinates;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+  // Perform a hit-test at the given screen coordinates
+  Dali::HitTestAlgorithm::Results results;
+  Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor != actor );
+
+  actor.SetName("HittableActor");
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+
+  // Perform a hit-test at the given screen coordinates
+  Dali::HitTestAlgorithm::HitTest( stage, screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor == actor );
+  DALI_TEST_EQUALS( localCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHitTestAlgorithmWithFunctorOnRenderTask(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm functor, specific to a given render task");
+
+  Stage stage = Stage::GetCurrent();
+  Size stageSize = stage.GetSize();
+  RenderTaskList taskList = stage.GetRenderTaskList();
+
+  Actor actor[2];
+
+  for( int i=0; i<2; i++ )
+  {
+    actor[i] = Actor::New();
+    actor[i].SetSize(100.f, 100.f);
+    actor[i].SetParentOrigin(ParentOrigin::TOP_LEFT);
+    actor[i].SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    actor[i].SetName("HittableActor");
+    stage.Add(actor[i]);
+  }
+  Vector2 position( 50.f, 40.f );
+  actor[1].SetPosition( position.x, position.y );
+
+  RenderTask renderTask[2];
+  renderTask[0] = taskList.GetTask( 0u );
+
+  FrameBufferImage frameBufferImage =  FrameBufferImage::New(stageSize.width, stageSize.height, Pixel::A8, Image::NEVER);
+  renderTask[1] = taskList.CreateTask();
+  renderTask[1].SetSourceActor( actor[1] );
+  renderTask[1].SetExclusive( true );
+  renderTask[1].SetInputEnabled( true );
+  renderTask[1].SetTargetFrameBuffer( frameBufferImage );
+  renderTask[1].SetRefreshRate( RenderTask::REFRESH_ONCE );
+  renderTask[1].SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  // Perform a hit-test at the given screen coordinates with different render tasks
+
+  Dali::HitTestAlgorithm::Results results;
+  Vector2 screenCoordinates( 25.f, 25.f );
+
+  Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor == actor[0] );
+  DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( !results.actor );
+  DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  screenCoordinates.x = 80.f;
+  screenCoordinates.y = 70.f;
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor == actor[0] );
+  DALI_TEST_EQUALS( screenCoordinates, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor == actor[1]);
+  DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  screenCoordinates.x = 120.f;
+  screenCoordinates.y = 130.f;
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  Dali::HitTestAlgorithm::HitTest( renderTask[0], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( !results.actor );
+  DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  Dali::HitTestAlgorithm::HitTest( renderTask[1], screenCoordinates, results, IsActorHittableFunction );
+  DALI_TEST_CHECK( results.actor == actor[1]);
+  DALI_TEST_EQUALS( screenCoordinates - position, results.actorCoordinates, 0.1f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliHitTestAlgorithmOrtho01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm with parallel Ortho camera()");
+
+  Stage stage = Stage::GetCurrent();
+  RenderTaskList renderTaskList = stage.GetRenderTaskList();
+  RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+  Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+  Vector2 stageSize ( stage.GetSize() );
+  cameraActor.SetOrthographicProjection( stageSize );
+  cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
+
+  Vector2 actorSize( stageSize * 0.5f );
+  // Create two actors with half the size of the stage and set them to be partially overlapping
+  Actor blue = Actor::New();
+  blue.SetName( "Blue" );
+  blue.SetAnchorPoint( AnchorPoint::CENTER );
+  blue.SetParentOrigin( Vector3(1.0f/3.0f, 1.0f/3.0f, 0.5f) );
+  blue.SetSize( actorSize );
+  blue.SetZ(30.0f);
+
+  Actor green = Actor::New( );
+  green.SetName( "Green" );
+  green.SetAnchorPoint( AnchorPoint::CENTER );
+  green.SetParentOrigin( Vector3(2.0f/3.0f, 2.0f/3.0f, 0.5f) );
+  green.SetSize( actorSize );
+
+  // Add the actors to the view
+  stage.Add( blue );
+  stage.Add( green );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+  application.Render(10);
+
+  HitTestAlgorithm::Results results;
+  HitTest(stage, stageSize / 2.0f, results, &DefaultIsActorTouchableFunction);
+  DALI_TEST_CHECK( results.actor == green );
+  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 1.0f/6.0f, TEST_LOCATION );
+
+  HitTest(stage, stageSize / 3.0f, results, &DefaultIsActorTouchableFunction);
+  DALI_TEST_CHECK( results.actor == blue );
+  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
+
+  HitTest(stage, stageSize * 2.0f / 3.0f, results, &DefaultIsActorTouchableFunction);
+  DALI_TEST_CHECK( results.actor == green );
+  DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.5f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliHitTestAlgorithmOrtho02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm with offset Ortho camera()");
+
+  Stage stage = Stage::GetCurrent();
+  RenderTaskList renderTaskList = stage.GetRenderTaskList();
+  RenderTask defaultRenderTask = renderTaskList.GetTask(0u);
+  Dali::CameraActor cameraActor = defaultRenderTask.GetCameraActor();
+
+  Vector2 stageSize ( stage.GetSize() );
+  cameraActor.SetOrthographicProjection(-stageSize.x * 0.3f,  stageSize.x * 0.7f,
+                                         stageSize.y * 0.3f, -stageSize.y * 0.7f,
+                                         800.0f, 4895.0f);
+  cameraActor.SetPosition(0.0f, 0.0f, 1600.0f);
+
+  Vector2 actorSize( stageSize * 0.5f );
+  // Create two actors with half the size of the stage and set them to be partially overlapping
+  Actor blue = Actor::New();
+  blue.SetName( "Blue" );
+  blue.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  blue.SetParentOrigin( Vector3(0.2f, 0.2f, 0.5f) );
+  blue.SetSize( actorSize );
+  blue.SetZ(30.0f);
+
+  Actor green = Actor::New( );
+  green.SetName( "Green" );
+  green.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  green.SetParentOrigin( Vector3(0.4f, 0.4f, 0.5f) );
+  green.SetSize( actorSize );
+
+  // Add the actors to the view
+  stage.Add( blue );
+  stage.Add( green );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render(0);
+  application.Render(10);
+
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, Vector2( 240.0f, 400.0f ), results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( results.actor == green );
+    DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.6f, 0.01f, TEST_LOCATION );
+  }
+
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, Vector2( 0.001f, 0.001f ), results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( results.actor == blue );
+    DALI_TEST_EQUALS( results.actorCoordinates, Vector2( 0.001f, 0.001f ), 0.001f, TEST_LOCATION );
+  }
+
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, stageSize, results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( ! results.actor );
+    DALI_TEST_EQUALS( results.actorCoordinates, Vector2::ZERO, TEST_LOCATION );
+  }
+
+  // Just inside green
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, stageSize*0.69f, results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( results.actor == green );
+    DALI_TEST_EQUALS( results.actorCoordinates, actorSize * 0.98f, 0.01f, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliHitTestAlgorithmStencil(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::HitTestAlgorithm with a stencil");
+
+  Stage stage = Stage::GetCurrent();
+  Actor rootLayer = stage.GetRootLayer();
+  rootLayer.SetName( "RootLayer" );
+
+  // Create a layer
+  Layer layer = Layer::New();
+  layer.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  layer.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  layer.SetName( "layer" );
+  stage.Add( layer );
+
+  // Create a stencil and add that to the layer
+  Actor stencil = ImageActor::New(Dali::BufferImage::WHITE() );
+  stencil.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  stencil.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  stencil.SetSize( 50.0f, 50.0f );
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stencil.SetName( "stencil" );
+  layer.Add( stencil );
+
+  // Create a renderable actor and add that to the layer
+  Actor layerHitActor = ImageActor::New();
+  layerHitActor.SetSize( 100.0f, 100.0f );
+  layerHitActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  layerHitActor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  layerHitActor.SetName( "layerHitActor" );
+  layer.Add( layerHitActor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Hit within stencil and actor
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, Vector2( 10.0f, 10.0f ), results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( results.actor == layerHitActor );
+    tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
+  }
+
+  // Hit within actor but outside of stencil, should hit the root-layer
+  {
+    HitTestAlgorithm::Results results;
+    HitTest(stage, Vector2( 60.0f, 60.0f ), results, &DefaultIsActorTouchableFunction);
+    DALI_TEST_CHECK( results.actor == rootLayer );
+    tet_printf( "Hit: %s\n", ( results.actor ? results.actor.GetName().c_str() : "NULL" ) );
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Material.cpp b/automated-tests/src/dali-devel/utc-Dali-Material.cpp
new file mode 100644 (file)
index 0000000..433520f
--- /dev/null
@@ -0,0 +1,1169 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+namespace
+{
+void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.b = 0.0f;
+}
+}
+
+
+void material_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void material_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliMaterialNew01(void)
+{
+  TestApplication application;
+
+  Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+  Material material = Material::New(shader);
+
+  DALI_TEST_CHECK( material );
+  END_TEST;
+}
+
+int UtcDaliMaterialNew02(void)
+{
+  TestApplication application;
+  Material material;
+  DALI_TEST_CHECK( !material );
+  END_TEST;
+}
+
+int UtcDaliMaterialCopyConstructor(void)
+{
+  TestApplication application;
+
+  Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+  Image image = BufferImage::New(32, 32, Pixel::RGBA8888);
+  Sampler sampler = Sampler::New(image, "sTexture");
+  Material material = Material::New(shader);
+  material.AddSampler( sampler );
+
+  Material materialCopy(material);
+
+  DALI_TEST_CHECK( materialCopy );
+  DALI_TEST_EQUALS( materialCopy.GetSamplerAt(0), sampler, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+  Image image = BufferImage::New(32, 32, Pixel::RGBA8888);
+  Sampler sampler = Sampler::New(image, "sTexture");
+  Material material = Material::New(shader);
+  material.AddSampler( sampler );
+
+  Material material2;
+  DALI_TEST_CHECK( !material2 );
+
+  material2 = material;
+  DALI_TEST_CHECK( material2 );
+  DALI_TEST_EQUALS( material2.GetSamplerAt(0), sampler, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialDownCast01(void)
+{
+  TestApplication application;
+  Shader shader = Shader::New("vertexSrc", "fragmentSrc");
+  Material material = Material::New(shader);
+
+  BaseHandle handle(material);
+  Material material2 = Material::DownCast(handle);
+  DALI_TEST_CHECK( material2 );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialDownCast02(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New(); // Create a custom object
+  Material material = Material::DownCast(handle);
+  DALI_TEST_CHECK( !material );
+  END_TEST;
+}
+
+int UtcDaliMaterialSetShader(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetShader(shader) ");
+
+  Shader shader1 = Shader::New( "vertexSrc1", "fragmentSrc1" );
+  shader1.RegisterProperty( "uFadeColor", Color::CYAN );
+
+  Shader shader2 = Shader::New( "vertexSrc1", "fragmentSrc1" );
+  shader2.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  // shader1
+  Material material = Material::New(shader1);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  application.SendNotification();
+  application.Render(0);
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION );
+
+  // shader2
+  material.SetShader( shader2 );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION );
+
+  // shader1
+  material.SetShader( shader1 );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialGetShader(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetShader() ");
+
+  Shader shader1 = Shader::New( "vertexSrc1", "fragmentSrc1" );
+  Shader shader2 = Shader::New( "vertexSrc1", "fragmentSrc1" );
+
+  // shader1
+  Material material = Material::New(shader1);
+  DALI_TEST_EQUALS( shader1, material.GetShader(), TEST_LOCATION );
+
+  // shader2
+  material.SetShader( shader2 );
+  DALI_TEST_EQUALS( shader2, material.GetShader(), TEST_LOCATION );
+
+  // shader1
+  material.SetShader( shader1 );
+  DALI_TEST_EQUALS( shader1, material.GetShader(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialAddSampler(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test AddSampler(sampler)");
+
+  Image image = BufferImage::New(32, 32, Pixel::RGBA8888);
+  Sampler sampler1 = Sampler::New(image, "sTexture1");
+  Sampler sampler2 = Sampler::New(image, "sTexture2");
+
+  Material material = CreateMaterial(0.5f);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  int textureUnit=-1;
+
+  material.AddSampler( sampler1 );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sTexture1", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION );
+
+  material.AddSampler( sampler2 );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sTexture2", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialGetNumberOfSampler(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetNumberOfSampler()");
+
+  Image image = BufferImage::New(32, 32, Pixel::RGBA8888);
+  Sampler sampler0 = Sampler::New(image, "sTexture0");
+  Sampler sampler1 = Sampler::New(image, "sTexture1");
+  Sampler sampler2 = Sampler::New(image, "sTexture2");
+  Sampler sampler3 = Sampler::New(image, "sTexture3");
+  Sampler sampler4 = Sampler::New(image, "sTexture4");
+
+  Material material = CreateMaterial(0.5f);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  material.AddSampler( sampler0 );
+  material.AddSampler( sampler1 );
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 2u, TEST_LOCATION );
+
+  material.AddSampler( sampler2 );
+  material.AddSampler( sampler3 );
+  material.AddSampler( sampler4 );
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 5u, TEST_LOCATION );
+
+  material.RemoveSampler(3); // remove sampler3
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 4u, TEST_LOCATION );
+
+  material.RemoveSampler(3); // remove sampler4
+  material.RemoveSampler(0); // remove sampler0
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 2u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialRemoveSampler(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test RemoveSampler(index)");
+  Image image = BufferImage::New(32, 32, Pixel::RGBA8888);
+  Sampler sampler1 = Sampler::New(image, "sTexture1");
+  Sampler sampler2 = Sampler::New(image, "sTexture2");
+
+  Material material = CreateMaterial(0.5f);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  material.AddSampler( sampler1 );
+  material.AddSampler( sampler2 );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  int textureUnit=-1;
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sTexture1", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION );
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sTexture2", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION );
+
+  material.RemoveSampler(0); // remove sampler1
+  application.SendNotification();
+  application.Render();
+  // Todo: test the sampler is removed from gl, cannot pass this test with current implementation
+  //DALI_TEST_CHECK( ! gl.GetUniformValue<int>( "sTexture1", textureUnit ) );
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 1u, TEST_LOCATION );
+
+  material.RemoveSampler(0); // remove sampler2
+  application.SendNotification();
+  application.Render();
+  // Todo: test the sampler is removed from gl, cannot pass this test with current implementation
+  //DALI_TEST_CHECK( ! gl.GetUniformValue<int>( "sTexture2", textureUnit ) );
+  DALI_TEST_EQUALS( material.GetNumberOfSamplers(), 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialGetSamplerAt(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetSamplerAt(index)");
+
+  Image image = BufferImage::New(16, 16, Pixel::RGBA8888);
+  Sampler sampler1 = Sampler::New(image, "sTexture1");
+  Sampler sampler2 = Sampler::New(image, "sTexture2");
+  Sampler sampler3 = Sampler::New(image, "sTexture3");
+
+  Material material = CreateMaterial(0.5f);
+  material.AddSampler( sampler1 );
+  material.AddSampler( sampler2 );
+  material.AddSampler( sampler3 );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( material.GetSamplerAt( 0 ), sampler1, TEST_LOCATION );
+  DALI_TEST_EQUALS( material.GetSamplerAt( 1 ), sampler2, TEST_LOCATION );
+  DALI_TEST_EQUALS( material.GetSamplerAt( 2 ), sampler3, TEST_LOCATION );
+
+  Sampler sampler = material.GetSamplerAt( 1 );
+  DALI_TEST_EQUALS( sampler.GetImage().GetWidth(), 16u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetFaceCullingMode(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetFaceCullingMode(cullingMode)");
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& cullFaceStack = gl.GetCullFaceTrace();
+  cullFaceStack.Reset();
+  gl.EnableCullFaceCallTrace(true);
+
+  material.SetFaceCullingMode( Material::CULL_BACK_AND_FRONT);
+  application.SendNotification();
+  application.Render();
+
+  // Todo: test the glCullFace(GL_FRONT_AND_BACK) is actually been called, cannot pass this test with current implementation
+  DALI_TEST_EQUALS( cullFaceStack.CountMethod( "CullFace" ), 0, TEST_LOCATION);
+  //string parameter("GL_FRONT_AND_BACK" );
+  //DALI_TEST_CHECK( cullFaceStack.TestMethodAndParams(0, "CullFace", parameter) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialBlendingOptions01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetBlendFunc(src, dest) ");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendFunc(BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE);
+
+  // Test that Set was successful:
+  {
+    BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO );
+    material.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorRgb,    TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE,  destFactorRgb,   TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorAlpha,  TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE,  destFactorAlpha, TEST_LOCATION );
+  }
+
+  application.SendNotification();
+  application.Render();
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE,  glAbstraction.GetLastBlendFuncDstRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE,  glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialBlendingOptions02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetBlendFunc(srcRgb, destRgb, srcAlpha, destAlpha) ");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendFunc( BlendingFactor::CONSTANT_COLOR, BlendingFactor::ONE_MINUS_CONSTANT_COLOR,
+                         BlendingFactor::CONSTANT_ALPHA, BlendingFactor::ONE_MINUS_CONSTANT_ALPHA );
+
+  // Test that Set was successful:
+  {
+    BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO );
+    material.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+
+    DALI_TEST_EQUALS( BlendingFactor::CONSTANT_COLOR,            srcFactorRgb,    TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_COLOR,  destFactorRgb,   TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::CONSTANT_ALPHA,            srcFactorAlpha,  TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_ALPHA,  destFactorAlpha, TEST_LOCATION );
+  }
+
+  application.SendNotification();
+  application.Render();
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_COLOR,           glAbstraction.GetLastBlendFuncSrcRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncDstRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_ALPHA,           glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliMaterialBlendingOptions03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetBlendEquation() defaults ");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  // Test the defaults as documented in blending.h
+  {
+    BlendingEquation::Type equationRgb( BlendingEquation::SUBTRACT );
+    BlendingEquation::Type equationAlpha( BlendingEquation::SUBTRACT );
+    material.GetBlendEquation( equationRgb, equationAlpha );
+    DALI_TEST_EQUALS( BlendingEquation::ADD, equationRgb, TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingEquation::ADD, equationAlpha, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliMaterialBlendingOptions04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetBlendEquation() ");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  // Test the single blending equation setting
+  {
+    material.SetBlendEquation( BlendingEquation::REVERSE_SUBTRACT );
+    BlendingEquation::Type equationRgba( BlendingEquation::SUBTRACT );
+    material.GetBlendEquation( equationRgba, equationRgba );
+    DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationRgba, TEST_LOCATION );
+  }
+
+  material.SetBlendEquation( BlendingEquation::REVERSE_SUBTRACT, BlendingEquation::REVERSE_SUBTRACT );
+
+  // Test that Set was successful
+  {
+    BlendingEquation::Type equationRgb( BlendingEquation::SUBTRACT );
+    BlendingEquation::Type equationAlpha( BlendingEquation::SUBTRACT );
+    material.GetBlendEquation( equationRgb, equationAlpha );
+    DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationRgb, TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingEquation::REVERSE_SUBTRACT, equationAlpha, TEST_LOCATION );
+  }
+
+  // Render & check GL commands
+  application.SendNotification();
+  application.Render();
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  DALI_TEST_EQUALS( (GLenum)GL_FUNC_REVERSE_SUBTRACT, glAbstraction.GetLastBlendEquationRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_FUNC_REVERSE_SUBTRACT, glAbstraction.GetLastBlendEquationAlpha(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to on with an opaque color renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::ON);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+
+int UtcDaliMaterialSetBlendMode02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to off with a transparent color renders with blending disabled (and not enabled)");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::OFF);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with a transparent material color renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(0.5f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque color renders with blending disabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode04b(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque material color and a transparent actor color renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  actor.SetColor( Vector4(1.0f, 0.0f, 1.0f, 0.5f) );
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode04c(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque material color and an opaque actor color renders with blending disabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  actor.SetColor( Color::MAGENTA );
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test setting the blend mode to auto with an opaque color and an image with an alpha channel renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  BufferImage image = BufferImage::New( 40, 40, Pixel::RGBA8888 );
+  Material material = CreateMaterial(1.0f, image);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendMode06(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with an opaque color and an image without an alpha channel and a shader with the hint OUTPUT_IS_TRANSPARENT renders with blending enabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_TRANSPARENT );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+
+//Todo: test the Shader::HINT_OUTPUT_IS_OPAQUE would disable the blending, the test cannot pass with current implementation
+/*int UtcDaliMaterialSetBlendMode07(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with a transparent color and an image without an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled");
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::TRANSPARENT);
+
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}*/
+
+int UtcDaliMaterialSetBlendMode08(void)
+{
+  TestApplication application;
+  tet_infoline("Test setting the blend mode to auto with an opaque color and an image without an alpha channel and a shader with the hint OUTPUT_IS_OPAQUE renders with blending disabled");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+  BufferImage image = BufferImage::New( 50, 50, Pixel::RGB888 );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  material.SetBlendMode(BlendingMode::AUTO);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = glAbstraction.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialGetBlendMode(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetBlendMode()");
+
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+
+  // default value
+  DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::OFF, TEST_LOCATION );
+
+  // AUTO
+  material.SetBlendMode(BlendingMode::AUTO);
+  DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::AUTO, TEST_LOCATION );
+
+  // ON
+  material.SetBlendMode(BlendingMode::ON);
+  DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::ON, TEST_LOCATION );
+
+  // OFF
+  material.SetBlendMode(BlendingMode::OFF);
+  DALI_TEST_EQUALS( material.GetBlendMode(), BlendingMode::OFF, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialSetBlendColor(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetBlendColor(color)");
+
+  Geometry geometry = CreateQuadGeometry();
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+  BufferImage image = BufferImage::New( 50, 50, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), Color::TRANSPARENT, TEST_LOCATION );
+
+  material.SetBlendColor( Color::MAGENTA );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), Color::MAGENTA, TEST_LOCATION );
+
+  Vector4 color( 0.1f, 0.2f, 0.3f, 0.4f );
+  material.SetBlendColor( color );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( glAbstraction.GetLastBlendColor(), color, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialGetBlendColor(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetBlendColor()");
+
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc", Shader::HINT_OUTPUT_IS_OPAQUE );
+  Material material = Material::New(shader);
+
+  DALI_TEST_EQUALS( material.GetBlendColor(), Color::TRANSPARENT, TEST_LOCATION );
+
+  material.SetBlendColor( Color::MAGENTA );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( material.GetBlendColor(), Color::MAGENTA, TEST_LOCATION );
+
+  Vector4 color( 0.1f, 0.2f, 0.3f, 0.4f );
+  material.SetBlendColor( color );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( material.GetBlendColor(), color, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialConstraint(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a custom material property can be constrained");
+
+  Shader shader = Shader::New( "VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( material, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect no blue component in either buffer - yellow
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+
+  material.RemoveConstraints();
+  material.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialConstraint02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map material property can be constrained");
+
+  Shader shader = Shader::New( "VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( material, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+   // Expect no blue component in either buffer - yellow
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  material.RemoveConstraints();
+  material.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliMaterialAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform material property can be animated");
+
+  Shader shader = Shader::New( "VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( material, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS( material.GetProperty<Vector4>(colorIndex), Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMaterialAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map material property can be animated");
+
+  Shader shader = Shader::New( "VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = material.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( material, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Mutex.cpp b/automated-tests/src/dali-devel/utc-Dali-Mutex.cpp
new file mode 100644 (file)
index 0000000..290a826
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/common/mutex.h>
+#include <dali-test-suite-utils.h>
+
+using Dali::Mutex;
+
+int UtcDaliMutexSingleThread(void)
+{
+  tet_infoline("Testing Dali::Mutex in a single thread");
+
+  {
+    Mutex mutex1;
+    DALI_TEST_EQUALS( false, mutex1.IsLocked(), TEST_LOCATION );
+  }
+
+  {
+    Mutex mutex2;
+    Mutex::ScopedLock lock( mutex2 );
+    DALI_TEST_EQUALS( true, mutex2.IsLocked(), TEST_LOCATION );
+  }
+
+  Mutex mutex3;
+  {
+    Mutex::ScopedLock lock( mutex3 );
+  }
+  DALI_TEST_EQUALS( false, mutex3.IsLocked(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+namespace // for local variables to avoid name clashes
+{
+// make all these volatile to pre-empt any optimization screwing up the logic
+volatile int gGlobalValue = 0;
+volatile bool gWorkerThreadWait = true;
+volatile enum ThreadState { INIT, RUN, LOCKING, TERMINATE } gWorkerThreadState = INIT;
+Mutex* volatile gGlobalValueMutex; // volatile pointer to a mutex object
+}
+void* WorkerThread1( void* ptr )
+{
+  gWorkerThreadState = RUN;
+  {
+    Mutex::ScopedLock lock( *gGlobalValueMutex );
+    gWorkerThreadState = LOCKING;
+    gGlobalValue = -1;
+    while( gWorkerThreadWait ) // wait till we can exit
+    {
+      usleep( 1 ); // 1 microsecond
+    }
+  }
+  gWorkerThreadState = TERMINATE;
+  return NULL;
+}
+
+int UtcDaliMutexMultiThread(void)
+{
+  tet_infoline("Testing Dali::Mutex multithreaded");
+
+  gGlobalValueMutex = new Dali::Mutex();
+
+  pthread_t thread1;
+  // initialize values
+  gGlobalValue = 0;
+  gWorkerThreadWait = true;
+  DALI_TEST_EQUALS( INIT, gWorkerThreadState, TEST_LOCATION );
+  DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
+
+  // lock the mutex
+  {
+    Mutex::ScopedLock lock( *gGlobalValueMutex );
+    DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
+    pthread_create( &thread1, NULL, &WorkerThread1, NULL );
+    // wait till the thread is in run state
+    while( RUN != gWorkerThreadState )
+    {
+      usleep( 1 ); // 1 microsecond
+    }
+    // now the thread is running and mutex is still locked by this thread so value is not changed
+    DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
+    DALI_TEST_EQUALS( 0, gGlobalValue, TEST_LOCATION );
+    // drop out of scope, releases our lock
+  }
+  // now child thread is allowed to change the value
+  // wait till the thread is in locking state
+  while( LOCKING != gWorkerThreadState )
+  {
+    usleep( 1 ); // 1 microsecond
+  }
+  // mutex is locked, but not by us, by the child thread
+  DALI_TEST_EQUALS( true, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
+  // value is changed
+  DALI_TEST_EQUALS( -1, gGlobalValue, TEST_LOCATION );
+  // let worker finish
+  gWorkerThreadWait = false;
+  // wait till the thread is terminated state
+  while( TERMINATE != gWorkerThreadState )
+  {
+    usleep( 1 ); // 1 microsecond
+  }
+  DALI_TEST_EQUALS( false, gGlobalValueMutex->IsLocked(), TEST_LOCATION );
+  void* exitValue;
+  pthread_join( thread1, &exitValue );
+
+  END_TEST;
+}
+
+int UtcDaliMutexNonCopyable(void)
+{
+  // we want to make sure that mutex is not copyable (its copy constructor is not defined)
+  // this test will stop compiling if Mutex has compiler generated copy constructor
+  DALI_COMPILE_TIME_ASSERT( !__has_trivial_copy( Mutex ) );
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+
diff --git a/automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp b/automated-tests/src/dali-devel/utc-Dali-PropertyBuffer.cpp
new file mode 100644 (file)
index 0000000..55b3d10
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/rendering/renderer.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+namespace
+{
+void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.b = 0.0f;
+}
+}
+
+void propertyBuffer_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void propertyBuffer_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliPropertyBufferNew01(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+
+  DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferNew02(void)
+{
+  TestApplication application;
+  PropertyBuffer propertyBuffer;
+  DALI_TEST_EQUALS( (bool)propertyBuffer, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferDownCast01(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+
+  BaseHandle handle(propertyBuffer);
+  PropertyBuffer propertyBuffer2 = PropertyBuffer::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)propertyBuffer2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferDownCast02(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New(); // Create a custom object
+  PropertyBuffer propertyBuffer = PropertyBuffer::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)propertyBuffer, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferCopyConstructor(void)
+{
+  TestApplication application;
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+
+  PropertyBuffer propertyBufferCopy(propertyBuffer);
+
+  DALI_TEST_EQUALS( (bool)propertyBufferCopy, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( propertyBufferCopy.GetSize(), 4u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferAssignmentOperator(void)
+{
+  TestApplication application;
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+
+  PropertyBuffer propertyBuffer2;
+  DALI_TEST_EQUALS( (bool)propertyBuffer2, false, TEST_LOCATION );
+
+  propertyBuffer2 = propertyBuffer;
+  DALI_TEST_EQUALS( (bool)propertyBuffer2, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( propertyBuffer2.GetSize(), 4u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferConstraint01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform propertyBuffer property can be constrained");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( propertyBuffer, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect no blue component in either buffer - yellow
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+
+  propertyBuffer.RemoveConstraints();
+  propertyBuffer.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferConstraint02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map propertyBuffer property can be constrained");
+
+  Shader shader = Shader::New( "VertexSource", "FragmentSource" );
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( propertyBuffer, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+   // Expect no blue component in either buffer - yellow
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  propertyBuffer.RemoveConstraints();
+  propertyBuffer.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliPropertyBufferAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform propertyBuffer property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( propertyBuffer, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<Vector4>(colorIndex), Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map propertyBuffer property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer propertyBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(propertyBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = propertyBuffer.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( propertyBuffer, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferSetData01(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+  DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION );
+
+  const float halfQuadSize = .5f;
+  struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+
+  propertyBuffer.SetData( texturedQuadVertexData );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( propertyBuffer );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+      application.GetGlAbstraction().GetBufferDataCalls();
+
+  DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferSetData02(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+  DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION );
+
+  const float halfQuadSize = .5f;
+  struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+
+  propertyBuffer.SetData( texturedQuadVertexData );
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( propertyBuffer );
+
+  Material material = CreateMaterial(1.f);
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.SetSize(Vector3::ONE * 100.f);
+  actor.AddRenderer(renderer);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+      application.GetGlAbstraction().GetBufferDataCalls();
+
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( bufferDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION );
+  }
+
+  // Re-upload the data on the propertyBuffer
+  propertyBuffer.SetData( texturedQuadVertexData );
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  {
+    const TestGlAbstraction::BufferSubDataCalls& bufferSubDataCalls =
+      application.GetGlAbstraction().GetBufferSubDataCalls();
+
+    const TestGlAbstraction::BufferDataCalls& bufferDataCalls =
+          application.GetGlAbstraction().GetBufferDataCalls();
+
+    DALI_TEST_EQUALS( bufferSubDataCalls.size(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( bufferDataCalls.size(), 1u, TEST_LOCATION );
+
+    if ( bufferSubDataCalls.size() )
+    {
+      DALI_TEST_EQUALS( bufferSubDataCalls[0], sizeof(texturedQuadVertexData), TEST_LOCATION );
+
+    }
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyBufferSetGetSize01(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, 4u );
+  DALI_TEST_EQUALS( (bool)propertyBuffer, true, TEST_LOCATION );
+
+  size_t size = propertyBuffer.GetSize();
+  DALI_TEST_EQUALS( size, 4u, TEST_LOCATION );
+
+  propertyBuffer.SetSize( 10u );
+  size = propertyBuffer.GetSize();
+  DALI_TEST_EQUALS( size, 10u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+//Todo: also test that the SetSize function is equivalent to setting the property SIZE
+int UtcDaliPropertyBufferSetGetSize02(void)
+{
+  TestApplication application;
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  int size = 5u;
+  PropertyBuffer propertyBuffer = PropertyBuffer::New( texturedQuadVertexFormat, size );
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<int>(PropertyBuffer::Property::SIZE), size, TEST_LOCATION );
+  DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION );
+
+  size += 3u;
+  propertyBuffer.SetSize( size );
+  DALI_TEST_EQUALS( propertyBuffer.GetProperty<int>(PropertyBuffer::Property::SIZE), size, TEST_LOCATION );
+  DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION );
+
+  size += 2u;
+  propertyBuffer.SetProperty(PropertyBuffer::Property::SIZE, size );
+  DALI_TEST_EQUALS( propertyBuffer.GetSize(), size, TEST_LOCATION );
+
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali-devel/utc-Dali-Renderer.cpp b/automated-tests/src/dali-devel/utc-Dali-Renderer.cpp
new file mode 100644 (file)
index 0000000..ce0489e
--- /dev/null
@@ -0,0 +1,1077 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+namespace
+{
+void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.b = 0.0f;
+}
+}
+
+void renderer_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void renderer_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliRendererNew01(void)
+{
+  TestApplication application;
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  DALI_TEST_EQUALS( (bool)renderer, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRendererNew02(void)
+{
+  TestApplication application;
+  Renderer renderer;
+  DALI_TEST_EQUALS( (bool)renderer, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRendererCopyConstructor(void)
+{
+  TestApplication application;
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  Renderer rendererCopy( renderer );
+  DALI_TEST_EQUALS( (bool)rendererCopy, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  Renderer renderer2;
+  DALI_TEST_EQUALS( (bool)renderer2, false, TEST_LOCATION );
+
+  renderer2 = renderer;
+  DALI_TEST_EQUALS( (bool)renderer2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRendererDownCast01(void)
+{
+  TestApplication application;
+
+  Geometry geometry = CreateQuadGeometry();
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry, material);
+
+  BaseHandle handle(renderer);
+  Renderer renderer2 = Renderer::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)renderer2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRendererDownCast02(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New(); // Create a custom object
+  Renderer renderer = Renderer::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)renderer, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRendererSetGetGeometry(void)
+{
+  TestApplication application;
+  tet_infoline( "Test SetGeometry, GetGeometry" );
+
+  Geometry geometry1 = CreateQuadGeometry();
+  geometry1.RegisterProperty( "uFadeColor", Color::RED );
+
+  Geometry geometry2 = CreateQuadGeometry();
+  geometry2.RegisterProperty( "uFadeColor", Color::GREEN );
+
+  Material material = CreateMaterial(1.0f);
+  Renderer renderer = Renderer::New(geometry1, material);
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the first geometry's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( renderer.GetGeometry(), geometry1, TEST_LOCATION );
+
+  // Set geometry2 to the renderer
+  renderer.SetGeometry( geometry2 );
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the second geometry's fade color property is accessed
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( renderer.GetGeometry(), geometry2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererSetGetMaterial(void)
+{
+  TestApplication application;
+  tet_infoline( "Test SetMaterial, GetMaterial" );
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  glAbstraction.EnableCullFaceCallTrace(true);
+
+  Material material1 = CreateMaterial(1.0f);
+  material1.RegisterProperty( "uFadeColor", Color::RED );
+
+  Material material2 = CreateMaterial(1.0f);
+  material2.RegisterProperty( "uFadeColor", Color::GREEN );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material1);
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the first material's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( renderer.GetMaterial(), material1, TEST_LOCATION );
+
+  // set the second material to the renderer
+  renderer.SetMaterial( material2 );
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the second material's fade color property is accessed
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( renderer.GetMaterial(), material2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererSetGetDepthIndex(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test SetDepthIndex, GetDepthIndex");
+
+  Material material = CreateMaterial(1.0f);
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetDepthIndex(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( renderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX), 0, TEST_LOCATION );
+
+  renderer.SetDepthIndex(1);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetDepthIndex(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( renderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX), 1, TEST_LOCATION );
+
+  renderer.SetDepthIndex(10);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetDepthIndex(), 10, TEST_LOCATION );
+  DALI_TEST_EQUALS( renderer.GetProperty<int>(Renderer::Property::DEPTH_INDEX), 10, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererConstraint01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform renderer property can be constrained");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( renderer, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect no blue component in either buffer - yellow
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+
+  renderer.RemoveConstraints();
+  renderer.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererConstraint02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map renderer property can be constrained");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( renderer, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+   // Expect no blue component in either buffer - yellow
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  renderer.RemoveConstraints();
+  renderer.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliRendererAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform renderer property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( renderer, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS( renderer.GetProperty<Vector4>(colorIndex), Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map renderer property can be animated");
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = renderer.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( renderer, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+
+int UtcDaliRendererUniformMapPrecendence01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  renderer.RegisterProperty( "uFadeColor", Color::RED );
+
+  actor.RegisterProperty( "uFadeColor", Color::GREEN );
+
+  Property::Index materialFadeColorIndex = material.RegisterProperty( "uFadeColor", Color::BLUE );
+
+  sampler.RegisterProperty( "uFadeColor", Color::CYAN );
+  shader.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the renderer's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+  // Animate material's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( material, materialFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::RED, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererUniformMapPrecendence02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer
+
+  actor.RegisterProperty( "uFadeColor", Color::GREEN );
+
+  Property::Index materialFadeColorIndex = material.RegisterProperty( "uFadeColor", Color::BLUE );
+
+  sampler.RegisterProperty( "uFadeColor", Color::CYAN );
+  shader.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the actor's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+  // Animate material's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( material, materialFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::GREEN, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliRendererUniformMapPrecendence03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer or actor
+
+  material.RegisterProperty( "uFadeColor", Color::BLUE );
+
+  sampler.RegisterProperty( "uFadeColor", Color::CYAN );
+  shader.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the material's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION );
+
+  // Animate geometry's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::BLUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliRendererUniformMapPrecendence04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer/actor/material
+
+  sampler.RegisterProperty( "uFadeColor", Color::CYAN );
+  shader.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the sampler's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION );
+
+  // Animate geometry's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::CYAN, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererUniformMapPrecendence05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer/actor/material/sampler
+
+  shader.RegisterProperty( "uFadeColor", Color::MAGENTA );
+
+  Property::Index geometryFadeColorIndex = geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the shader's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION );
+
+  // Animate geometry's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( geometry, geometryFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::MAGENTA, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererUniformMapPrecendence06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer/actor/material/sampler/shader
+
+  geometry.RegisterProperty( "uFadeColor", Color::YELLOW );
+
+  Property::Index vertexFadeColorIndex = vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the geometry's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  // Animate vertex buffer's fade color property. Should be no change to uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( vertexBuffer, vertexFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRendererUniformMapPrecendence07(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform map precedence is applied properly");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  // Don't add property / uniform map to renderer/actor/material/sampler/shader/geometry
+
+  Property::Index vertexFadeColorIndex = vertexBuffer.RegisterProperty( "uFadeColor", Color::BLACK );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that the vertex buffer's fade color property is accessed
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::BLACK, TEST_LOCATION );
+
+  // Animate vertex buffer's fade color property. Should change the uniform
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Color::WHITE);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( vertexBuffer, vertexFadeColorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE*0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliRendererUniformMapMultipleUniforms01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform maps are collected from all objects (same type)");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  renderer.RegisterProperty( "uUniform1", Color::RED );
+  actor.RegisterProperty( "uUniform2", Color::GREEN );
+  material.RegisterProperty( "uUniform3", Color::BLUE );
+  sampler.RegisterProperty( "uUniform4", Color::CYAN );
+  shader.RegisterProperty( "uUniform5", Color::MAGENTA );
+  geometry.RegisterProperty( "uUniform6", Color::YELLOW );
+  vertexBuffer.RegisterProperty( "uUniform7", Color::BLACK );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that each of the object's uniforms are set
+  Vector4 uniform1Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform1", uniform1Value ) );
+  DALI_TEST_EQUALS( uniform1Value, Color::RED, TEST_LOCATION );
+
+  Vector4 uniform2Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform2", uniform2Value ) );
+  DALI_TEST_EQUALS( uniform2Value, Color::GREEN, TEST_LOCATION );
+
+  Vector4 uniform3Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform3", uniform3Value ) );
+  DALI_TEST_EQUALS( uniform3Value, Color::BLUE, TEST_LOCATION );
+
+  Vector4 uniform4Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform4", uniform4Value ) );
+  DALI_TEST_EQUALS( uniform4Value, Color::CYAN, TEST_LOCATION );
+
+  Vector4 uniform5Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform5", uniform5Value ) );
+  DALI_TEST_EQUALS( uniform5Value, Color::MAGENTA, TEST_LOCATION );
+
+  Vector4 uniform6Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform6", uniform6Value ) );
+  DALI_TEST_EQUALS( uniform6Value, Color::YELLOW, TEST_LOCATION );
+
+  Vector4 uniform7Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uUniform7", uniform7Value ) );
+  DALI_TEST_EQUALS( uniform7Value, Color::BLACK, TEST_LOCATION );
+
+
+  END_TEST;
+}
+
+
+int UtcDaliRendererUniformMapMultipleUniforms02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test the uniform maps are collected from all objects (different types)");
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Shader shader = Shader::New("VertexSource", "FragmentSource");
+  Material material = Material::New( shader );
+  material.AddSampler( sampler );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  PropertyBuffer vertexBuffer = CreatePropertyBuffer();
+  Geometry geometry = CreateQuadGeometryFromBuffer(vertexBuffer);
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Property::Value value1(Color::RED);
+  renderer.RegisterProperty( "uFadeColor", value1 );
+
+  Property::Value value2(1.0f);
+  actor.RegisterProperty( "uFadeProgress", value2 );
+
+  Property::Value value3(Vector3(0.5f, 0.5f, 1.0f));
+  material.RegisterProperty( "uFadePosition", value3);
+
+  Property::Value value4(Vector2(0.5f, 1.0f));
+  sampler.RegisterProperty( "uFadeUV", value4 );
+
+  Property::Value value5(Matrix3::IDENTITY);
+  shader.RegisterProperty( "uANormalMatrix", value5 );
+
+  Property::Value value6(Matrix::IDENTITY);
+  geometry.RegisterProperty( "uAWorldMatrix", value6 );
+
+  Property::Value value7(7);
+  vertexBuffer.RegisterProperty( "uAnotherFadeColor", value7 );
+
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect that each of the object's uniforms are set
+  Vector4 uniform1Value(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", uniform1Value ) );
+  DALI_TEST_EQUALS( uniform1Value, value1.Get<Vector4>(), TEST_LOCATION );
+
+  float uniform2Value(0.0f);
+  DALI_TEST_CHECK( gl.GetUniformValue<float>( "uFadeProgress", uniform2Value ) );
+  DALI_TEST_EQUALS( uniform2Value, value2.Get<float>(), TEST_LOCATION );
+
+  Vector3 uniform3Value(Vector3::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector3>( "uFadePosition", uniform3Value ) );
+  DALI_TEST_EQUALS( uniform3Value, value3.Get<Vector3>(), TEST_LOCATION );
+
+  Vector2 uniform4Value(Vector2::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector2>( "uFadeUV", uniform4Value ) );
+  DALI_TEST_EQUALS( uniform4Value, value4.Get<Vector2>(), TEST_LOCATION );
+
+  Matrix3 uniform5Value;
+  DALI_TEST_CHECK( gl.GetUniformValue<Matrix3>( "uANormalMatrix", uniform5Value ) );
+  DALI_TEST_EQUALS( uniform5Value, value5.Get<Matrix3>(), TEST_LOCATION );
+
+  Matrix uniform6Value;
+  DALI_TEST_CHECK( gl.GetUniformValue<Matrix>( "uAWorldMatrix", uniform6Value ) );
+  DALI_TEST_EQUALS( uniform6Value, value6.Get<Matrix>(), TEST_LOCATION );
+
+  int uniform7Value = 0;
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "uAnotherFadeColor", uniform7Value ) );
+  DALI_TEST_EQUALS( uniform7Value, value7.Get<int>(), TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Sampler.cpp b/automated-tests/src/dali-devel/utc-Dali-Sampler.cpp
new file mode 100644 (file)
index 0000000..4cecb5f
--- /dev/null
@@ -0,0 +1,448 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+void sampler_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void sampler_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliSamplerNew01(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  DALI_TEST_EQUALS( (bool)sampler, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSamplerNew02(void)
+{
+  TestApplication application;
+  Sampler sampler;
+  DALI_TEST_EQUALS( (bool)sampler, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSamplerCopyConstructor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Handle::Handle(const Handle&)");
+
+  // Initialize an object, ref count == 1
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  DALI_TEST_EQUALS(1, sampler.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  // Copy the object, ref count == 2
+  Sampler copy(sampler);
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliSamplerDownCast01(void)
+{
+  TestApplication application;
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  BaseHandle handle(sampler);
+  Sampler sampler2 = Sampler::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)sampler2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSamplerDownCast02(void)
+{
+  TestApplication application;
+
+  BaseHandle handle;
+  Sampler sampler = Sampler::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)sampler, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSamplerAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler1 = Sampler::New(image, "sTexture");
+
+  Sampler sampler2;
+
+  DALI_TEST_CHECK(!(sampler1 == sampler2));
+
+  sampler2 = sampler1;
+
+  DALI_TEST_CHECK(sampler1 == sampler2);
+
+  sampler2 = Sampler::New(image, "sTexture");
+
+  DALI_TEST_CHECK(!(sampler1 == sampler2));
+
+  END_TEST;
+}
+
+int UtcDaliSamplerSetUniformName01(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+  sampler.SetUniformName( "sEffectTexture" );
+
+  Material material = CreateMaterial(1.0f);
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+
+  Stage::GetCurrent().Add( actor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render();
+
+  int textureUnit=-1;
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sEffectTexture", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSamplerSetUniformName02(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Image image2 = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler1 = Sampler::New(image, "sTexture");
+  sampler1.SetUniformName( "sEffectTexture" );
+
+  Sampler sampler2 = Sampler::New(image2, "sTexture2");
+
+  Material material = CreateMaterial(1.0f);
+  material.AddSampler( sampler1 );
+  material.AddSampler( sampler2 );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+
+  Stage::GetCurrent().Add( actor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render();
+
+  int textureUnit=-1;
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sEffectTexture", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 0, TEST_LOCATION );
+
+  DALI_TEST_CHECK( gl.GetUniformValue<int>( "sTexture2", textureUnit ) );
+  DALI_TEST_EQUALS( textureUnit, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSamplerSetGetImage(void)
+{
+  TestApplication application;
+
+  Image image1 = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Image image2 = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image1, "sTexture");
+
+  DALI_TEST_CHECK(image1 == sampler.GetImage());
+
+  sampler.SetImage( image2 );
+  DALI_TEST_CHECK(!(image1 == sampler.GetImage()));
+  DALI_TEST_CHECK(image2 == sampler.GetImage());
+
+  END_TEST;
+}
+
+int UtcSamplerSetFilterMode(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  Material material = CreateMaterial(1.0f);
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  float initialValue = 1.0f;
+  sampler.RegisterProperty("uWidthClamp", initialValue );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  /**************************************************************/
+  // Default/Default
+  TraceCallStack& texParameterTrace = gl.GetTexParameterTrace();
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetFilterMode( Sampler::DEFAULT, Sampler::DEFAULT );
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify gl state
+
+  // There are two calls to TexParameteri when the texture is first created
+  // Texture mag filter is not called as the first time set it uses the system default
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION);
+
+  std::stringstream out;
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(2, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+  // Default/Default
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetFilterMode( Sampler::DEFAULT, Sampler::DEFAULT );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify gl state
+
+  // Should not make any calls when settings are the same
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION);
+
+  /**************************************************************/
+  // Nearest/Nearest
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetFilterMode( Sampler::NEAREST, Sampler::NEAREST );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_NEAREST;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+  // Nearest/Linear
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetFilterMode( Sampler::NEAREST, Sampler::LINEAR );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+  // NONE/NONE
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetFilterMode( Sampler::NONE, Sampler::NONE );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST_MIPMAP_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcSamplerSetWrapMode(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  Material material = CreateMaterial(1.0f);
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  //****************************************
+  // CLAMP_TO_EDGE / CLAMP_TO_EDGE
+  TraceCallStack& texParameterTrace = gl.GetTexParameterTrace();
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify gl state
+
+  // There are two calls to TexParameteri when the texture is first created
+  // Texture mag filter is not called as the first time set it uses the system default
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION);
+
+  std::stringstream out;
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_S << ", " << GL_CLAMP_TO_EDGE;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_WRAP_T << ", " << GL_CLAMP_TO_EDGE;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  sampler.SetWrapMode( Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify gl state
+
+  // Should not make any calls when settings are the same
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION);
+
+  //Todo: Test the other wrap mode ( REPEAT, MIRRORED_REPEAT )  , currently not support!!
+
+  END_TEST;
+}
+
+int UtcSamplerSetAffectsTransparency(void)
+{
+  TestApplication application;
+
+  Image image = BufferImage::New( 64, 64, Pixel::RGBA8888 );
+  Sampler sampler = Sampler::New(image, "sTexture");
+
+  Material material = CreateMaterial(1.0f);
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add( actor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  // Test SetAffectsTransparency( false )
+  sampler.SetAffectsTransparency( false );
+
+  gl.EnableCullFaceCallTrace(true);
+  application.SendNotification();
+  application.Render();
+
+  TraceCallStack& glEnableStack = gl.GetCullFaceTrace();
+  std::ostringstream blendStr;
+  blendStr << GL_BLEND;
+  DALI_TEST_CHECK( ! glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  // Test SetAffectsTransparency( true )
+  sampler.SetAffectsTransparency( true );
+
+  glEnableStack.Reset();
+  gl.EnableCullFaceCallTrace(true);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( glEnableStack.FindMethodAndParams( "Enable", blendStr.str().c_str() ) );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Scripting.cpp b/automated-tests/src/dali-devel/utc-Dali-Scripting.cpp
new file mode 100644 (file)
index 0000000..e001a89
--- /dev/null
@@ -0,0 +1,1039 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Scripting;
+
+namespace
+{
+
+const StringEnum COLOR_MODE_VALUES[] =
+{
+    { "USE_OWN_COLOR", USE_OWN_COLOR },
+    { "USE_PARENT_COLOR", USE_PARENT_COLOR },
+    { "USE_OWN_MULTIPLY_PARENT_COLOR", USE_OWN_MULTIPLY_PARENT_COLOR },
+    { "USE_OWN_MULTIPLY_PARENT_ALPHA", USE_OWN_MULTIPLY_PARENT_ALPHA },
+};
+const unsigned int COLOR_MODE_VALUES_COUNT = sizeof( COLOR_MODE_VALUES ) / sizeof( COLOR_MODE_VALUES[0] );
+
+const StringEnum POSITION_INHERITANCE_MODE_VALUES[] =
+{
+    { "INHERIT_PARENT_POSITION", INHERIT_PARENT_POSITION },
+    { "USE_PARENT_POSITION", USE_PARENT_POSITION },
+    { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION", USE_PARENT_POSITION_PLUS_LOCAL_POSITION },
+    { "DONT_INHERIT_POSITION", DONT_INHERIT_POSITION },
+};
+const unsigned int POSITION_INHERITANCE_MODE_VALUES_COUNT = sizeof( POSITION_INHERITANCE_MODE_VALUES ) / sizeof( POSITION_INHERITANCE_MODE_VALUES[0] );
+
+const StringEnum DRAW_MODE_VALUES[] =
+{
+    { "NORMAL", DrawMode::NORMAL },
+    { "OVERLAY_2D", DrawMode::OVERLAY_2D },
+    { "STENCIL", DrawMode::STENCIL },
+};
+const unsigned int DRAW_MODE_VALUES_COUNT = sizeof( DRAW_MODE_VALUES ) / sizeof( DRAW_MODE_VALUES[0] );
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Helpers for string to enum comparisons for Image and Image loading parameters
+////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Template to check enumerations of type T, with a class of type X
+ */
+template< typename T, typename X >
+void TestEnumStrings(
+  Property::Map& map,                       // The map used to create instance of type X
+  const char * const keyName,               // the name of the key to iterate through
+  const StringEnum* values,                 // An array of string values
+  unsigned int num,                         // Number of items in the array
+  T ( X::*method )() const,                 // The member method of X to call to get the enum
+  X ( *creator ) ( const Property::Value& ) // The method which creates an instance of type X
+)
+{
+  // get the key reference so we can change its value
+  Property::Value* value = map.Find( keyName );
+  for ( unsigned int i = 0; i < num; ++i )
+  {
+    *value = values[i].string;
+    tet_printf("Checking: %s: %s\n", keyName, values[i].string );
+    X instance = creator( map );
+    DALI_TEST_EQUALS( values[i].value, ( instance.*method )(), TEST_LOCATION );
+  }
+}
+
+/// Helper method to create ResourceImage using property
+ResourceImage NewResourceImage( const Property::Value& map )
+{
+  ResourceImage image = ResourceImage::DownCast( NewImage( map ) );
+  return image;
+}
+
+/// Helper method to create ResourceImage using property
+BufferImage NewBufferImage( const Property::Value& map )
+{
+  BufferImage image = BufferImage::DownCast( NewImage( map ) );
+  return image;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Helpers for string to enum comparisons for Actor to Property::Map
+//////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Template to check enumerations of type T
+ */
+template< typename T >
+void TestEnumStrings(
+  const char * const keyName,               // The name of the key to check
+  TestApplication& application,             // Reference to the application class
+  const StringEnum* values,                 // An array of string values
+  unsigned int num,                         // Number of items in the array
+  void ( Actor::*method )( T )              // The Actor member method to set the enumeration
+)
+{
+  for ( unsigned int i = 0; i < num; ++i )
+  {
+    tet_printf("Checking: %s: %s\n", keyName, values[i].string );
+
+    Actor actor = Actor::New();
+    (actor.*method)( ( T ) values[i].value );
+
+    Stage::GetCurrent().Add( actor );
+    application.SendNotification();
+    application.Render();
+
+    Property::Map map;
+    CreatePropertyMap( actor, map );
+
+    DALI_TEST_CHECK( 0 < map.Count() );
+    DALI_TEST_CHECK( NULL != map.Find( keyName ) );
+    DALI_TEST_EQUALS( map.Find( keyName )->Get< std::string >(), values[i].string, TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( actor );
+  }
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+
+} // anon namespace
+
+
+
+int UtcDaliScriptingGetColorMode(void)
+{
+  for ( unsigned int i = 0; i < COLOR_MODE_VALUES_COUNT; ++i )
+  {
+    tet_printf( "Checking %s == %d\n", COLOR_MODE_VALUES[i].string, COLOR_MODE_VALUES[i].value );
+    DALI_TEST_EQUALS( COLOR_MODE_VALUES[i].value, GetColorMode( COLOR_MODE_VALUES[i].string ), TEST_LOCATION );
+    DALI_TEST_EQUALS( COLOR_MODE_VALUES[i].string, GetColorMode( (ColorMode) COLOR_MODE_VALUES[i].value ), TEST_LOCATION );
+  }
+
+  DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, GetColorMode("INVALID_ARG"), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingGetPositionInheritanceMode(void)
+{
+  for ( unsigned int i = 0; i < POSITION_INHERITANCE_MODE_VALUES_COUNT; ++i )
+  {
+    tet_printf( "Checking %s == %d\n", POSITION_INHERITANCE_MODE_VALUES[i].string, POSITION_INHERITANCE_MODE_VALUES[i].value );
+    DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[i].value, GetPositionInheritanceMode( POSITION_INHERITANCE_MODE_VALUES[i].string ), TEST_LOCATION );
+    DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[i].string, GetPositionInheritanceMode( (PositionInheritanceMode) POSITION_INHERITANCE_MODE_VALUES[i].value ), TEST_LOCATION );
+  }
+
+  DALI_TEST_EQUALS( POSITION_INHERITANCE_MODE_VALUES[0].value, GetPositionInheritanceMode("INVALID_ARG"), TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliScriptingGetDrawMode(void)
+{
+  for ( unsigned int i = 0; i < DRAW_MODE_VALUES_COUNT; ++i )
+  {
+    tet_printf( "Checking %s == %d\n", DRAW_MODE_VALUES[i].string, DRAW_MODE_VALUES[i].value );
+    DALI_TEST_EQUALS( DRAW_MODE_VALUES[i].value, GetDrawMode( DRAW_MODE_VALUES[i].string ), TEST_LOCATION );
+    DALI_TEST_EQUALS( DRAW_MODE_VALUES[i].string, GetDrawMode( (DrawMode::Type) DRAW_MODE_VALUES[i].value ), TEST_LOCATION );
+  }
+
+  DALI_TEST_EQUALS( DRAW_MODE_VALUES[0].value, GetDrawMode( "INVALID_ARG" ), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliScriptingGetAnchorConstant(void)
+{
+  DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_LEFT, GetAnchorConstant( "TOP_LEFT" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_CENTER, GetAnchorConstant( "TOP_CENTER" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::TOP_RIGHT, GetAnchorConstant( "TOP_RIGHT" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER_LEFT, GetAnchorConstant( "CENTER_LEFT" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER, GetAnchorConstant( "CENTER" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::CENTER_RIGHT, GetAnchorConstant( "CENTER_RIGHT" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_LEFT, GetAnchorConstant( "BOTTOM_LEFT" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_CENTER, GetAnchorConstant( "BOTTOM_CENTER" ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Dali::ParentOrigin::BOTTOM_RIGHT, GetAnchorConstant( "BOTTOM_RIGHT" ), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Vector3(), GetAnchorConstant("INVALID_ARG"), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative01(void)
+{
+  // Invalid filename
+  Property::Map map;
+  map[ "filename" ] = Vector3::ZERO;
+  // will give us an empty image handle
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( !image );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative02(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid load-policy value type
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "load-policy" ] = Vector3::ZERO;
+  // will give us a valid image handle with default load policy
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetLoadPolicy(), ResourceImage::IMMEDIATE, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative03(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid load-policy value
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "load-policy" ] = "INVALID";
+  // will give us a valid image with default load policy
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetLoadPolicy(), ResourceImage::IMMEDIATE, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative04(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid release-policy value type
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "release-policy" ] = Vector3::ZERO;
+  // will give us a valid image with default release policy
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetReleasePolicy(), Image::NEVER, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative05(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid release-policy value
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "release-policy" ] = "INVALID";
+  // will give us a valid image with default release policy
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetReleasePolicy(), Image::NEVER, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative06(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid width and height
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "width" ] = "Invalid";
+  map[ "height" ] = 100;
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetWidth(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( resImage.GetHeight(), 100, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative07(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid height
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "width" ] = 10;
+  map[ "height" ] = "Invalid";
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  DALI_TEST_EQUALS( resImage.GetWidth(), 10, TEST_LOCATION );
+  DALI_TEST_EQUALS( resImage.GetHeight(), 0, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative08(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid fitting-mode
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "fitting-mode" ] = Vector3::ZERO;
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative09(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid value
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "fitting-mode" ] = "INVALID";
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative10(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid scaling-mode
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "sampling-mode" ] = Vector3::ZERO;
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative12(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid orientation-correction
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "orientation" ] = Vector3::ZERO;
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative13(void)
+{
+  TestApplication application; // Image needs application
+  // Invalid type
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+  map[ "type" ] = Vector3::ZERO;
+  // will give us a valid image
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  ResourceImage resImage = ResourceImage::DownCast( image );
+  DALI_TEST_CHECK( resImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative14(void)
+{
+  // Invalid value
+  Property::Map map;
+  map[ "type" ] = "INVALID";
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( !image );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative15(void)
+{
+  // Invalid pixel-format
+  Property::Map map;
+  map[ "pixel-format" ] = Vector3::ZERO;
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( !image );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImageNegative16(void)
+{
+  // Invalid value
+  Property::Map map;
+  map[ "pixel-format" ] = "INVALID";
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( !image );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage01P(void)
+{
+  TestApplication application; // Image needs application
+
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+
+  // Filename only
+  ResourceImage image = ResourceImage::DownCast( NewImage( map ) );
+  DALI_TEST_EQUALS( "TEST_FILE", image.GetUrl(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage02P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+
+  // load-policy
+  map[ "load-policy" ] = "";
+  const StringEnum values[] =
+  {
+    { "IMMEDIATE", ResourceImage::IMMEDIATE },
+    { "ON_DEMAND", ResourceImage::ON_DEMAND }
+  };
+  TestEnumStrings< ResourceImage::LoadPolicy, ResourceImage >( map, "load-policy", values, ( sizeof( values ) / sizeof ( values[0] ) ), &ResourceImage::GetLoadPolicy, &NewResourceImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage03P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+
+  // release-policy
+  map[ "release-policy" ] = "";
+  const StringEnum values[] =
+  {
+    { "UNUSED", Image::UNUSED },
+    { "NEVER", Image::NEVER }
+  };
+  TestEnumStrings< Image::ReleasePolicy, Image >( map, "release-policy", values, ( sizeof( values ) / sizeof ( values[0] ) ), &Image::GetReleasePolicy, &NewImage );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage04P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+
+  // float width and height
+  map[ "width" ] = (float) 10.0f;
+  map[ "height" ] = (float) 20.0f;
+  Image image = NewImage( map );
+  DALI_TEST_EQUALS( image.GetWidth(), 10.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( image.GetHeight(), 20.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage05P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "filename" ] = "TEST_FILE";
+
+  // width and height
+  map[ "width"] = 50;
+  map[ "height" ] = 70;
+  Image image = NewImage( map );
+  DALI_TEST_EQUALS( image.GetWidth(), 50u, TEST_LOCATION );
+  DALI_TEST_EQUALS( image.GetHeight(), 70u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage06P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  // type FrameBufferImage
+  map[ "type" ] = "FrameBufferImage";
+  // width and height
+  map[ "width"] = 50;
+  map[ "height" ] = 70;
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  DALI_TEST_CHECK( FrameBufferImage::DownCast( image ) );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage07P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  // type BufferImage
+  map[ "type" ] = "BufferImage";
+  // width and height
+  map[ "width"] = 50;
+  map[ "height" ] = 70;
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  DALI_TEST_CHECK( BufferImage::DownCast( image ) );
+  DALI_TEST_EQUALS( (BufferImage::DownCast( image )).GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage08P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "type" ] = "BufferImage";
+  // width and height
+  map[ "width"] = 66;
+  map[ "height" ] = 99;
+  // pixel-format
+  map[ "pixel-format" ] = "";
+  const StringEnum values[] =
+  {
+    { "A8", Pixel::A8 },
+    { "L8", Pixel::L8 },
+    { "LA88", Pixel::LA88 },
+    { "RGB565", Pixel::RGB565 },
+    { "BGR565", Pixel::BGR565 },
+    { "RGBA4444", Pixel::RGBA4444 },
+    { "BGRA4444", Pixel::BGRA4444 },
+    { "RGBA5551", Pixel::RGBA5551 },
+    { "BGRA5551", Pixel::BGRA5551 },
+    { "RGB888", Pixel::RGB888 },
+    { "RGB8888", Pixel::RGB8888 },
+    { "BGR8888", Pixel::BGR8888 },
+    { "RGBA8888", Pixel::RGBA8888 },
+    { "BGRA8888", Pixel::BGRA8888 },
+    // BufferImage does not support compressed formats
+  };
+  TestEnumStrings< Pixel::Format, BufferImage >( map, "pixel-format", values, ( sizeof( values ) / sizeof ( values[0] ) ), &BufferImage::GetPixelFormat, &NewBufferImage );
+
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage09P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  // type Image
+  map[ "type" ] = "ResourceImage";
+  map[ "filename" ] = "TEST_FILE";
+
+  {
+    Image image = NewImage( map );
+    DALI_TEST_CHECK( ResourceImage::DownCast( image ) );
+    DALI_TEST_CHECK( !FrameBufferImage::DownCast( image ) );
+    DALI_TEST_CHECK( !BufferImage::DownCast( image ) );
+  }
+  END_TEST;
+}
+
+int UtcDaliScriptingNewImage10P(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  // type FrameBufferImage, empty size gives us stage size
+  map[ "type" ] = "FrameBufferImage";
+  Image image = NewImage( map );
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewShaderEffect(void)
+{
+  TestApplication application;
+
+  Property::Map programMap;
+  programMap[ "vertex-filename" ] = "bump.vert";
+  programMap[ "fragment-filename" ] = "bump.frag";
+
+  Property::Map imageMap;
+  imageMap[ "filename" ] = "image.png";
+
+  Property::Map map;
+  map[ "image" ] = imageMap;
+  map[ "program" ] = programMap;
+  map[ "uLightPosition" ] = Vector3( 0.0, 0.0, -1.5);
+  map[ "uAmbientLight" ] = (int)10;
+
+  ShaderEffect shader = NewShaderEffect( map );
+
+  DALI_TEST_CHECK( shader );
+  END_TEST;
+}
+
+int UtcDaliScriptingNewActorNegative(void)
+{
+  TestApplication application;
+
+  // Empty map
+  {
+    Actor handle = NewActor( Property::Map() );
+    DALI_TEST_CHECK( !handle );
+  }
+
+  // Map with only properties
+  {
+    Property::Map map;
+    map[ "parent-origin" ] = ParentOrigin::TOP_CENTER;
+    map[ "anchor-point" ] = AnchorPoint::TOP_CENTER;
+    Actor handle = NewActor( map );
+    DALI_TEST_CHECK( !handle );
+  }
+
+  // Add some signals to the map, we should have no signal connections as its not yet supported
+  {
+    Property::Map map;
+    map[ "type" ] = "Actor";
+    map[ "signals" ] = Property::MAP;
+    Actor handle = NewActor( map );
+    DALI_TEST_CHECK( handle );
+    DALI_TEST_CHECK( !handle.WheelEventSignal().GetConnectionCount() );
+    DALI_TEST_CHECK( !handle.OffStageSignal().GetConnectionCount() );
+    DALI_TEST_CHECK( !handle.OnStageSignal().GetConnectionCount() );
+    DALI_TEST_CHECK( !handle.TouchedSignal().GetConnectionCount() );
+  }
+  END_TEST;
+}
+
+int UtcDaliScriptingNewActorProperties(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "type" ] = "Actor";
+  map[ "size" ] = Vector3::ONE;
+  map[ "position" ] = Vector3::XAXIS;
+  map[ "scale" ] = Vector3::ONE;
+  map[ "visible" ] = false;
+  map[ "color" ] = Color::MAGENTA;
+  map[ "name" ] = "MyActor";
+  map[ "color-mode" ] = "USE_PARENT_COLOR";
+  map[ "inherit-shader-effect" ] = false;
+  map[ "sensitive" ] = false;
+  map[ "leave-required" ] = true;
+  map[ "position-inheritance" ] = "DONT_INHERIT_POSITION";
+  map[ "draw-mode" ] = "STENCIL";
+  map[ "inherit-orientation" ] = false;
+  map[ "inherit-scale" ] = false;
+
+  // Default properties
+  {
+    Actor handle = NewActor( map );
+    DALI_TEST_CHECK( handle );
+
+    Stage::GetCurrent().Add( handle );
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( handle.GetCurrentSize(), Vector3::ONE, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetCurrentPosition(), Vector3::XAXIS, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.IsVisible(), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetCurrentColor(), Color::MAGENTA, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetName(), "MyActor", TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetColorMode(), USE_PARENT_COLOR, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.IsSensitive(), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetLeaveRequired(), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetPositionInheritanceMode(), DONT_INHERIT_POSITION, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetDrawMode(), DrawMode::STENCIL, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.IsOrientationInherited(), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.IsScaleInherited(), false, TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( handle );
+  }
+
+  // Check Anchor point and parent origin vector3s
+  map[ "parent-origin" ] = ParentOrigin::TOP_CENTER;
+  map[ "anchor-point" ] = AnchorPoint::TOP_LEFT;
+  {
+    Actor handle = NewActor( map );
+    DALI_TEST_CHECK( handle );
+
+    Stage::GetCurrent().Add( handle );
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( handle.GetCurrentParentOrigin(), ParentOrigin::TOP_CENTER, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetCurrentAnchorPoint(), AnchorPoint::TOP_LEFT, TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( handle );
+  }
+
+  // Check Anchor point and parent origin STRINGS
+  map[ "parent-origin" ] = "TOP_LEFT";
+  map[ "anchor-point" ] = "CENTER_LEFT";
+  {
+    Actor handle = NewActor( map );
+    DALI_TEST_CHECK( handle );
+
+    Stage::GetCurrent().Add( handle );
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( handle.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION );
+    DALI_TEST_EQUALS( handle.GetCurrentAnchorPoint(), AnchorPoint::CENTER_LEFT, TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( handle );
+  }
+  END_TEST;
+}
+
+int UtcDaliScriptingNewActorChildren(void)
+{
+  TestApplication application;
+
+  Property::Map map;
+  map[ "type" ] = "Actor";
+  map[ "position" ] = Vector3::XAXIS;
+
+  Property::Map child1Map;
+  child1Map[ "type" ] = "ImageActor";
+  child1Map[ "position" ] = Vector3::YAXIS;
+
+  Property::Array childArray;
+  childArray.PushBack( child1Map );
+  map[ "actors" ] = childArray;
+
+  // Create
+  Actor handle = NewActor( map );
+  DALI_TEST_CHECK( handle );
+
+  Stage::GetCurrent().Add( handle );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( handle.GetCurrentPosition(), Vector3::XAXIS, TEST_LOCATION );
+  DALI_TEST_EQUALS( handle.GetChildCount(), 1u, TEST_LOCATION );
+
+  Actor child1 = handle.GetChildAt(0);
+  DALI_TEST_CHECK( child1 );
+  DALI_TEST_CHECK( ImageActor::DownCast( child1 ) );
+  DALI_TEST_EQUALS( child1.GetCurrentPosition(), Vector3::YAXIS, TEST_LOCATION );
+  DALI_TEST_EQUALS( child1.GetChildCount(), 0u, TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( handle );
+  END_TEST;
+}
+
+
+int UtcDaliScriptingCreatePropertyMapActor(void)
+{
+  TestApplication application;
+
+  // Actor Type
+  {
+    Actor actor = Actor::New();
+
+    Property::Map map;
+    CreatePropertyMap( actor, map );
+    DALI_TEST_CHECK( !map.Empty() );
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type")->Get< std::string >(), "Actor", TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( actor );
+  }
+
+  // ImageActor Type
+  {
+    Actor actor = ImageActor::New();
+
+    Property::Map map;
+    CreatePropertyMap( actor, map );
+    DALI_TEST_CHECK( !map.Empty() );
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ImageActor", TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( actor );
+  }
+
+  // Default properties
+  {
+    Actor actor = Actor::New();
+    actor.SetSize( Vector3::ONE );
+    actor.SetPosition( Vector3::XAXIS );
+    actor.SetScale( Vector3::ZAXIS );
+    actor.SetVisible( false );
+    actor.SetColor( Color::MAGENTA );
+    actor.SetName( "MyActor" );
+    actor.SetAnchorPoint( AnchorPoint::CENTER_LEFT );
+    actor.SetParentOrigin( ParentOrigin::TOP_RIGHT );
+    actor.SetSensitive( false );
+    actor.SetLeaveRequired( true );
+    actor.SetInheritOrientation( false );
+    actor.SetInheritScale( false );
+    actor.SetSizeModeFactor( Vector3::ONE );
+
+    Stage::GetCurrent().Add( actor );
+    application.SendNotification();
+    application.Render();
+
+    Property::Map map;
+    CreatePropertyMap( actor, map );
+
+    DALI_TEST_CHECK( !map.Empty() );
+    DALI_TEST_CHECK( NULL != map.Find( "size" ) );
+    DALI_TEST_EQUALS( map.Find( "size" )->Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "position" ) );
+    DALI_TEST_EQUALS( map.Find( "position" )->Get< Vector3 >(), Vector3::XAXIS, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "scale" ) );
+    DALI_TEST_EQUALS( map.Find( "scale" )->Get< Vector3 >(), Vector3::ZAXIS, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "visible" ) );
+    DALI_TEST_EQUALS( map.Find( "visible" )->Get< bool >(), false, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "color" ) );
+    DALI_TEST_EQUALS( map.Find( "color" )->Get< Vector4 >(), Color::MAGENTA, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "name" ) );
+    DALI_TEST_EQUALS( map.Find( "name")->Get< std::string >(), "MyActor", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "anchor-point" ) );
+    DALI_TEST_EQUALS( map.Find( "anchor-point" )->Get< Vector3 >(), AnchorPoint::CENTER_LEFT, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "parent-origin" ) );
+    DALI_TEST_EQUALS( map.Find( "parent-origin" )->Get< Vector3 >(), ParentOrigin::TOP_RIGHT, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "sensitive" ) );
+    DALI_TEST_EQUALS( map.Find( "sensitive" )->Get< bool >(), false, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "leave-required" ) );
+    DALI_TEST_EQUALS( map.Find( "leave-required" )->Get< bool >(), true, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "inherit-orientation" ) );
+    DALI_TEST_EQUALS( map.Find( "inherit-orientation" )->Get< bool >(), false, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "inherit-scale" ) );
+    DALI_TEST_EQUALS( map.Find( "inherit-scale" )->Get< bool >(), false, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "size-mode-factor" ) );
+    DALI_TEST_EQUALS( map.Find( "size-mode-factor" )->Get< Vector3 >(), Vector3::ONE, TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( actor );
+  }
+
+  // ColorMode
+  TestEnumStrings< ColorMode >( "color-mode", application, COLOR_MODE_VALUES, COLOR_MODE_VALUES_COUNT, &Actor::SetColorMode );
+
+  // PositionInheritanceMode
+  TestEnumStrings< PositionInheritanceMode >( "position-inheritance", application, POSITION_INHERITANCE_MODE_VALUES, POSITION_INHERITANCE_MODE_VALUES_COUNT, &Actor::SetPositionInheritanceMode );
+
+  // DrawMode
+  TestEnumStrings< DrawMode::Type >( "draw-mode", application, DRAW_MODE_VALUES, DRAW_MODE_VALUES_COUNT, &Actor::SetDrawMode );
+
+  // Children
+  {
+    Actor actor = Actor::New();
+    Actor child = ImageActor::New();
+    actor.Add( child );
+
+    Stage::GetCurrent().Add( actor );
+    application.SendNotification();
+    application.Render();
+
+    Property::Map map;
+    CreatePropertyMap( actor, map );
+    DALI_TEST_CHECK( !map.Empty() );
+
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "Actor", TEST_LOCATION );
+
+    DALI_TEST_CHECK( NULL != map.Find( "actors" ) );
+    Property::Array children( map.Find( "actors")->Get< Property::Array >() );
+    DALI_TEST_CHECK( !children.Empty() );
+    Property::Map childMap( children[0].Get< Property::Map >() );
+    DALI_TEST_CHECK( !childMap.Empty() );
+    DALI_TEST_CHECK( childMap.Find( "type" ) );
+    DALI_TEST_EQUALS( childMap.Find( "type" )->Get< std::string >(), "ImageActor", TEST_LOCATION );
+
+    Stage::GetCurrent().Remove( actor );
+  }
+  END_TEST;
+}
+
+int UtcDaliScriptingCreatePropertyMapImage(void)
+{
+  TestApplication application;
+
+  // Empty
+  {
+    Image image;
+    Property::Map map;
+    CreatePropertyMap( image, map );
+    DALI_TEST_CHECK( map.Empty() );
+  }
+
+  // Default
+  {
+    Image image = ResourceImage::New( "MY_PATH" );
+
+    Property::Map map;
+    CreatePropertyMap( image, map );
+    DALI_TEST_CHECK( !map.Empty() );
+
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ResourceImage", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "filename" ) );
+    DALI_TEST_EQUALS( map.Find( "filename" )->Get< std::string >(), "MY_PATH", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "load-policy") );
+    DALI_TEST_EQUALS( map.Find( "load-policy" )->Get< std::string >(), "IMMEDIATE", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "release-policy") );
+    DALI_TEST_EQUALS( map.Find( "release-policy" )->Get< std::string >(), "NEVER", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL == map.Find( "width" ) );
+    DALI_TEST_CHECK( NULL == map.Find( "height" ) );
+  }
+
+  // Change values
+  {
+    ResourceImage image = ResourceImage::New( "MY_PATH", ResourceImage::ON_DEMAND, Image::UNUSED, ImageDimensions( 300, 400 ), FittingMode::FIT_WIDTH );
+
+    Property::Map map;
+    CreatePropertyMap( image, map );
+    DALI_TEST_CHECK( !map.Empty() );
+
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "ResourceImage", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "filename" ) );
+    DALI_TEST_EQUALS( map.Find( "filename" )->Get< std::string >(), "MY_PATH", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "load-policy") );
+    DALI_TEST_EQUALS( map.Find( "load-policy" )->Get< std::string >(), "ON_DEMAND", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "release-policy") );
+    DALI_TEST_EQUALS( map.Find( "release-policy" )->Get< std::string >(), "UNUSED", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "width" ) );
+    DALI_TEST_EQUALS( map.Find( "width" )->Get< int >(), 300, TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "height" ) );
+    DALI_TEST_EQUALS( map.Find( "height" )->Get< int >(), 400, TEST_LOCATION );
+  }
+
+  // BufferImage
+  {
+    Image image = BufferImage::New( 200, 300, Pixel::A8 );
+    Property::Map map;
+    CreatePropertyMap( image, map );
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "BufferImage", TEST_LOCATION );
+    DALI_TEST_CHECK( NULL != map.Find( "pixel-format") );
+    DALI_TEST_EQUALS( map.Find( "pixel-format" )->Get< std::string >(), "A8", TEST_LOCATION );
+  }
+
+  // FrameBufferImage
+  {
+    Image image = FrameBufferImage::New( 200, 300, Pixel::RGBA8888 );
+    Property::Map map;
+    CreatePropertyMap( image, map );
+    DALI_TEST_CHECK( NULL != map.Find( "type" ) );
+    DALI_TEST_EQUALS( map.Find( "type" )->Get< std::string >(), "FrameBufferImage", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliScriptingGetEnumerationTemplates(void)
+{
+  const Scripting::StringEnum myTable[] =
+  {
+    { "ONE",    1 },
+    { "TWO",    2 },
+    { "THREE",  3 },
+    { "FOUR",   4 },
+    { "FIVE",   5 },
+  };
+  const unsigned int myTableCount = sizeof( myTable ) / sizeof( myTable[0] );
+
+  for ( unsigned int i = 0; i < myTableCount; ++i )
+  {
+    tet_printf("Checking: %s\n", myTable[ i ].string );
+    int value;
+    DALI_TEST_CHECK( GetEnumeration<int>( myTable[ i ].string, myTable, myTableCount, value ) );
+    DALI_TEST_EQUALS( myTable[ i ].value, value, TEST_LOCATION );
+  }
+
+  for ( unsigned int i = 0; i < myTableCount; ++i )
+  {
+    tet_printf("Checking: %d\n", myTable[ i ].value );
+    DALI_TEST_EQUALS( myTable[ i ].string, GetEnumerationName( myTable[ i ].value, myTable, myTableCount ), TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliScriptingGetEnumerationNameN(void)
+{
+  const char* value = GetEnumerationName( 10, NULL, 0 );
+  DALI_TEST_CHECK( NULL == value );
+
+  value = GetEnumerationName( 10, NULL, 1 );
+  DALI_TEST_CHECK( NULL == value );
+
+  END_TEST;
+}
+
+int UtcDaliScriptingGetLinearEnumerationNameN(void)
+{
+  const char* value = GetLinearEnumerationName( 10, NULL, 0 );
+  DALI_TEST_CHECK( NULL == value );
+
+  value = GetLinearEnumerationName( 10, NULL, 1 );
+  DALI_TEST_CHECK( NULL == value );
+
+  END_TEST;
+}
+
+int UtcDaliScriptingFindEnumIndexN(void)
+{
+  const Scripting::StringEnum myTable[] =
+  {
+    { "ONE",    1 },
+    { "TWO",    2 },
+    { "THREE",  3 },
+    { "FOUR",   4 },
+    { "FIVE",   5 },
+  };
+  const unsigned int myTableCount = sizeof( myTable ) / sizeof( myTable[0] );
+  DALI_TEST_EQUALS( myTableCount, FindEnumIndex( "Foo", myTable, myTableCount ), TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-Shader.cpp b/automated-tests/src/dali-devel/utc-Dali-Shader.cpp
new file mode 100644 (file)
index 0000000..5cf3a34
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <mesh-builder.h>
+
+using namespace Dali;
+
+void utc_dali_shader_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_shader_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+static const char* VertexSource =
+"This is a custom vertex shader\n"
+"made on purpose to look nothing like a normal vertex shader inside dali\n";
+
+static const char* FragmentSource =
+"This is a custom fragment shader\n"
+"made on purpose to look nothing like a normal fragment shader inside dali\n";
+
+
+void TestConstraintNoBlue( Vector4& current, const PropertyInputContainer& inputs )
+{
+  current.b = 0.0f;
+}
+
+
+} // anon namespace
+
+
+int UtcDaliShaderMethodNew01(void)
+{
+  TestApplication application;
+
+  Shader shader = Shader::New( VertexSource, FragmentSource );
+  DALI_TEST_EQUALS((bool)shader, true, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliShaderMethodNew02(void)
+{
+  TestApplication application;
+
+  Shader shader;
+  DALI_TEST_EQUALS((bool)shader, false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliShaderAssignmentOperator(void)
+{
+  TestApplication application;
+
+  Shader shader1 = Shader::New(VertexSource, FragmentSource);
+
+  Shader shader2;
+
+  DALI_TEST_CHECK(!(shader1 == shader2));
+
+  shader2 = shader1;
+
+  DALI_TEST_CHECK(shader1 == shader2);
+
+  shader2 = Shader::New(VertexSource, FragmentSource);;
+
+  DALI_TEST_CHECK(!(shader1 == shader2));
+
+  END_TEST;
+}
+
+int UtcDaliShaderDownCast01(void)
+{
+  TestApplication application;
+
+  Shader shader = Shader::New(VertexSource, FragmentSource);
+
+  BaseHandle handle(shader);
+  Shader shader2 = Shader::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)shader2, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliShaderDownCast02(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New(); // Create a custom object
+  Shader shader = Shader::DownCast(handle);
+  DALI_TEST_EQUALS( (bool)shader, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliShaderConstraint01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform shader property can be constrained");
+
+  Shader shader = Shader::New(VertexSource, FragmentSource);
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( shader, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+  // Expect no blue component in either buffer - yellow
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), Color::YELLOW, TEST_LOCATION );
+
+  shader.RemoveConstraints();
+  shader.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliShaderConstraint02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map shader property can be constrained");
+
+  Shader shader = Shader::New(VertexSource, FragmentSource);
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  // Apply constraint
+  Constraint constraint = Constraint::New<Vector4>( shader, colorIndex, TestConstraintNoBlue );
+  constraint.Apply();
+  application.SendNotification();
+  application.Render(0);
+
+   // Expect no blue component in either buffer - yellow
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  application.Render(0);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::YELLOW, TEST_LOCATION );
+
+  shader.RemoveConstraints();
+  shader.SetProperty(colorIndex, Color::WHITE );
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliShaderAnimatedProperty01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a non-uniform shader property can be animated");
+
+  Shader shader = Shader::New(VertexSource, FragmentSource);
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( shader, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+
+  DALI_TEST_EQUALS( shader.GetProperty<Vector4>(colorIndex), Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliShaderAnimatedProperty02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that a uniform map shader property can be animated");
+
+  Shader shader = Shader::New(VertexSource, FragmentSource);
+  Material material = Material::New( shader );
+  material.SetProperty(Material::Property::COLOR, Color::WHITE);
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor actor = Actor::New();
+  actor.AddRenderer(renderer);
+  actor.SetSize(400, 400);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 initialColor = Color::WHITE;
+  Property::Index colorIndex = shader.RegisterProperty( "uFadeColor", initialColor );
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+
+  application.SendNotification();
+  application.Render(0);
+
+  Vector4 actualValue(Vector4::ZERO);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, initialColor, TEST_LOCATION );
+
+  Animation  animation = Animation::New(1.0f);
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, initialColor);
+  keyFrames.Add(1.0f, Color::TRANSPARENT);
+  animation.AnimateBetween( Property( shader, colorIndex ), keyFrames );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(500);
+
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::WHITE * 0.5f, TEST_LOCATION );
+
+  application.Render(500);
+  DALI_TEST_CHECK( gl.GetUniformValue<Vector4>( "uFadeColor", actualValue ) );
+  DALI_TEST_EQUALS( actualValue, Color::TRANSPARENT, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp b/automated-tests/src/dali-devel/utc-Dali-WeakHandle.cpp
new file mode 100644 (file)
index 0000000..fedb2e1
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/object/weak-handle.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+/*******************************************************************************
+ *
+ * Custom Actor
+ *
+ ******************************************************************************/
+namespace Impl
+{
+struct MyTestCustomActor : public CustomActorImpl
+{
+  typedef Signal< void ()> SignalType;
+  typedef Signal< void (float)> SignalTypeFloat;
+
+  MyTestCustomActor() : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS ) )
+  { }
+
+  virtual ~MyTestCustomActor()
+  { }
+
+  void ResetCallStack()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+  }
+  virtual void OnStageDisconnection()
+  {
+  }
+  virtual void OnChildAdd(Actor& child)
+  {
+  }
+  virtual void OnChildRemove(Actor& child)
+  {
+  }
+  virtual void OnSizeSet(const Vector3& targetSize)
+  {
+  }
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+  {
+  }
+  virtual bool OnTouchEvent(const TouchEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnHoverEvent(const HoverEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnWheelEvent(const WheelEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnKeyEvent(const KeyEvent& event)
+  {
+    return true;
+  }
+  virtual void OnKeyInputFocusGained()
+  {
+  }
+  virtual void OnKeyInputFocusLost()
+  {
+  }
+  virtual Vector3 GetNaturalSize()
+  {
+    return Vector3( 0.0f, 0.0f, 0.0f );
+  }
+
+  virtual float GetHeightForWidth( float width )
+  {
+    return 0.0f;
+  }
+
+  virtual float GetWidthForHeight( float height )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+  }
+
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+  {
+  }
+
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+  }
+
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+  }
+
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS )
+  {
+    return false;
+  }
+
+public:
+
+  SignalType mSignal;
+};
+
+}; // namespace Impl
+
+class MyTestCustomActor : public CustomActor
+{
+public:
+
+  typedef Signal< void ()> SignalType;
+  typedef Signal< void (float)> SignalTypeFloat;
+
+  MyTestCustomActor()
+  {
+  }
+
+  static MyTestCustomActor New()
+  {
+    Impl::MyTestCustomActor* p = new Impl::MyTestCustomActor;
+    return MyTestCustomActor( *p ); // takes ownership
+  }
+
+  virtual ~MyTestCustomActor()
+  {
+  }
+
+  static MyTestCustomActor DownCast( BaseHandle handle )
+  {
+    MyTestCustomActor result;
+
+    CustomActor custom = Dali::CustomActor::DownCast( handle );
+    if ( custom )
+    {
+      CustomActorImpl& customImpl = custom.GetImplementation();
+
+      Impl::MyTestCustomActor* impl = dynamic_cast<Impl::MyTestCustomActor*>(&customImpl);
+
+      if (impl)
+      {
+        result = MyTestCustomActor(customImpl.GetOwner());
+      }
+    }
+
+    return result;
+  }
+
+  SignalType& GetCustomSignal()
+  {
+    Dali::RefObject& obj = GetImplementation();
+    return static_cast<Impl::MyTestCustomActor&>( obj ).mSignal;
+  }
+
+  MyTestCustomActor(Internal::CustomActor* internal)
+  : CustomActor(internal)
+  {
+  }
+
+  MyTestCustomActor( Impl::MyTestCustomActor& impl )
+  : CustomActor( impl )
+  {
+  }
+};
+
+}
+
+int UtcDaliWeakHandleBaseConstructorVoid(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase()");
+
+  WeakHandleBase object;
+
+  DALI_TEST_CHECK(!object.GetBaseHandle());
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseConstructorWithHandle(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(Handle)");
+
+  Handle emptyHandle;
+  WeakHandleBase emptyObject(emptyHandle);
+  DALI_TEST_CHECK(!emptyObject.GetBaseHandle());
+
+  Actor actor = Actor::New();
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseCopyConstructor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&)");
+
+  Actor actor = Actor::New();
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  WeakHandleBase copy(object);
+  DALI_TEST_CHECK(copy.GetBaseHandle() == actor);
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseAssignmentOperator(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandleBase::operator=");
+
+  Actor actor = Actor::New();
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  WeakHandleBase copy = object;
+  DALI_TEST_CHECK(copy.GetBaseHandle() == actor);
+  DALI_TEST_EQUALS(1, actor.GetBaseObject().ReferenceCount(), TEST_LOCATION); // reference count of the actor is not increased
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseEqualityOperatorP(void)
+{
+  TestApplication application;
+  tet_infoline("Positive Test Dali::WeakHandleBase::operator==");
+
+  WeakHandleBase object;
+  WeakHandleBase theSameObject;
+  DALI_TEST_CHECK(object == theSameObject);
+
+  Actor actor = Actor::New();
+
+  object = WeakHandleBase(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  theSameObject = object;
+  DALI_TEST_CHECK(theSameObject.GetBaseHandle() == actor);
+  DALI_TEST_CHECK(object == theSameObject);
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseEqualityOperatorN(void)
+{
+  TestApplication application;
+  tet_infoline("Negative Test Dali::WeakHandleBase::operator==");
+
+  Actor actor = Actor::New();
+
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  Actor differentActor = Actor::New();
+  WeakHandleBase aDifferentWeakHandleBase(differentActor);
+
+  DALI_TEST_CHECK(!(object == aDifferentWeakHandleBase));
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseInequalityOperatorP(void)
+{
+  TestApplication application;
+  tet_infoline("Positive Test Dali::WeakHandleBase::operator!=");
+
+  Actor actor = Actor::New();
+
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  Actor differentActor = Actor::New();
+  WeakHandleBase aDifferentWeakHandleBase(differentActor);
+
+  DALI_TEST_CHECK(object != aDifferentWeakHandleBase);
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseInequalityOperatorN(void)
+{
+  TestApplication application;
+  tet_infoline("Negative Test Dali::WeakHandleBase::operator!=");
+
+  Actor actor = Actor::New();
+
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  WeakHandleBase theSameWeakHandleBase = object;
+
+  DALI_TEST_CHECK(!(object != theSameWeakHandleBase));
+  END_TEST;
+}
+
+int UtcDaliWeakHandleBaseGetBaseHandle(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandleBase::GetBaseHandle()");
+
+  Handle emptyHandle;
+  WeakHandleBase emptyObject(emptyHandle);
+  DALI_TEST_CHECK(!emptyObject.GetBaseHandle());
+
+  Actor actor = Actor::New();
+  WeakHandleBase object(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == actor);
+
+  WeakHandleBase theSameObject = WeakHandleBase(actor);
+  DALI_TEST_CHECK(object.GetBaseHandle() == theSameObject.GetBaseHandle());
+
+  Actor differentActor = Actor::New();
+  WeakHandleBase aDifferentWeakHandleBase(differentActor);
+  DALI_TEST_CHECK(object.GetBaseHandle() != aDifferentWeakHandleBase.GetBaseHandle());
+
+  END_TEST;
+}
+
+int UtcDaliWeakHandleGetHandle(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::WeakHandle::GetHandle()");
+
+  Actor actor = Actor::New();
+  WeakHandle<Actor> object(actor);
+  DALI_TEST_CHECK(object.GetHandle() == actor);
+
+  MyTestCustomActor customActor = MyTestCustomActor::New();
+  WeakHandle<MyTestCustomActor> customObject(customActor);
+  DALI_TEST_CHECK(customObject.GetHandle() == customActor);
+
+  DALI_TEST_CHECK(object.GetHandle() != customObject.GetHandle());
+
+  END_TEST;
+}
+
+
+
diff --git a/automated-tests/src/dali-internal/CMakeLists.txt b/automated-tests/src/dali-internal/CMakeLists.txt
new file mode 100644 (file)
index 0000000..8678b55
--- /dev/null
@@ -0,0 +1,57 @@
+SET(PKG_NAME "dali-internal")
+
+SET(EXEC_NAME "tct-${PKG_NAME}-core")
+SET(RPM_NAME "core-${PKG_NAME}-tests")
+
+SET(CAPI_LIB "dali-internal")
+
+SET(TC_SOURCES
+        utc-Dali-Internal-Handles.cpp
+        utc-Dali-Internal-ImageFactory.cpp
+        utc-Dali-Internal-ResourceClient.cpp
+        utc-Dali-Internal-Image-Culling.cpp
+        utc-Dali-Internal-FixedSizeMemoryPool.cpp
+        utc-Dali-Internal-MemoryPoolObjectAllocator.cpp
+        utc-Dali-Internal-FrustumCulling.cpp
+)
+
+LIST(APPEND TC_SOURCES
+        ../dali/dali-test-suite-utils/mesh-builder.cpp
+        ../dali/dali-test-suite-utils/test-harness.cpp
+        ../dali/dali-test-suite-utils/dali-test-suite-utils.cpp
+        ../dali/dali-test-suite-utils/test-application.cpp
+        ../dali/dali-test-suite-utils/test-gesture-manager.cpp
+        ../dali/dali-test-suite-utils/test-gl-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-native-image.cpp
+        ../dali/dali-test-suite-utils/test-platform-abstraction.cpp
+        ../dali/dali-test-suite-utils/test-render-controller.cpp
+        ../dali/dali-test-suite-utils/test-trace-call-stack.cpp
+)
+
+PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
+     dali-core
+)
+
+SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type")
+
+FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
+    SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}")
+ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS})
+
+INCLUDE_DIRECTORIES(
+    ../../..
+    .
+    ${${CAPI_LIB}_INCLUDE_DIRS}
+    ../dali/dali-test-suite-utils
+    ../dali-devel
+)
+
+ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES})
+TARGET_LINK_LIBRARIES(${EXEC_NAME}
+    ${${CAPI_LIB}_LIBRARIES}
+)
+
+INSTALL(PROGRAMS ${EXEC_NAME}
+    DESTINATION ${BIN_DIR}/${EXEC_NAME}
+)
diff --git a/automated-tests/src/dali-internal/tct-dali-internal-core.cpp b/automated-tests/src/dali-internal/tct-dali-internal-core.cpp
new file mode 100644 (file)
index 0000000..359a7d2
--- /dev/null
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <test-harness.h>
+#include "tct-dali-internal-core.h"
+
+int main(int argc, char * const argv[])
+{
+  int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT;
+
+  const char* optString = "r";
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'r':
+        optRerunFailed = true;
+        break;
+      case '?':
+        TestHarness::Usage(argv[0]);
+        exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT);
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optind == argc ) // no testcase name in argument list
+  {
+    result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed);
+  }
+  else
+  {
+    // optind is index of next argument - interpret as testcase name
+    result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]);
+  }
+  return result;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-FixedSizeMemoryPool.cpp
new file mode 100644 (file)
index 0000000..c4f653f
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+#include <dali/internal/common/fixed-size-memory-pool.h>
+
+using namespace Dali;
+
+void utc_dali_internal_fixedsizememorypool_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_fixedsizememorypool_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+unsigned int gTestObjectConstructed = 0;
+unsigned int gTestObjectDestructed = 0;
+unsigned int gTestObjectMethod = 0;
+unsigned int gTestObjectDataAccess = 0;
+
+} // namespace
+
+
+class TestObject
+{
+public:
+
+  TestObject()
+  : mData1( 0 ),
+    mData2( false )
+  {
+    gTestObjectConstructed++;
+  }
+
+  ~TestObject()
+  {
+    gTestObjectDestructed++;
+  }
+
+  void Method()
+  {
+    gTestObjectMethod++;
+  }
+
+  void DataAccess()
+  {
+    mData1++;
+    mData2 = true;
+
+    gTestObjectDataAccess++;
+  }
+
+private:
+
+  unsigned int mData1;
+  bool mData2;
+
+};
+
+int UtcDaliFixedSizeMemoryPoolCreate(void)
+{
+  gTestObjectConstructed = 0;
+  gTestObjectDestructed = 0;
+  gTestObjectMethod = 0;
+  gTestObjectDataAccess = 0;
+
+  Internal::FixedSizeMemoryPool memoryPool( Internal::TypeSizeWithAlignment< TestObject >::size );
+
+  TestObject* testObject1 = new (memoryPool.Allocate()) TestObject();
+  DALI_TEST_CHECK( testObject1 );
+  DALI_TEST_EQUALS( gTestObjectConstructed, 1U, TEST_LOCATION );
+
+  testObject1->Method();
+  DALI_TEST_EQUALS( gTestObjectMethod, 1U, TEST_LOCATION );
+
+  testObject1->DataAccess();
+  DALI_TEST_EQUALS( gTestObjectDataAccess, 1U, TEST_LOCATION );
+
+  testObject1->~TestObject();
+  memoryPool.Free( testObject1 );
+  DALI_TEST_EQUALS( gTestObjectDestructed, 1U, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliFixedSizeMemoryPoolStressTest(void)
+{
+  gTestObjectConstructed = 0;
+  gTestObjectDestructed = 0;
+  gTestObjectMethod = 0;
+  gTestObjectDataAccess = 0;
+
+  const size_t initialCapacity = 32;
+  const size_t maximumCapacity = 1024;
+
+  const unsigned int numObjects = 1024 * 1024;
+
+  Internal::FixedSizeMemoryPool memoryPool( Internal::TypeSizeWithAlignment< TestObject >::size, initialCapacity, maximumCapacity );
+
+  Dali::Vector<TestObject*> objects;
+  objects.Reserve( numObjects );
+
+  for( unsigned int i = 0; i < numObjects; ++i )
+  {
+    TestObject* testObject = new ( memoryPool.Allocate() ) TestObject();
+    DALI_TEST_CHECK( testObject );
+
+    objects.PushBack( testObject );
+  }
+
+  DALI_TEST_EQUALS( gTestObjectConstructed, numObjects, TEST_LOCATION );
+
+  for( unsigned int i = 0; i < numObjects; ++i )
+  {
+    objects[i]->~TestObject();
+    memoryPool.Free( objects[i] );
+  }
+
+  DALI_TEST_EQUALS( gTestObjectDestructed, numObjects, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-FrustumCulling.cpp
new file mode 100644 (file)
index 0000000..5a65c6d
--- /dev/null
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <dali/devel-api/object/property-buffer.h>
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/renderer.h>
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/devel-api/rendering/shader.h>
+
+using namespace Dali;
+
+#define MAKE_SHADER(A)#A
+
+const char* VERTEX_SHADER = MAKE_SHADER(
+attribute mediump vec2    aPosition;
+attribute mediump vec2    aTexCoord;
+uniform   mediump mat4    uMvpMatrix;
+uniform   mediump vec3    uSize;
+varying   mediump vec2    vTexCoord;
+
+void main()
+{
+  mediump vec4 vertexPosition = vec4(aPosition, 0.0, 1.0);
+  vertexPosition.xyz *= uSize;
+  vertexPosition = uMvpMatrix * vertexPosition;
+  vTexCoord = aTexCoord;
+  gl_Position = vertexPosition;
+}
+);
+
+const char* FRAGMENT_SHADER = MAKE_SHADER(
+uniform Sampler2D sTexture;
+varying mediump vec2 vTexCoord;
+void main()
+{
+  gl_FragColor = texture2D( sTexture, vTexCoord );
+}
+);
+
+Geometry CreateGeometry()
+{
+  const float halfQuadSize = .5f;
+  struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
+  PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+  texturedQuadVertices.SetData(texturedQuadVertexData);
+
+  // Create indices
+  unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
+  Property::Map indexFormat;
+  indexFormat["indices"] = Property::INTEGER;
+  PropertyBuffer indices = PropertyBuffer::New( indexFormat, sizeof(indexData)/sizeof(indexData[0]) );
+  indices.SetData(indexData);
+
+  // Create the geometry object
+  Geometry texturedQuadGeometry = Geometry::New();
+  texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices );
+  texturedQuadGeometry.SetIndexBuffer( indices );
+
+  return texturedQuadGeometry;
+}
+
+int UtcFrustumCullN(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( ParentOrigin::CENTER );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumLeftCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( -0.42f, 0.5f, 0.5f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be box culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  meshActor.SetParentOrigin( Vector3( -0.5f, 0.5f, 0.5f ) );
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumRightCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 1.42f, 0.5f, 0.5f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This should be box culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  meshActor.SetParentOrigin( Vector3( 1.5f, 0.0f, 0.5f ) );
+  application.SendNotification();
+  application.Render(16);
+
+  // This should be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumTopCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 0.5f, -0.32f, 0.5f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This should be box culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  meshActor.SetParentOrigin( Vector3( 0.5f, -0.5f, 0.5f ) );
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumBottomCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 0.5f, 1.32f, 0.5f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This should be box culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+
+  drawTrace.Reset();
+  meshActor.SetParentOrigin( Vector3( 0.5f, 1.5f, 0.5f ) );
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumNearCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, 7.0f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumFarCullP(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, -7.0f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This will be sphere culled
+  DALI_TEST_CHECK( !drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
+
+int UtcFrustumCullDisabledP(void)
+{
+    TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  PixelBuffer* pixelBuffer = new PixelBuffer[ 4 ];
+  BufferImage image = BufferImage::New( pixelBuffer, 1, 1 );
+
+  Geometry geometry = CreateGeometry();
+  Material material = Material::New( Shader::New( VERTEX_SHADER, FRAGMENT_SHADER, Shader::HINT_MODIFIES_GEOMETRY ) );
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+  Renderer renderer = Renderer::New( geometry, material );
+
+  Actor meshActor = Actor::New();
+  meshActor.AddRenderer( renderer );
+  meshActor.SetSize(400, 400);
+  drawTrace.Reset();
+
+  meshActor.SetParentOrigin( Vector3( 0.5f, 0.5f, -7.0f ) );
+  meshActor.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( meshActor );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // This should not be culled
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawElements" ) );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Handles.cpp
new file mode 100644 (file)
index 0000000..9d26c45
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+
+using namespace Dali;
+
+void utc_dali_internal_handles_startup()
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_handles_cleanup()
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliCameraActorConstructorRefObject(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CameraActor::CameraActor(Internal::CameraActor*)");
+
+  CameraActor actor(NULL);
+
+  DALI_TEST_CHECK(!actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorConstructorRefObject(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor::ImageActor(Internal::ImageActor*)");
+
+  ImageActor actor(NULL);
+
+  DALI_TEST_CHECK(!actor);
+  END_TEST;
+}
+
+int UtcDaliTextActorConstructorRefObject(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::TextActor::TextActor(Internal::TextActor*)");
+  ImageActor actor(NULL);
+  DALI_TEST_CHECK(!actor);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-Image-Culling.cpp
new file mode 100644 (file)
index 0000000..7297524
--- /dev/null
@@ -0,0 +1,847 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_internal_image_culling_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_image_culling_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+namespace
+{
+#define NUM_ROWS 9
+#define NUM_COLS 9
+#define NUM_ROWS_PER_PANE 3
+#define NUM_COLS_PER_PANE 3
+const unsigned int TEXTURE_ID_OFFSET = 23;
+
+Image LoadImage( TestApplication& application, GLuint textureId, int width, int height )
+{
+  Image image;
+  char* filename = NULL;
+  int numChars = asprintf(&filename, "image%u.png", textureId );
+
+  if( numChars > 0 )
+  {
+    const Vector2 closestImageSize( width, height );
+    application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+    image = ResourceImage::New( filename, ResourceImage::IMMEDIATE, Image::NEVER );
+    free (filename);
+  }
+  DALI_TEST_CHECK(image);
+  application.SendNotification();
+  application.Render(16);
+
+  std::vector<GLuint> ids;
+  ids.push_back( textureId );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, width, height, width, height);
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+  DALI_TEST_CHECK( request != NULL );
+  if(request)
+  {
+    application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, resource);
+  }
+  application.SendNotification();
+  application.Render(16);
+  application.GetPlatform().ClearReadyResources();
+  application.GetPlatform().DiscardRequest();
+  application.SendNotification();
+  application.Render(16);
+
+  return image;
+}
+
+ImageActor CreateOnStageActor(TestApplication& application, Image image, int width, int height, bool testDraw)
+{
+  ImageActor imageActor = ImageActor::New(image);
+  Stage::GetCurrent().Add(imageActor);
+
+  imageActor.SetParentOrigin(ParentOrigin::CENTER);
+  application.SendNotification();
+  application.Render(16);
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  if(testDraw)
+  {
+    DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+    DALI_TEST_CHECK( textureTrace.FindMethod( "BindTexture" ) );
+    const std::vector<GLuint>& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+    DALI_TEST_CHECK( textures.size() > 0 );
+    if( textures.size() > 0 )
+    {
+      DALI_TEST_CHECK( textures[0] == 23 );
+    }
+  }
+  return imageActor;
+}
+
+
+void TestImageInside( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Image image = LoadImage( application, 23, width, height );
+
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+  imageActor.SetPosition(0.0f, 0.0f, 0.0f);
+
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  drawTrace.Reset();
+  imageActor.SetParentOrigin(ParentOrigin::TOP_LEFT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+
+  drawTrace.Reset();
+  imageActor.SetParentOrigin(ParentOrigin::TOP_RIGHT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+
+  drawTrace.Reset();
+  imageActor.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+
+  drawTrace.Reset();
+  imageActor.SetParentOrigin(ParentOrigin::BOTTOM_LEFT);
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+}
+
+
+bool RepositionActor(TestApplication& application, Actor actor, float x, float y, bool inside)
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  application.SendNotification();
+  application.Render(16);
+
+  bool found = drawTrace.FindMethod( "DrawArrays" );
+  return (inside && found) || (!inside && !found);
+}
+
+
+void RepositionActorWithAngle(TestApplication& application, Actor actor, float x, float y, float angle, bool inside)
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  actor.SetOrientation( Degree(angle), Vector3::ZAXIS );
+  application.SendNotification();
+  application.Render(16);
+  if( inside )
+  {
+    bool found = drawTrace.FindMethod( "DrawArrays" );
+    if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( found );
+  }
+  else
+  {
+    bool found = drawTrace.FindMethod( "DrawArrays" );
+    if( found ) tet_printf( "Drawn when not needed: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( ! found );
+  }
+}
+
+void RepositionActorOutside(TestApplication& application, Actor actor, float x, float y, bool drawn )
+{
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+
+  drawTrace.Reset();
+  actor.SetPosition( x, y, 0.0f);
+  application.SendNotification();
+  application.Render(16);
+  if( drawn )
+  {
+    bool found = drawTrace.FindMethod( "DrawArrays" );
+    if( ! found ) tet_printf( "Not drawn: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( found );
+  }
+  else
+  {
+    bool found = drawTrace.FindMethod( "DrawArrays" );
+    if( found ) tet_printf( "Drawn unnecessarily: Position:(%3.0f, %3.0f)\n", x, y );
+    DALI_TEST_CHECK( ! found );
+  }
+
+}
+
+void SphereTestImageAtBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  Image image = LoadImage(application, 23, width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  imageSize.z = 0.0f;
+  float radius = imageSize.Length() * 0.5f; // Radius of bounding box
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) := radius=%3.0f\n",
+             stageSize.x, stageSize.y, imageSize.x, imageSize.y, radius);
+
+  for( int i=0; i<=radius; i++ )
+  {
+    float x1 = -stageSize.x/2.0f - i;
+    float x2 =  stageSize.x/2.0f + i;
+    float y1 = -stageSize.y/2.0f - i;
+    float y2 =  stageSize.y/2.0f + i;
+
+    //tet_printf("Testing i=%d\n",i);
+
+    // Test paths marked with dots
+    //  + . . . . . .
+    //  .\_     ^
+    //  .  \_   | within radius
+    //  .    \  v
+    //  .     +-----
+    //  .     | Stage
+
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = ((stageSize.x+2*radius)/21.0f) * j;
+      float y = ((stageSize.y+2*radius)/21.0f) * j;
+
+      RepositionActor( application, imageActor, x1, y, true );
+      RepositionActor( application, imageActor, x2, y, true );
+      RepositionActor( application, imageActor, x, y1, true );
+      RepositionActor( application, imageActor, x, y2, true );
+    }
+  }
+}
+
+void OBBTestImageAtBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  Image image = LoadImage(application, 23, width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  imageSize.z = 0.0f;
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) \n",
+             stageSize.x, stageSize.y, imageSize.x, imageSize.y);
+
+  int successCount = 0;
+  int totalCount = 0;
+  for( int i=0; i<100; i++ )
+  {
+    float x1 = -stageSize.x/2.0f - imageSize.x*i/200.0f;
+    float x2 =  stageSize.x/2.0f + imageSize.x*i/200.0f;
+    float y1 = -stageSize.y/2.0f - imageSize.y*i/200.0f;
+    float y2 =  stageSize.y/2.0f + imageSize.y*i/200.0f;
+
+    //tet_printf("Testing i=%d\n",i);
+
+    // Test paths marked with dots
+    //  + . . . . . .
+    //  .\_     ^
+    //  .  \_   | within radius
+    //  .    \  v
+    //  .     +-----
+    //  .     | Stage
+
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = ((stageSize.x+imageSize.x/2.0f)/21.0f) * j;
+      float y = ((stageSize.y+imageSize.y/2.0f)/21.0f) * j;
+
+      if(RepositionActor( application, imageActor, x1, y, true )) successCount++;
+      if(RepositionActor( application, imageActor, x2, y, true )) successCount++;
+      if(RepositionActor( application, imageActor, x, y1, true )) successCount++;
+      if(RepositionActor( application, imageActor, x, y2, true )) successCount++;
+
+      totalCount += 4;
+    }
+  }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
+}
+
+
+void SphereTestImageOutsideBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  Image image = LoadImage( application, 23, width, height );
+
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  imageSize.z = 0.0f;
+  float radius = imageSize.Length() * 0.5f; // Radius of bounding box
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f) := radius=%3.0f\n",
+             stageSize.x, stageSize.y, imageSize.x, imageSize.y, radius);
+
+  for( int i=0; i<100; i++ )
+  {
+    // Try from 3 times
+    float x1 = -stageSize.x/2.0f - imageSize.x*i/200.0f;
+    float x2 =  stageSize.x/2.0f + imageSize.x*i/200.0f;
+    float y1 = -stageSize.y/2.0f - imageSize.y*i/200.0f;
+    float y2 =  stageSize.y/2.0f + imageSize.y*i/200.0f;
+
+
+    //tet_printf("Testing i=%d\n",i);
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area
+      float y = (stageSize.y/17.0f) * j;
+
+      RepositionActor( application, imageActor, x1, y, false );
+      RepositionActor( application, imageActor, x2, y, false );
+      RepositionActor( application, imageActor, x, y1, false );
+      RepositionActor( application, imageActor, x, y2, false );
+    }
+  }
+}
+
+void OBBTestImageOutsideBoundary( TestApplication& application, int width, int height )
+{
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  Image image = LoadImage( application, 23, width, height );
+
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  imageSize.z = 0.0f;
+  tet_printf("Testing Stage Size: (%3.0f, %3.0f) image size:(%3.0f, %3.0f)\n",
+             stageSize.x, stageSize.y, imageSize.x, imageSize.y);
+
+  int successCount=0;
+  int totalCount=0;
+
+  for( int i=0; i<=100; i++ )
+  {
+    float x1 = -stageSize.x/2.0f - imageSize.x * (1.5f + i/100.0f);
+    float x2 =  stageSize.x/2.0f + imageSize.x * (1.5f + i/100.0f);
+    float y1 = -stageSize.y/2.0f - imageSize.y * (1.5f + i/100.0f);
+    float y2 =  stageSize.y/2.0f + imageSize.y * (1.5f + i/100.0f);
+
+    for( int j=-10; j<=10; j++ )
+    {
+      float x = (stageSize.x/17.0f) * j; // use larger intervals to test more area
+      float y = (stageSize.y/17.0f) * j;
+
+      if(RepositionActor( application, imageActor, x1, y, false )) successCount++;
+      if(RepositionActor( application, imageActor, x2, y, false )) successCount++;
+      if(RepositionActor( application, imageActor, x, y1, false )) successCount++;
+      if(RepositionActor( application, imageActor, x, y2, false )) successCount++;
+      totalCount+=4;
+    }
+  }
+  DALI_TEST_EQUALS(successCount, totalCount, TEST_LOCATION);
+  tet_printf( "Test succeeded with %d passes out of %d tests\n", successCount, totalCount);
+}
+
+void TestPlaneOfImages(TestApplication& application, float z)
+{
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Vector2 imageSize = stageSize/3.0f;
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  // Create a grid of 9 x 9 actors; only the central 3x3 are in viewport
+
+  std::vector< Actor > actors;
+  for( int i = 0; i < NUM_ROWS*NUM_COLS; i++ )
+  {
+    GLuint textureId = TEXTURE_ID_OFFSET+i;
+    Image image = LoadImage( application, textureId, imageSize.x, imageSize.y );
+    ImageActor imageActor = CreateOnStageActor(application, image, imageSize.x, imageSize.y, false );
+    actors.push_back(imageActor);
+  }
+  application.SendNotification();
+  application.Render(16);
+
+  drawTrace.Reset();
+  textureTrace.Reset();
+  drawTrace.Enable(true);
+  textureTrace.Enable(true);
+  application.GetGlAbstraction().ClearBoundTextures();
+
+  for( int row=0; row<NUM_ROWS; row++)
+  {
+    for( int col=0; col<NUM_COLS; col++)
+    {
+      // col:    0   1   2  | 3   4   5 | 6   7   8
+      //
+      //        -4/3 -1 -2/3 -1/3  0 1/3 |2/3 1  4/3
+      // col*2 -5
+      //         0   2   4
+      // NUM_COLS = 9 NUM_COLS_PER_PANE = 3   (A pane is stage sized)
+      //
+      // NUM_COLS / NUM_COLS_PER_PANE => number of panes
+      // 3 per pane, splits into -1/3, 0, +1/3
+      // number of lh planes * number of cols per plane
+      // Center column maps to zero, index of center column = num_cols / 2 rounded down
+      // index - that  and divide by number of cols per pane.
+      // 0 1 2 3 4  5 6 7 8  9 10 11 12
+      float xOffset = (int)(col - (NUM_COLS/2));
+      float yOffset = (int)(row - (NUM_ROWS/2));
+      float x = stageSize.x*xOffset / (float)(NUM_COLS_PER_PANE);
+      float y = stageSize.y*yOffset / (float)(NUM_ROWS_PER_PANE);
+      actors[row*NUM_COLS+col].SetPosition( x, y, z );
+    }
+  }
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+
+  typedef std::vector<GLuint> TexVec;
+  const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+  DALI_TEST_CHECK( textures.size() >= NUM_ROWS_PER_PANE * NUM_COLS_PER_PANE );
+  if( textures.size() > 0 )
+  {
+    int foundCount=0;
+    int expectedCount = 0;
+    for(unsigned int row=0; row<NUM_ROWS; row++)
+    {
+      for(unsigned int col=0; col<NUM_ROWS; col++)
+      {
+        Vector3 pos = actors[row*NUM_COLS+col].GetCurrentPosition();
+        if( -stageSize.x/2.0f <= pos.x && pos.x <= stageSize.x/2.0f &&
+            -stageSize.y/2.0f <= pos.y && pos.y <= stageSize.y/2.0f )
+        {
+          expectedCount++;
+          GLuint texId = (row*NUM_COLS+col)+TEXTURE_ID_OFFSET;
+
+          for(TexVec::const_iterator iter = textures.begin(); iter != textures.end(); iter++)
+          {
+            if(*iter == texId)
+            {
+              foundCount++;
+            }
+          }
+        }
+      }
+    }
+    tet_printf("Number of expected draws: %u\n", expectedCount);
+    DALI_TEST_EQUALS(foundCount, expectedCount, TEST_LOCATION);
+  }
+  int numDrawCalls = drawTrace.CountMethod("DrawArrays");
+  DALI_TEST_CHECK( numDrawCalls >= NUM_ROWS_PER_PANE * NUM_COLS_PER_PANE );
+
+  tet_printf("Number of bound textures: %u\n", textures.size());
+  tet_printf("Number of draw calls: %d\n", numDrawCalls);
+}
+
+} // namespace
+
+int UtcDaliImageCulling_Inside01(void)
+{
+  tet_infoline( "Testing that 80x80 image positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestImageInside(application, 80, 80);
+
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Inside02(void)
+{
+  tet_infoline( "Testing that 120x40 image positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestImageInside(application, 120, 40);
+
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Inside03(void)
+{
+  tet_infoline( "Testing that 40x120 image positioned inside the stage is drawn\n");
+
+  TestApplication application;
+
+  TestImageInside(application, 40, 120);
+
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Inside04(void)
+{
+  tet_infoline( "Testing that 500x2 image positioned inside the stage is drawn\n");
+  TestApplication application;
+  TestImageInside(application, 500, 2);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Inside05(void)
+{
+  tet_infoline( "Testing that 2x500 image positioned inside the stage is drawn\n");
+  TestApplication application;
+  TestImageInside(application, 2, 500);
+  END_TEST;
+}
+
+
+int UtcDaliImageCulling_WithinBoundary01(void)
+{
+  tet_infoline("Test that 80x80 image positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestImageAtBoundary( application, 80, 80);
+  END_TEST;
+}
+int UtcDaliImageCulling_WithinBoundary02(void)
+{
+  tet_infoline("Test that 120x40 image positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestImageAtBoundary( application, 120, 40 );
+  END_TEST;
+}
+int UtcDaliImageCulling_WithinBoundary03(void)
+{
+  tet_infoline("Test that 40x120 image positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestImageAtBoundary( application, 40, 120);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_WithinBoundary04(void)
+{
+  tet_infoline("Test that 500x2 images positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestImageAtBoundary( application, 500, 2 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_WithinBoundary05(void)
+{
+  tet_infoline("Test that 2x500 images positioned outside the stage but with bounding box intersecting the stage is drawn\n");
+
+  TestApplication application;
+  OBBTestImageAtBoundary( application, 2, 500 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideBoundary01(void)
+{
+  tet_infoline("Test that 80x80 image positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestImageOutsideBoundary( application, 80, 80 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideBoundary02(void)
+{
+  tet_infoline("Test that 120x40 image positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestImageOutsideBoundary( application, 120, 40 );
+  END_TEST;
+}
+int UtcDaliImageCulling_OutsideBoundary03(void)
+{
+  tet_infoline("Test that 40x120 image positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestImageOutsideBoundary( application, 40, 120 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideBoundary04(void)
+{
+  tet_infoline("Test that 500x2 image positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestImageOutsideBoundary( application, 500, 2 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideBoundary05(void)
+{
+  tet_infoline("Test that 2x500 image positioned outside the stage by more than 2 times\n"
+               "the radius of the bounding circle  is not drawn\n");
+
+  TestApplication application;
+  OBBTestImageOutsideBoundary( application, 2, 500 );
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideIntersect01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n"
+               "outside the stage but intersecting it are still drawn");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*0.2f;
+  Image image = LoadImage( application, 23,  width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  RepositionActor( application, imageActor, stageSize.x*1.2f, 0.0f, true);
+  RepositionActor( application, imageActor, stageSize.x*1.2f, -stageSize.y*0.55f, true);
+  RepositionActor( application, imageActor, stageSize.x*1.2f, stageSize.y*0.55f, true);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideIntersect02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that actors positioned outside the stage with bounding boxes also\n"
+               "outside the stage that cross planes are not drawn");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*0.2f;
+  Image image = LoadImage( application, 23,  width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  RepositionActor( application, imageActor,  stageSize.x*10.0f,  stageSize.y*0.5f, false);
+  RepositionActor( application, imageActor, -stageSize.x*10.0f,  stageSize.y*0.5f, false);
+  RepositionActor( application, imageActor,  stageSize.x*10.0f, -stageSize.y*0.5f, false);
+  RepositionActor( application, imageActor, -stageSize.x*10.0f, -stageSize.y*0.5f, false);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideIntersect03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that image actor larger than the stage, positioned outside the stage \n"
+               "with bounding boxes also outside the stage but intersecting it is still drawn\n");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // Try an actor bigger than the stage, with center outside stage
+  float width = stageSize.x*5.0f;
+  float height = stageSize.y*5.0f;
+  Image image = LoadImage( application, 23,  width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  RepositionActor( application, imageActor, stageSize.x*1.2f, 0.0f, true);
+  RepositionActor( application, imageActor, stageSize.x*1.2f, -stageSize.y*1.1f, true);
+  RepositionActor( application, imageActor, stageSize.x*1.2f, stageSize.y*1.1f, true);
+
+  END_TEST;
+}
+
+int UtcDaliImageCulling_OutsideIntersect04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test that image actors positioned outside the stage, with bounding boxes\n"
+               "also outside the stage but intersecting it, and angled at 45 degrees to\n"
+               "the corners are still drawn\n");
+
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // Test image at 45 degrees outside corners of stage
+  float width = 400.0f;
+  float height = 200.0f;
+  Image image = LoadImage( application, 23,  width, height);
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+
+  RepositionActorWithAngle( application, imageActor, -stageSize.x*0.55f, -stageSize.y*0.55, 135.0f, true);
+  RepositionActorWithAngle( application, imageActor, -stageSize.x*0.55f,  stageSize.y*0.55, 225.0f, true);
+  RepositionActorWithAngle( application, imageActor,  stageSize.x*0.55f, -stageSize.y*0.55,  45.0f, true);
+  RepositionActorWithAngle( application, imageActor,  stageSize.x*0.55f,  stageSize.y*0.55, 315.0f, true);
+
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Plane01(void)
+{
+  tet_infoline("Test that a set of image actors with different images are drawn appropriately");
+
+  TestApplication application;
+
+  TestPlaneOfImages(application, 0.0f);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Plane02(void)
+{
+  tet_infoline("Test that a set of image actors with different images are drawn appropriately");
+
+  TestApplication application;
+
+  TestPlaneOfImages(application, 100.0f);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Plane03(void)
+{
+  tet_infoline("Test that a set of image actors with different images are drawn appropriately");
+
+  TestApplication application;
+
+  TestPlaneOfImages(application, -100.0f);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Plane04(void)
+{
+  tet_infoline("Test that a set of image actors with different images are drawn appropriately");
+
+  TestApplication application;
+
+  TestPlaneOfImages(application, -200.0f);
+  END_TEST;
+}
+
+int UtcDaliImageCulling_Disable(void)
+{
+  tet_infoline("Test that culling can be disabled");
+
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  float width=80;
+  float height=80;
+  Image image = LoadImage( application, 23, width, height );
+
+  ImageActor imageActor = CreateOnStageActor(application, image, width, height, true);
+  Vector3 imageSize = imageActor.GetCurrentSize();
+  DALI_TEST_EQUALS( imageSize, Vector3(width, height, std::min(width, height)), TEST_LOCATION);
+
+  imageSize.z = 0.0f;
+
+  tet_infoline("Setting cull mode to false\n");
+  Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(false);
+
+  float x1 = -stageSize.x - imageSize.x;
+  float x2 =  stageSize.x + imageSize.x;
+  float y1 = -stageSize.y - imageSize.y;
+  float y2 =  stageSize.y + imageSize.y;
+
+  // Positioning actors outside stage, with no culling, they should still be drawn.
+  RepositionActorOutside( application, imageActor, x1, y1, true );
+  RepositionActorOutside( application, imageActor, x2, y1, true );
+  RepositionActorOutside( application, imageActor, x1, y2, true );
+  RepositionActorOutside( application, imageActor, x2, y2, true );
+
+  tet_infoline("Setting cull mode to true\n");
+  Stage::GetCurrent().GetRenderTaskList().GetTask(0).SetCullMode(true);
+
+  RepositionActorOutside( application, imageActor, x1, y1, false );
+  RepositionActorOutside( application, imageActor, x2, y1, false );
+  RepositionActorOutside( application, imageActor, x1, y2, false );
+  RepositionActorOutside( application, imageActor, x2, y2, false );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ImageFactory.cpp
new file mode 100644 (file)
index 0000000..d0e63ad
--- /dev/null
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/common/image-attributes.h>
+
+using namespace Dali;
+
+using Internal::ResourceTicketPtr;
+using Internal::ImageFactory;
+using Internal::ImageFactoryCache::RequestPtr;
+using Internal::ImageAttributes;
+
+namespace
+{
+
+static const char* gTestImageFilename = "icon_wrt.png";
+
+static void EmulateImageLoaded( TestApplication& application, unsigned int width, unsigned int height )
+{
+  // emulate load success
+  Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource( bitmap );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, width, height, width, height );
+  if( request )
+  {
+    application.GetPlatform().SetResourceLoaded( request->GetId(), request->GetType()->id, resource );
+  }
+
+  application.SendNotification();
+  application.Render();
+
+  application.SendNotification();
+  application.Render();
+}
+
+} //anonymous namespace
+
+
+// High-level test for image factory request cache
+int UtcDaliImageFactoryUseCachedRequest01(void)
+{
+  TestApplication application;
+
+  tet_infoline( "UtcDaliImageFactoryCachedRequest01 - Request same image more than once" );
+
+  Image image = ResourceImage::New( gTestImageFilename );
+
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  Image image2 = ResourceImage::New( gTestImageFilename );
+
+  application.SendNotification();
+  application.Render();
+
+  // check resource is not loaded twice
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  Image image3 = ResourceImage::New( gTestImageFilename );
+
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  END_TEST;
+}
+
+// High-level test for image factory request cache
+int UtcDaliImageFactoryUseCachedRequest02(void)
+{
+  TestApplication application;
+
+  // testing resource deletion when taken off stage
+  tet_infoline( "UtcDaliImageFactoryCachedRequest02 - Discard previously requested resource" );
+
+  Image image = ResourceImage::New( gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED );
+  ImageActor actor = ImageActor::New( image );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  // Add actor to stage
+  Stage::GetCurrent().Add( actor );
+
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  // Release the resource, request is still cached
+  Stage::GetCurrent().Remove( actor );
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  // Should find stale request in cache, so load image from filesystem
+  Image image2 = ResourceImage::New( gTestImageFilename );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  // Resource is reloaded
+  Image image3 = ResourceImage::New( gTestImageFilename );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  END_TEST;
+}
+
+// Low-level test for image factory request cache
+int UtcDaliImageFactoryUseCachedRequest03(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCachedRequest03 - Request same image more than once - Request Ids" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+  DALI_TEST_EQUALS( req, req2, TEST_LOCATION );
+  DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION );
+
+  req2 = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket3 = imageFactory.Load( *req2.Get() );
+  DALI_TEST_EQUALS( req, req2, TEST_LOCATION );
+  DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION );
+
+  // request differs in scaled size - not default size
+  ImageAttributes attr = ImageAttributes::New( 80, 160);
+  req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket4 = imageFactory.Load( *req2.Get() );
+  DALI_TEST_CHECK( req != req2 );
+  END_TEST;
+}
+
+// Low-level test for image factory request cache
+int UtcDaliImageFactoryUseCachedRequest04(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCachedRequest04 - Request same image with different Image objects - Request Ids" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  ImageAttributes attr = ImageAttributes::New( 80, 160 );
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+
+  ImageAttributes attr2 = ImageAttributes::New( 80, 160 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr2 );
+  DALI_TEST_EQUALS( req, req2, TEST_LOCATION );
+  END_TEST;
+}
+
+// Different requests, compatible resource
+int UtcDaliImageFactoryCompatibleResource01(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCompatibleResource01 - Two requests mapping to same resource" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  // request with default attributes ( size is 0,0 )
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  // Request a second load using exact-match image size:
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( 80, 80 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+
+  DALI_TEST_CHECK( req != req2 ); // different requests
+  DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource
+  END_TEST;
+}
+
+// Different requests, compatible resource
+int UtcDaliImageFactoryCompatibleResource02(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCompatibleResource02 - Two requests mapping to same resource." );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize( 2048.0f, 2048.0f );
+  application.GetPlatform().SetClosestImageSize( testSize );
+
+  // request with default attributes ( size is 0,0 )
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, testSize.x, testSize.y );
+
+  // Request slightly bigger size than actual image.
+  // This will load the same resource as the ImageFactory cache uses a small fudge factor in matching.
+  // See UtcDaliImageFactoryReload06
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( testSize.x + 1, testSize.y + 1 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+
+  DALI_TEST_CHECK( req != req2 ); // different requests
+  DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource
+  END_TEST;
+}
+
+// Different requests, incompatible resource, so two loads result:
+int UtcDaliImageFactoryInCompatibleResource(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCompatibleResource02 - Two requests mapping to same resource." );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(2048.0f, 2048.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  // request with default attributes ( size is 0,0 )
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, testSize.x, testSize.y );
+
+  // Request substantially different size than actual image.
+  // This will issue a second resource load as difference in sizes is greater than
+  // the small fudge factor used in the ImageFactory cache.
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( testSize.x - 16, testSize.y - 16 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+
+  DALI_TEST_CHECK( req != req2 ); // different requests
+  DALI_TEST_CHECK( ticket->GetId() != ticket2->GetId() ); // differnet resources
+  END_TEST;
+}
+
+// Different requests, compatible resource
+int UtcDaliImageFactoryCompatibleResource03(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryCompatibleResource03 - Two requests mapping to same resource" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  // this time use defined attributes, nut just NULL
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( 120, 120 );
+
+  // request with default attributes ( size is 0,0 )
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  ImageAttributes attr2 = ImageAttributes::New();
+  attr2.SetSize( 80, 80 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr2 );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+
+  DALI_TEST_CHECK( req != req2 ); // different requests
+  DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource
+  END_TEST;
+}
+
+// Test for reloading image
+int UtcDaliImageFactoryReload01(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryReload01 - Reload unchanged image" );
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() );
+  DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION );
+
+  ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() );
+  DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION );
+  END_TEST;
+}
+
+// Testing file system access when reloading image
+int UtcDaliImageFactoryReload02(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryReload02 - Reload unchanged image" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION );
+  // resource is still loading, do not issue another request
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION );
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  ticket3 = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  END_TEST;
+}
+
+// Test for reloading changed image
+int UtcDaliImageFactoryReload03(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryReload03 - Reload changed image" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize( 80.0f, 80.0f );
+  application.GetPlatform().SetClosestImageSize( testSize );
+
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  Vector2 newSize( 192.0f, 192.0f );
+  application.GetPlatform().SetClosestImageSize( newSize );
+
+  // Image file changed size, new resource request should be issued
+  ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() );
+  DALI_TEST_CHECK( ticket != ticket2 );
+
+  ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() );
+  DALI_TEST_EQUALS( ticket2, ticket3, TEST_LOCATION );
+  END_TEST;
+}
+
+// Testing file system access when reloading image
+int UtcDaliImageFactoryReload04(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryReload04 - Reload unchanged image" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  ResourceTicketPtr ticket2 = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( ticket, ticket2, TEST_LOCATION );
+  // resource is still loading, do not issue another request
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  ResourceTicketPtr ticket3 = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // size didn't change, using same ticket
+  DALI_TEST_EQUALS( ticket, ticket3, TEST_LOCATION );
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  application.GetPlatform().ResetTrace();
+
+  // still loading
+  ticket3 = imageFactory.Reload( *req.Get() );
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  END_TEST;
+}
+
+// Testing OnDemand + Reload
+// Reload should have no effect if OnDemand Image is not loaded yet, as stated in the API documentation
+int UtcDaliImageFactoryReload05(void)
+{
+  TestApplication application;
+
+  tet_infoline( "UtcDaliImageFactoryReload05 - Reload OnDemand image" );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(80.0f, 80.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+
+  RequestPtr req;
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( 80, 80 );
+
+  // this happens first when loading Image OnDemand
+  req = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+
+  application.SendNotification();
+  application.Render();
+
+  ResourceTicketPtr ticket = imageFactory.Reload( *req.Get() );
+
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  DALI_TEST_CHECK( !ticket );
+
+  // this happens when Image is put on stage
+  ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  DALI_TEST_CHECK( ticket );
+  application.GetPlatform().ResetTrace();
+
+  ticket = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // still loading, no new request
+  DALI_TEST_CHECK( !application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+
+  // emulate load success
+  EmulateImageLoaded( application, 80, 80 );
+
+  ticket = imageFactory.Reload( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+
+  application.SendNotification();
+  application.Render();
+
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled( TestPlatformAbstraction::LoadResourceFunc ) );
+  END_TEST;
+}
+
+// Initally two different requests map to same resource.
+// After overwriting the file, they load different image resources.
+int UtcDaliImageFactoryReload06(void)
+{
+  TestApplication application;
+  tet_infoline( "UtcDaliImageFactoryReload06 - Two requests first mapping to same resource, then different resources." );
+
+  ImageFactory& imageFactory  = Internal::ThreadLocalStorage::Get().GetImageFactory();
+
+  Vector2 testSize(2048.0f, 2048.0f);
+    application.GetPlatform().SetClosestImageSize( testSize );
+
+  // request with default attributes ( size is 0,0 )
+  RequestPtr req = imageFactory.RegisterRequest( gTestImageFilename, NULL );
+  ResourceTicketPtr ticket = imageFactory.Load( *req.Get() );
+
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // emulate load success
+  EmulateImageLoaded( application, testSize.x, testSize.y );
+
+  // Request bigger size than actual image.
+  // This will load the same resource.
+  // However if image size changes later on to eg. 512*512 (file is overwritten),
+  // reissuing these two requests will load different resources.
+  ImageAttributes attr = ImageAttributes::New();
+  attr.SetSize( testSize.x + 1, testSize.y + 1 );
+  RequestPtr req2 = imageFactory.RegisterRequest( gTestImageFilename, &attr );
+  ResourceTicketPtr ticket2 = imageFactory.Load( *req2.Get() );
+
+  DALI_TEST_CHECK( req != req2 ); // different requests
+  DALI_TEST_EQUALS( ticket->GetId(), ticket2->GetId(), TEST_LOCATION ); // same resource
+
+  Vector2 newSize(512.0f, 512.0f);
+  application.GetPlatform().SetClosestImageSize(newSize);
+
+  // reload fixed size (192,192) request
+  ticket2 = imageFactory.Reload( *req2.Get() );
+
+  // emulate load success
+  // note: this is the only way to emulate what size is loaded by platform abstraction
+  EmulateImageLoaded( application, testSize.x + 1, testSize.y + 1 );
+
+  // reload default size request
+  ticket = imageFactory.Reload( *req.Get() );
+
+  DALI_TEST_CHECK( ticket->GetId() != ticket2->GetId() ); // different resources
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-MemoryPoolObjectAllocator.cpp
new file mode 100644 (file)
index 0000000..e254b68
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+// Internal headers are allowed here
+
+#include <dali/internal/common/memory-pool-object-allocator.h>
+
+using namespace Dali;
+
+void utc_dali_internal_memorypoolobjectallocator_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_memorypoolobjectallocator_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+struct MemoryPoolObjectAllocatorTestObjectTracking
+{
+  int testObjectDestructed;
+  int testObjectMethod;
+  int testObjectDataAccess;
+
+  MemoryPoolObjectAllocatorTestObjectTracking()
+  : testObjectDestructed( 0 ),
+    testObjectMethod( 0 ),
+    testObjectDataAccess( 0 )
+  {
+  }
+};
+
+class MemoryPoolObjectAllocatorTestObject
+{
+public:
+
+  MemoryPoolObjectAllocatorTestObject()
+  : mData1( 0 ),
+    mData2( false ),
+    mTracking( NULL )
+  {
+  }
+
+  ~MemoryPoolObjectAllocatorTestObject()
+  {
+    if( mTracking )
+    {
+      mTracking->testObjectDestructed++;
+    }
+  }
+
+  void Method()
+  {
+    if( mTracking )
+    {
+      mTracking->testObjectMethod++;
+    }
+  }
+
+  void DataAccess()
+  {
+    mData1++;
+    mData2 = true;
+
+    if( mTracking )
+    {
+      mTracking->testObjectDataAccess++;
+    }
+  }
+
+  void SetTracking( MemoryPoolObjectAllocatorTestObjectTracking* tracking )
+  {
+    mTracking = tracking;
+  }
+
+private:
+
+  int mData1;
+  bool mData2;
+
+  MemoryPoolObjectAllocatorTestObjectTracking* mTracking;
+};
+
+int UtcDaliMemoryPoolObjectAllocatorObjectAllocation(void)
+{
+
+  Internal::MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator;
+
+  // Allocate an object
+  MemoryPoolObjectAllocatorTestObject* testObject1 = allocator.Allocate();
+  DALI_TEST_CHECK( testObject1 );
+
+  MemoryPoolObjectAllocatorTestObjectTracking tracking1;
+  testObject1->SetTracking( &tracking1 );
+
+  testObject1->Method();
+  DALI_TEST_EQUALS( tracking1.testObjectMethod, 1, TEST_LOCATION );
+
+  testObject1->DataAccess();
+  DALI_TEST_EQUALS( tracking1.testObjectDataAccess, 1, TEST_LOCATION );
+
+  allocator.Free( testObject1 );
+  DALI_TEST_EQUALS( tracking1.testObjectDestructed, 1, TEST_LOCATION );
+
+  // Reset and allocate another object
+  allocator.ResetMemoryPool();
+
+  MemoryPoolObjectAllocatorTestObject* testObject2 = allocator.Allocate();
+  DALI_TEST_CHECK( testObject2 );
+
+  MemoryPoolObjectAllocatorTestObjectTracking tracking2;
+  testObject2->SetTracking( &tracking2 );
+
+  testObject2->Method();
+  DALI_TEST_EQUALS( tracking2.testObjectMethod, 1, TEST_LOCATION );
+
+  testObject2->DataAccess();
+  DALI_TEST_EQUALS( tracking2.testObjectDataAccess, 1, TEST_LOCATION );
+
+  allocator.Free( testObject2 );
+  DALI_TEST_EQUALS( tracking2.testObjectDestructed, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMemoryPoolObjectAllocatorObjectRawAllocation(void)
+{
+  Internal::MemoryPoolObjectAllocator< MemoryPoolObjectAllocatorTestObject > allocator;
+
+  MemoryPoolObjectAllocatorTestObject* testObject = new ( allocator.AllocateRaw() ) MemoryPoolObjectAllocatorTestObject();
+  DALI_TEST_CHECK( testObject );
+
+  MemoryPoolObjectAllocatorTestObjectTracking tracking;
+  testObject->SetTracking( &tracking );
+
+  testObject->Method();
+  DALI_TEST_EQUALS( tracking.testObjectMethod, 1, TEST_LOCATION );
+
+  testObject->DataAccess();
+  DALI_TEST_EQUALS( tracking.testObjectDataAccess, 1, TEST_LOCATION );
+
+  allocator.Free( testObject );
+  DALI_TEST_EQUALS( tracking.testObjectDestructed, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliMemoryPoolObjectAllocatorObjectAllocationPOD(void)
+{
+  Internal::MemoryPoolObjectAllocator< bool > allocator;
+
+  bool* testObject1 = allocator.Allocate();
+  DALI_TEST_CHECK( testObject1 );
+
+  allocator.Free( testObject1 );
+
+  allocator.ResetMemoryPool();
+
+  bool* testObject2 = allocator.Allocate();
+  DALI_TEST_CHECK( testObject2 );
+
+  allocator.Free( testObject2 );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp b/automated-tests/src/dali-internal/utc-Dali-Internal-ResourceClient.cpp
new file mode 100644 (file)
index 0000000..71855fc
--- /dev/null
@@ -0,0 +1,1022 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+
+// Internal headers are allowed here
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/update/resources/bitmap-metadata.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/resources/image-ticket.h>
+#include <dali/internal/event/resources/resource-ticket-observer.h>
+#include <dali/internal/event/images/resource-image-impl.h>
+#include <dali/integration-api/resource-cache.h>
+#include <dali/internal/render/gl-resources/texture-declarations.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/common/image-attributes.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+namespace
+{
+
+class TestTicketObserver : public Internal::ResourceTicketObserver
+{
+public:
+  TestTicketObserver()
+  : mLoadingFailedCalled(0), mLoadingSucceededCalled(0),
+    mUploadedCount(0)
+  {}
+
+  int LoadFailedCalled() {
+    tet_printf("TicketObserver: LoadingFailed() called %d times", mLoadingFailedCalled);
+    return mLoadingFailedCalled;
+  }
+  int LoadSucceededCalled() {
+    tet_printf("TicketObserver: LoadingSucceeded()  called %d times", mLoadingSucceededCalled);
+    return mLoadingSucceededCalled;
+  }
+  int  UploadCalled() {
+    tet_printf("TicketObserver: Uploaded() called %d times", mUploadedCount);
+    return mUploadedCount;
+  }
+  void Reset() {
+    mLoadingFailedCalled    = 0;
+    mLoadingSucceededCalled = 0;
+    mUploadedCount           = 0;
+  }
+
+public: // From ResourceTicketObserver
+  virtual void ResourceLoadingFailed(const Internal::ResourceTicket& ticket) {mLoadingFailedCalled++;}
+  virtual void ResourceLoadingSucceeded(const Internal::ResourceTicket& ticket) {mLoadingSucceededCalled++;}
+  virtual void ResourceUploaded(const Internal::ResourceTicket& ticket) {mUploadedCount++;}
+
+private:
+  int mLoadingFailedCalled;
+  int mLoadingSucceededCalled;
+  int mUploadedCount;
+};
+
+class TestTicketLifetimeObserver : public Internal::ResourceTicketLifetimeObserver
+{
+public:
+  TestTicketLifetimeObserver() : resourceTicketDiscarded(false) {}
+
+  virtual void ResourceTicketDiscarded( const Internal::ResourceTicket& ticket )
+  { resourceTicketDiscarded = true; }
+
+  void Reset() { resourceTicketDiscarded = false; }
+  bool resourceTicketDiscarded;
+};
+
+static TestTicketObserver testTicketObserver;
+static TestTicketLifetimeObserver testTicketLifetimeObserver;
+
+
+Internal::ImagePtr LoadImage(TestApplication& application, char* name)
+{
+  Internal::ResourceImagePtr image = Internal::ResourceImage::New( name, Internal::ImageAttributes::DEFAULT_ATTRIBUTES );
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80,80,80,80 );
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  req=NULL;
+  application.GetPlatform().ResetTrace();
+  return image;
+}
+
+
+Internal::ResourceTicketPtr CheckLoadBitmap(TestApplication& application, const char* name, int w, int h)
+{
+  Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, name );
+  ticket->AddObserver(testTicketObserver);
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  Integration::ResourceRequest*   req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, w, h, w, h );
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingSucceeded );
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  req=NULL;
+  application.GetPlatform().ResetTrace();
+
+  return ticket;
+}
+
+} //anonymous namespace
+
+
+void utc_dali_internal_resource_client_startup()
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_internal_resource_client_cleanup()
+{
+  test_return_value = TET_PASS;
+}
+
+// Load a bitmap resource successfully, then discard it's ticket
+int UtcDaliInternalRequestResourceBitmapRequests01(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Testing bitmap requests");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceId id(0);
+
+  testTicketObserver.Reset();
+
+  {
+    Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" );
+    ticket->AddObserver(testTicketObserver);
+
+    // Update thread will request the bitmap resource:
+    // Sets application.GetPlatform().mRequest
+    application.SendNotification(); // Run flush update queue
+    application.Render(1);          // Process update messages
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+
+    application.SendNotification(); // Send any event messages
+    DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 );
+    DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+    DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoading );
+
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    DALI_TEST_CHECK( imageTicket );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Create a resource
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+    bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
+    Integration::ResourcePointer resourcePtr(bitmap); // reference it
+
+    // Set up platform abstraction to load it
+    id=req->GetId();
+    application.GetPlatform().SetResourceLoaded( id, Integration::ResourceBitmap, resourcePtr );
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(req->GetId()) );
+
+    // load the cache, which will immediately have the loaded resource
+    application.Render(0);
+
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(req->GetId()) );
+    Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(req->GetId());
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 80 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 80 );
+
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Trigger the event thread to process notify messages. Should then trigger the signals
+    // in the ticket observer
+    application.SendNotification();
+
+    DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingSucceeded );
+    DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+
+    // Check that the image ticket was updated with the image attributes
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+  } // Discard ticket
+
+  application.SendNotification(); // Flush update queue (with ticket discarded message
+  application.Render(1);          // Process update messages
+  application.SendNotification(); // Send event notifications
+  application.Render(1);          // Process update messages
+
+  // Resource should have been discarded.
+  DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) );
+  DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+  DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS(testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+  END_TEST;
+}
+
+// Starting Loading a bitmap resource, then discard it's ticket before loading complete.
+int UtcDaliInternalRequestResourceBitmapRequests02(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Testing bitmap request ticket discard before load complete");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceId id(0);
+
+  testTicketObserver.Reset();
+
+  {
+    Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" );
+    ticket->AddObserver(testTicketObserver);
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    DALI_TEST_CHECK( imageTicket );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Update thread will request the bitmap resource:
+    // Sets application.GetPlatform().mRequest
+    application.SendNotification(); // Run flush update queue
+    application.Render(1);
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    id=req->GetId();
+
+    application.SendNotification(); // Should produce no messages
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+    DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoading );
+
+  } // Discard ticket
+
+  // Ensure ticket discarded message is sent to update thread
+  application.SendNotification(); // Flush update queue
+  application.Render(0);          // Process update messages
+
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) );
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+
+  DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+  // Trigger the event thread to process notify messages. Should then trigger the signals
+  // in the ticket observer
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(testTicketObserver.LoadSucceededCalled(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS(testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+  END_TEST;
+}
+
+// start loading a bitmap resource that doesn't exist, then discard it's ticket after failure
+int UtcDaliInternalRequestResourceBitmapRequests03(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Load bitmap that doesn't exist, followed by ticket discard. Expect LoadingFailed");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceId id(0);
+
+  testTicketObserver.Reset();
+  { // Scope lifetime of ticket
+    Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" );
+    ticket->AddObserver(testTicketObserver);
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    DALI_TEST_CHECK( imageTicket );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Update thread will request the bitmap resource:
+    // Sets application.GetPlatform().mRequest
+    application.SendNotification(); // Run flush update queue
+    application.Render(1);          // process update messages
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    id=req->GetId();
+    application.SendNotification(); // Should produce no messages
+    DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 );
+    DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+    application.GetPlatform().SetResourceLoadFailed(id, Integration::FailureFileNotFound );
+
+    application.Render(0); // Get failed result
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+    application.SendNotification(); // send failed
+    DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() != 0 );
+    DALI_TEST_CHECK( ticket->GetLoadingState() == ResourceLoadingFailed );
+
+    DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+  } // Discard ticket
+
+  application.Render(0); // Send DiscardTicket
+  application.SendNotification();
+
+  DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+  END_TEST;
+}
+
+
+
+// Load a bitmap resource successfully, then reload it
+int UtcDaliInternalRequestReloadBitmapRequests01(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Testing bitmap reload after successful load");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+
+  Internal::ResourceId id(0);
+  testTicketObserver.Reset();
+
+  {
+    Internal::ResourceTicketPtr ticket = CheckLoadBitmap( application, "image.png", 80, 80 );
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    id = ticket->GetId();
+
+    // Reset call statistics - test that resource is reloaded
+    application.GetPlatform().ResetTrace();
+
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    resourceClient.ReloadResource( ticket->GetId() );
+
+    DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    application.SendNotification(); // Flush update messages
+    application.Render(0);  // Process update messages
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    application.SendNotification(); // Process event messages
+
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoading, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+
+    // Create a new resource - the image size could have changed in the meantime
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+    bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 );
+    Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
+    DALI_TEST_CHECK( req->GetId() == ticket->GetId() );
+    application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr2);
+
+    application.Render(0);  // Process update messages / UpdateCache
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id));
+    Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id);
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 120 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 120 );
+
+    // Ticket can't have been updated yet - it should still have old values
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+    application.SendNotification(); // Process event messages
+    application.Render(0);          // Process update messages / UpdateCache
+    application.SendNotification(); // Process event messages
+
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 120, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 120, TEST_LOCATION );
+
+  } // Discard ticket
+
+  application.SendNotification(); // Flush update queue (with ticket discarded message
+  application.Render(1);          // Process update messages
+  application.SendNotification(); // Send event notifications
+  application.Render(1);          // Process update messages
+
+  // Resource should have been discarded.
+  DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::CancelLoadFunc ) );
+  DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+  DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliInternalRequestReloadBitmapRequests02(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Testing bitmap reload during first load");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceId id(0);
+
+  testTicketObserver.Reset();
+
+  {
+    Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+    Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" );
+    ticket->AddObserver(testTicketObserver);
+
+    // Update thread will request the bitmap resource:
+    // Sets application.GetPlatform().mRequest
+    application.SendNotification(); // Run flush update queue
+    application.Render(1);          // Process update messages
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+
+    application.SendNotification(); // Send any event messages
+    DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 );
+    DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    DALI_TEST_CHECK( imageTicket );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    resourceClient.ReloadResource( ticket->GetId() );
+    /************************************************************
+     * Expected result - current load completes as usual, no reload requested
+     ************************************************************/
+
+    application.SendNotification(); // Flush update methods
+
+    // Reset call statistics - test that resource is not reloaded
+    application.GetPlatform().ResetTrace();
+
+    application.Render(0); // Process reload message (nothing for UpdateCache yet)
+
+    DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+    // Create a resource
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+    bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
+    Integration::ResourcePointer resourcePtr(bitmap); // reference it
+
+    // Set up platform abstraction to load it
+    id=req->GetId();
+
+    application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr);
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+    application.GetPlatform().ResetTrace();
+    // load the cache, which will immediately have the loaded resource
+    application.Render(0);
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id));
+    Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id);
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 80 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 80 );
+
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Trigger the event thread to process notify messages. Should then trigger the signals
+    // in the ticket observer
+    application.SendNotification();
+
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+
+    // Check that the image ticket was updated with the image attributes
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+    DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+
+    application.SendNotification(); // Flush update messages
+    application.Render(0);  // Process update messages
+
+    // There should be no reload
+    DALI_TEST_CHECK( ! application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    application.SendNotification(); // Process event messages
+
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.LoadFailedCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id));
+    bitmapData = resourceManager.GetBitmapMetadata(id);
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 80 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 80 );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+  } // Discard ticket
+  END_TEST;
+}
+
+
+int UtcDaliInternalRequestReloadBitmapRequests03(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  tet_infoline("Testing bitmap reload at end of first load");
+
+  Internal::ResourceManager& resourceManager = Internal::ThreadLocalStorage::Get().GetResourceManager();
+  Integration::BitmapResourceType bitmapRequest;
+  Internal::ResourceId id(0);
+
+  testTicketObserver.Reset();
+
+  {
+    Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+    Internal::ResourceTicketPtr ticket = resourceClient.RequestResource( bitmapRequest, "image.png" );
+    ticket->AddObserver(testTicketObserver);
+
+    // Update thread will request the bitmap resource:
+    // Sets application.GetPlatform().mRequest
+    application.SendNotification(); // Run flush update queue
+    application.Render(1);          // Process update messages
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+
+    application.SendNotification(); // Send any event messages
+    DALI_TEST_CHECK( testTicketObserver.LoadFailedCalled() == 0 );
+    DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+
+    Internal::ImageTicketPtr imageTicket(dynamic_cast<Internal::ImageTicket*>(ticket.Get()));
+    DALI_TEST_CHECK( imageTicket );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+
+    /************************************************************
+     * FUNCTION UNDER TEST
+     ***********************************************************/
+    resourceClient.ReloadResource( ticket->GetId() );
+    /************************************************************
+     * Expected result - current load completes as usual, no reload requested
+     ************************************************************/
+
+    application.SendNotification(); // Flush update methods
+
+    // Reset call statistics - test that resource is not reloaded
+    application.GetPlatform().ResetTrace();
+
+    // Create a resource
+    Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+    Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+    bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 80, 80, 80, 80 );
+    Integration::ResourcePointer resourcePtr(bitmap); // reference it
+
+    // Set up platform abstraction to load it
+    id=req->GetId();
+
+    application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr);
+
+    DALI_TEST_CHECK( ! resourceManager.IsResourceLoaded(id));
+
+    application.GetPlatform().ResetTrace();
+    // load the cache, which will immediately have the loaded resource
+    application.Render(0);
+
+    // UpdateCache runs before ProcessMessages, so the loading resource completes before
+    // the reload request is handled.
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc ) );
+    DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::GetResourcesFunc ) );
+
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id));
+    Internal::BitmapMetadata bitmapData = resourceManager.GetBitmapMetadata(id);
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 80 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 80 );
+
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 0, TEST_LOCATION );
+
+    // Trigger the event thread to process notify messages. Should then trigger the signals
+    // in the ticket observer
+    application.SendNotification();
+
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoading, TEST_LOCATION );
+
+    // Check that the image ticket was updated with the image attributes
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( resourceManager.ResourcesToProcess(), true, TEST_LOCATION );
+
+    // Create a new resource - the image size could have changed in the meantime
+    req = application.GetPlatform().GetRequest();
+    Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+    bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 120, 120, 120, 120 );
+    Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
+    DALI_TEST_CHECK( req->GetId() == id );
+    application.GetPlatform().SetResourceLoaded(id, Integration::ResourceBitmap, resourcePtr2);
+
+    application.Render(0);  // Process update messages / UpdateCache
+
+    DALI_TEST_CHECK( resourceManager.IsResourceLoaded(id));
+    bitmapData = resourceManager.GetBitmapMetadata(id);
+    DALI_TEST_CHECK( bitmapData.GetWidth() == 120 );
+    DALI_TEST_CHECK( bitmapData.GetHeight() == 120 );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 80, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+    application.SendNotification(); // Process event messages
+
+    DALI_TEST_EQUALS( testTicketObserver.LoadSucceededCalled(), 2, TEST_LOCATION );
+
+    // Not staged - no GL upload
+    DALI_TEST_EQUALS( testTicketObserver.UploadCalled(), 0, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( ticket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetWidth(), 120, TEST_LOCATION );
+    DALI_TEST_EQUALS( imageTicket->GetHeight(), 120, TEST_LOCATION );
+    DALI_TEST_EQUALS( resourceManager.ResourcesToProcess(), false, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliInternalRequestResourceTicket01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RequestResourceTicket() with valid id");
+
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+
+  // First, load a bitmap resource
+  Internal::ResourceTicketPtr ticket = CheckLoadBitmap(application, "bitmap.jpg", 80, 80);
+
+  Internal::ResourceTicketPtr newTicket = resourceClient.RequestResourceTicket( ticket->GetId() );
+  DALI_TEST_CHECK( newTicket );
+  DALI_TEST_CHECK( newTicket->GetId() == ticket->GetId() );
+  DALI_TEST_CHECK( newTicket->GetTypePath().type->id == ticket->GetTypePath().type->id );
+  END_TEST;
+}
+
+int UtcDaliInternalRequestResourceTicket02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RequestResourceTicket() with invalid id");
+
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient = Internal::ThreadLocalStorage::Get().GetResourceClient();
+
+  // First, load a bitmap resource
+  Internal::ResourceTicketPtr ticket = CheckLoadBitmap(application, "bitmap.jpg", 80, 80);
+
+  Internal::ResourceTicketPtr newTicket = resourceClient.RequestResourceTicket( ticket->GetId() + 2000 );
+  DALI_TEST_CHECK( ! newTicket );
+  END_TEST;
+}
+
+int UtcDaliInternalAllocateBitmapImage01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AllocateBitmapImage()");
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ImageTicketPtr imageTicket = resourceClient.AllocateBitmapImage(80, 80, 80, 80, Pixel::RGB565);
+  imageTicket->AddObserver( testTicketObserver );
+
+  DALI_TEST_CHECK( imageTicket );
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+  Integration::Bitmap* bitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( bitmap != NULL );
+  DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliInternalAddBitmapImage01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AddBitmap with reserved buffer()");
+  testTicketObserver.Reset();
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::OWNED_RETAIN  );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGB565, 80, 80, 80, 80 );
+
+  Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
+  DALI_TEST_CHECK( imageTicket );
+  imageTicket->AddObserver( testTicketObserver );
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+
+  Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( theBitmap != NULL );
+  DALI_TEST_CHECK ( bitmap == theBitmap );
+  DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGB565, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliInternalAddBitmapImage02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AddBitmap without reserved buffer()");
+  testTicketObserver.Reset();
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::OWNED_RETAIN  );
+
+  Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
+  DALI_TEST_CHECK( imageTicket );
+  imageTicket->AddObserver( testTicketObserver );
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 0, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 0, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 0, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( theBitmap != NULL );
+  DALI_TEST_CHECK ( bitmap == theBitmap );
+  DALI_TEST_EQUALS ( bitmap->GetImageWidth(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetImageHeight(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  // There is no way for the ticket's image attributes to be updated if the bitmap
+  // reserves a buffer after ticket generation.
+  // Probably not an issue - there is no public API in BufferImage to change the image size.
+  END_TEST;
+}
+
+
+int UtcDaliInternalAddBitmapImage03(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AddBitmap() with invalid bitmap");
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ImageTicketPtr imageTicket;
+  bool exceptionRaised=false;
+  try
+  {
+    imageTicket = resourceClient.AddBitmapImage( NULL );
+  }
+  catch( DaliException& e )
+  {
+    exceptionRaised = true;
+  }
+  DALI_TEST_CHECK( exceptionRaised );
+  DALI_TEST_CHECK( ! imageTicket );
+  END_TEST;
+}
+
+int UtcDaliInternalGetBitmapImage01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing GetBitmap() with valid ticket");
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS,  ResourcePolicy::OWNED_RETAIN  );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888, 20, 20, 80, 80 );
+  Internal::ImageTicketPtr imageTicket = resourceClient.AddBitmapImage( bitmap );
+
+  Integration::Bitmap* theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( theBitmap != NULL );
+  DALI_TEST_CHECK ( bitmap == theBitmap );
+  DALI_TEST_EQUALS ( bitmap->GetImageWidth(),   20u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetImageHeight(),  20u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(),  80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+  imageTicket->AddObserver( testTicketObserver );
+  application.SendNotification(); // Flush update queue
+  application.Render(0);          // Process message
+  application.SendNotification(); // Send message to tickets
+
+  theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( theBitmap != NULL );
+  DALI_TEST_CHECK ( bitmap == theBitmap );
+  DALI_TEST_EQUALS ( bitmap->GetImageWidth(),   20u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetImageHeight(),  20u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferWidth(),  80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPackedPixelsProfile()->GetBufferHeight(), 80u, TEST_LOCATION );
+  DALI_TEST_EQUALS ( bitmap->GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliInternalGetBitmapImage02(void)
+{
+  TestApplication application;
+  tet_infoline("Testing GetBitmap() with invalid ticket");
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ImageTicketPtr imageTicket;
+  Integration::Bitmap* theBitmap = NULL;
+  bool exceptionRaised = false;
+  try
+  {
+    theBitmap = resourceClient.GetBitmap(imageTicket);
+  } catch (DaliException& e)
+  {
+    exceptionRaised = true;
+  }
+  DALI_TEST_CHECK( exceptionRaised );
+  DALI_TEST_CHECK( ! theBitmap );
+  END_TEST;
+}
+
+int UtcDaliInternalGetBitmapImage03(void)
+{
+  TestApplication application;
+  tet_infoline("Testing GetBitmap() with valid ticket for incorrect type");
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();  Internal::ResourceTicketPtr imageTicket = CheckLoadBitmap( application, "Stuff.png", 100, 100 );
+
+  Integration::Bitmap* theBitmap = NULL;
+  theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK( ! theBitmap );
+
+  END_TEST;
+}
+
+int UtcDaliInternalAllocateTexture01(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AllocateTexture()");
+  testTicketObserver.Reset();
+
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ResourceTicketPtr resourceTicket = resourceClient.AllocateTexture(80, 80, Pixel::L8 );
+  resourceTicket->AddObserver( testTicketObserver );
+
+  DALI_TEST_CHECK( resourceTicket );
+  DALI_TEST_EQUALS ( resourceTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_EQUALS ( resourceTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_CHECK( testTicketObserver.LoadSucceededCalled() == 0 );
+  END_TEST;
+}
+
+int UtcDaliInternalAddNativeImage(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AddNativeImage()");
+
+  testTicketObserver.Reset();
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ResourceTicketPtr ticket;
+  Internal::ImageTicketPtr imageTicket;
+  { // Test image going out of scope after ticket creation (message to Update thread holds a ref)
+    TestNativeImagePointer nativeImage = TestNativeImage::New( 80, 80 );
+    ticket = resourceClient.AddNativeImage( *nativeImage );
+    imageTicket = dynamic_cast<Internal::ImageTicket*>(ticket.Get());
+    DALI_TEST_CHECK( imageTicket );
+    imageTicket->AddObserver( testTicketObserver );
+  }
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(),  80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(),  80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  Integration::Bitmap* theBitmap = NULL;
+  theBitmap = resourceClient.GetBitmap(imageTicket);
+
+  DALI_TEST_CHECK ( theBitmap == NULL );
+  END_TEST;
+}
+
+int UtcDaliInternalAddFrameBufferImage(void)
+{
+  TestApplication application;
+  tet_infoline("Testing AddFrameBufferImage()");
+
+  testTicketObserver.Reset();
+  Internal::ResourceClient& resourceClient  = Internal::ThreadLocalStorage::Get().GetResourceClient();
+  Internal::ImageTicketPtr imageTicket = resourceClient.AddFrameBufferImage(80, 80, Pixel::A8, RenderBuffer::COLOR );
+  DALI_TEST_CHECK( imageTicket );
+  imageTicket->AddObserver( testTicketObserver );
+
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(),  80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  application.SendNotification(); // Flush update queue
+  application.Render(0); // Process message
+  application.SendNotification(); // Send message to tickets
+
+  DALI_TEST_EQUALS ( imageTicket->GetLoadingState(), ResourceLoadingSucceeded, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetWidth(), 80, TEST_LOCATION );
+  DALI_TEST_EQUALS ( imageTicket->GetHeight(), 80, TEST_LOCATION );
+  DALI_TEST_CHECK ( 0 == testTicketObserver.LoadSucceededCalled() ); // Check no message was sent
+
+  Integration::Bitmap* theBitmap = NULL;
+  theBitmap = resourceClient.GetBitmap(imageTicket);
+  DALI_TEST_CHECK ( theBitmap == NULL );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/CMakeLists.txt b/automated-tests/src/dali/CMakeLists.txt
new file mode 100644 (file)
index 0000000..d474038
--- /dev/null
@@ -0,0 +1,118 @@
+SET(PKG_NAME "dali")
+
+SET(EXEC_NAME "tct-${PKG_NAME}-core")
+SET(RPM_NAME "core-${PKG_NAME}-tests")
+
+SET(CAPI_LIB "dali")
+
+SET(TC_SOURCES
+        utc-Dali-Actor.cpp
+        utc-Dali-AlphaFunction.cpp
+        utc-Dali-AngleAxis.cpp
+        utc-Dali-Animation.cpp
+        utc-Dali-Any.cpp
+        utc-Dali-BaseHandle.cpp
+        utc-Dali-BufferImage.cpp
+        utc-Dali-CameraActor.cpp
+        utc-Dali-Constraint.cpp
+        utc-Dali-ConstraintFunction.cpp
+        utc-Dali-Constraints.cpp
+        utc-Dali-ConstraintSource.cpp
+        utc-Dali-ConnectionTracker.cpp
+        utc-Dali-CustomActor.cpp
+        utc-Dali-Degree.cpp
+        utc-Dali-EncodedBufferImage.cpp
+        utc-Dali-FrameBufferImage.cpp
+        utc-Dali-Gesture.cpp
+        utc-Dali-GestureDetector.cpp
+        utc-Dali-Handle.cpp
+        utc-Dali-HoverProcessing.cpp
+        utc-Dali-Image.cpp
+        utc-Dali-ImageActor.cpp
+        utc-Dali-IntrusivePtr.cpp
+        utc-Dali-KeyEvent.cpp
+        utc-Dali-Layer.cpp
+        utc-Dali-LocklessBuffer.cpp
+        utc-Dali-LongPressGesture.cpp
+        utc-Dali-LongPressGestureDetector.cpp
+        utc-Dali-MathUtils.cpp
+        utc-Dali-Matrix.cpp
+        utc-Dali-Matrix3.cpp
+        utc-Dali-MeshMaterial.cpp
+        utc-Dali-NativeImage.cpp
+        utc-Dali-NinePatchImages.cpp
+        utc-Dali-ObjectRegistry.cpp
+        utc-Dali-PanGesture.cpp
+        utc-Dali-PanGestureDetector.cpp
+        utc-Dali-Path.cpp
+        utc-Dali-PinchGesture.cpp
+        utc-Dali-PinchGestureDetector.cpp
+        utc-Dali-Pixel.cpp
+        utc-Dali-PropertyMap.cpp
+        utc-Dali-PropertyArray.cpp
+        utc-Dali-PropertyNotification.cpp
+        utc-Dali-PropertyTypes.cpp
+        utc-Dali-PropertyValue.cpp
+        utc-Dali-Quaternion.cpp
+        utc-Dali-Radian.cpp
+        utc-Dali-Random.cpp
+        utc-Dali-Rect.cpp
+        utc-Dali-RenderTask.cpp
+        utc-Dali-RenderTaskList.cpp
+        utc-Dali-ResourceImage.cpp
+        utc-Dali-ShaderEffect.cpp
+        utc-Dali-SignalTemplatesFunctors.cpp
+        utc-Dali-SignalTemplates.cpp
+        utc-Dali-Stage.cpp
+        utc-Dali-TapGesture.cpp
+        utc-Dali-TapGestureDetector.cpp
+        utc-Dali-TouchEventCombiner.cpp
+        utc-Dali-TouchProcessing.cpp
+        utc-Dali-TypeRegistry.cpp
+        utc-Dali-Uint16Pair.cpp
+        utc-Dali-Vector.cpp
+        utc-Dali-Vector2.cpp
+        utc-Dali-Vector3.cpp
+        utc-Dali-Vector4.cpp
+        utc-Dali-WheelEvent.cpp
+        utc-Dali-Constrainer.cpp
+)
+
+LIST(APPEND TC_SOURCES
+        dali-test-suite-utils/mesh-builder.cpp
+        dali-test-suite-utils/dali-test-suite-utils.cpp
+        dali-test-suite-utils/test-harness.cpp
+        dali-test-suite-utils/test-application.cpp
+        dali-test-suite-utils/test-gesture-manager.cpp
+        dali-test-suite-utils/test-gl-abstraction.cpp
+        dali-test-suite-utils/test-gl-sync-abstraction.cpp
+        dali-test-suite-utils/test-native-image.cpp
+        dali-test-suite-utils/test-platform-abstraction.cpp
+        dali-test-suite-utils/test-render-controller.cpp
+        dali-test-suite-utils/test-trace-call-stack.cpp
+)
+
+PKG_CHECK_MODULES(${CAPI_LIB} REQUIRED
+     dali-core
+)
+
+SET(CMAKE_CXX_FLAGS  "${CMAKE_CXX_FLAGS} ${${CAPI_LIB}_CFLAGS_OTHER} -O0 -ggdb --coverage -Wall -Werror=return-type")
+
+FOREACH(directory ${${CAPI_LIB}_LIBRARY_DIRS})
+    SET(CMAKE_CXX_LINK_FLAGS "${CMAKE_CXX_LINK_FLAGS} -L${directory}")
+ENDFOREACH(directory ${CAPI_LIB_LIBRARY_DIRS})
+
+INCLUDE_DIRECTORIES(
+    ../../../
+    ${${CAPI_LIB}_INCLUDE_DIRS}
+    dali-test-suite-utils
+)
+
+ADD_EXECUTABLE(${EXEC_NAME} ${EXEC_NAME}.cpp ${TC_SOURCES})
+TARGET_LINK_LIBRARIES(${EXEC_NAME}
+    ${${CAPI_LIB}_LIBRARIES}
+)
+
+INSTALL(PROGRAMS ${EXEC_NAME}
+    DESTINATION ${BIN_DIR}/${EXEC_NAME}
+)
diff --git a/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.cpp
new file mode 100644 (file)
index 0000000..d053cf5
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "dali-test-suite-utils.h"
+
+// EXTERNAL INCLUDES
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+
+using namespace Dali;
+
+int test_return_value = TET_UNDEF;
+
+void tet_result(int value)
+{
+  // First TET_PASS should set to zero
+  // first TET_FAIL should prevent any further TET_PASS from setting back to zero
+  // Any TET_FAIL should set to fail or leave as fail
+  if( test_return_value != 1 )
+    test_return_value = value;
+}
+
+#define END_TEST \
+  return ((test_return_value>0)?1:0)
+
+
+void tet_infoline(const char* str)
+{
+  fprintf(stderr, "%s\n", str);
+}
+
+void tet_printf(const char *format, ...)
+{
+  va_list arg;
+  va_start(arg, format);
+  vfprintf(stderr, format, arg);
+  va_end(arg);
+}
+
+bool operator==(TimePeriod a, TimePeriod b)
+{
+  return Equals(a.durationSeconds, b.durationSeconds) && Equals(a.delaySeconds, b.delaySeconds) ;
+}
+
+std::ostream& operator<<( std::ostream& ostream, TimePeriod value )
+{
+  return ostream << "( Duration:" << value.durationSeconds << " Delay:" << value.delaySeconds << ")";
+}
+
+std::ostream& operator<<( std::ostream& ostream, Radian angle )
+{
+  ostream << angle.radian;
+  return ostream;
+}
+
+std::ostream& operator<<( std::ostream& ostream, Degree angle )
+{
+  ostream << angle.degree;
+  return ostream;
+}
+
+void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const char* location)
+{
+  const float* m1 = matrix1.AsFloat();
+  const float* m2 = matrix2.AsFloat();
+  bool equivalent = true;
+
+  for (int i=0;i<9;++i)
+  {
+    if( ! (fabsf(m1[i] - m2[i])< GetRangedEpsilon(m1[i], m2[i])) )
+    {
+      equivalent = false;
+    }
+  }
+
+  if( !equivalent )
+  {
+    fprintf(stderr, "%s, checking\n"
+               "(%f, %f, %f)    (%f, %f, %f)\n"
+               "(%f, %f, %f) == (%f, %f, %f)\n"
+               "(%f, %f, %f)    (%f, %f, %f)\n",
+               location,
+               m1[0],  m1[1], m1[2],   m2[0],  m2[1], m2[2],
+               m1[3],  m1[4], m1[5],   m2[3],  m2[4], m2[5],
+               m1[6],  m1[7], m1[8],   m2[6],  m2[7], m2[8]);
+
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location)
+{
+  const float* m1 = matrix1.AsFloat();
+  const float* m2 = matrix2.AsFloat();
+  bool equivalent = true;
+
+  for (int i=0;i<9;++i)
+  {
+    equivalent &= (fabsf(m1[i] - m2[i])<epsilon);
+  }
+
+  if (!equivalent)
+  {
+    fprintf(stderr, "%s, checking\n"
+               "(%f, %f, %f)    (%f, %f, %f)\n"
+               "(%f, %f, %f) == (%f, %f, %f)\n"
+               "(%f, %f, %f)    (%f, %f, %f)\n",
+               location,
+               m1[0],  m1[1], m1[2],   m2[0],  m2[1], m2[2],
+               m1[3],  m1[4], m1[5],   m2[3],  m2[4], m2[5],
+               m1[6],  m1[7], m1[8],   m2[6],  m2[7], m2[8]);
+
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, const char* location)
+{
+  const float* m1 = matrix1.AsFloat();
+  const float* m2 = matrix2.AsFloat();
+  bool identical = true;
+
+  int i;
+  for (i=0;i<16;++i)
+  {
+    if(m1[i] != m2[i])
+    {
+      identical = false;
+      break;
+    }
+  }
+
+  if (!identical)
+  {
+    fprintf(stderr, "%s, checking\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f) == (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n", location,
+               m1[0],  m1[1],  m1[2],  m1[3],   m2[0],  m2[1],  m2[2],  m2[3],
+               m1[4],  m1[5],  m1[6],  m1[7],   m2[4],  m2[5],  m2[6],  m2[7],
+               m1[8],  m1[9], m1[10], m1[11],   m2[8],  m2[9], m2[10], m2[11],
+              m1[12], m1[13], m1[14], m1[15],  m2[12], m2[13], m2[14], m2[15]);
+
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location)
+{
+  const float* m1 = matrix1.AsFloat();
+  const float* m2 = matrix2.AsFloat();
+  bool equivalent = true;
+
+  for (int i=0;i<16;++i)
+  {
+    equivalent &= (fabsf(m1[i] - m2[i])<epsilon);
+  }
+
+  if (!equivalent)
+  {
+    fprintf(stderr, "%s, checking\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f) == (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n"
+               "(%f, %f, %f, %f)    (%f, %f, %f, %f)\n", location,
+               m1[0],  m1[1],  m1[2],  m1[3],   m2[0],  m2[1],  m2[2],  m2[3],
+               m1[4],  m1[5],  m1[6],  m1[7],   m2[4],  m2[5],  m2[6],  m2[7],
+               m1[8],  m1[9], m1[10], m1[11],   m2[8],  m2[9], m2[10], m2[11],
+              m1[12], m1[13], m1[14], m1[15],  m2[12], m2[13], m2[14], m2[15]);
+
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1.c_str(), str2, location);
+}
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1, str2.c_str(), location);
+}
+
+void DALI_TEST_ASSERT( DaliException& e, std::string conditionSubString, const char* location )
+{
+  if( NULL == strstr( e.condition, conditionSubString.c_str() ) )
+  {
+    fprintf(stderr, "Expected substring '%s' : actual exception string '%s' : location %s\n", conditionSubString.c_str(), e.condition, location );
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+// Functor to test whether an Applied signal is emitted
+ConstraintAppliedCheck::ConstraintAppliedCheck( bool& signalReceived )
+: mSignalReceived( signalReceived )
+{
+}
+
+void ConstraintAppliedCheck::operator()( Constraint& constraint )
+{
+  mSignalReceived = true;
+}
+
+void ConstraintAppliedCheck::Reset()
+{
+  mSignalReceived = false;
+}
+
+void ConstraintAppliedCheck::CheckSignalReceived()
+{
+  if ( !mSignalReceived )
+  {
+    fprintf(stderr,  "Expected Applied signal was not received\n" );
+    tet_result( TET_FAIL );
+  }
+  else
+  {
+    tet_result( TET_PASS );
+  }
+}
+
+void ConstraintAppliedCheck::CheckSignalNotReceived()
+{
+  if ( mSignalReceived )
+  {
+    fprintf(stderr,  "Unexpected Applied signal was received\n" );
+    tet_result( TET_FAIL );
+  }
+  else
+  {
+    tet_result( TET_PASS );
+  }
+}
+
+BufferImage CreateBufferImage()
+{
+  BufferImage image = BufferImage::New(4,4,Pixel::RGBA8888);
+
+  PixelBuffer* pixbuf = image.GetBuffer();
+
+  // Using a 4x4 image gives a better blend with the GL implementation
+  // than a 3x3 image
+  for(size_t i=0; i<16; i++)
+  {
+    pixbuf[i*4+0] = 0xFF;
+    pixbuf[i*4+1] = 0xFF;
+    pixbuf[i*4+2] = 0xFF;
+    pixbuf[i*4+3] = 0xFF;
+  }
+
+  return image;
+}
diff --git a/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h b/automated-tests/src/dali/dali-test-suite-utils/dali-test-suite-utils.h
new file mode 100644 (file)
index 0000000..07c8d1f
--- /dev/null
@@ -0,0 +1,375 @@
+#ifndef __DALI_TEST_SUITE_UTILS_H__
+#define __DALI_TEST_SUITE_UTILS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstdarg>
+#include <iostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+
+void tet_infoline(const char*str);
+void tet_printf(const char *format, ...);
+
+#include "test-application.h"
+
+using namespace Dali;
+
+#define STRINGIZE_I(text) #text
+#define STRINGIZE(text) STRINGIZE_I(text)
+
+// the following is the other compilers way of token pasting, gcc seems to just concatenate strings automatically
+//#define TOKENPASTE(x,y) x ## y
+#define TOKENPASTE(x,y) x y
+#define TOKENPASTE2(x,y) TOKENPASTE( x, y )
+#define TEST_LOCATION TOKENPASTE2( "Test failed in ", TOKENPASTE2( __FILE__, TOKENPASTE2( ", line ", STRINGIZE(__LINE__) ) ) )
+
+#define TET_UNDEF 2
+#define TET_FAIL 1
+#define TET_PASS 0
+
+extern int test_return_value;
+
+void tet_result(int value);
+
+#define END_TEST \
+  return ((test_return_value>0)?1:0)
+
+void tet_infoline(const char* str);
+void tet_printf(const char *format, ...);
+
+/**
+ * DALI_TEST_CHECK is a wrapper for tet_result.
+ * If the condition evaluates to false, the test is stopped.
+ * @param[in] The boolean expression to check
+ */
+#define DALI_TEST_CHECK(condition)                                                        \
+if ( (condition) )                                                                        \
+{                                                                                         \
+  tet_result(TET_PASS);                                                                   \
+}                                                                                         \
+else                                                                                      \
+{                                                                                         \
+  fprintf(stderr, "%s Failed in %s at line %d\n", __PRETTY_FUNCTION__, __FILE__, __LINE__);    \
+  tet_result(TET_FAIL);                                                                   \
+  throw("TET_FAIL");                                                                      \
+}
+
+template <typename Type>
+inline bool CompareType(Type value1, Type value2, float epsilon);
+
+/**
+ * A helper for fuzzy-comparing Vector2 objects
+ * @param[in] vector1 the first object
+ * @param[in] vector2 the second object
+ * @param[in] epsilon difference threshold
+ * @returns true if difference is smaller than epsilon threshold, false otherwise
+ */
+template <>
+inline bool CompareType<float>(float value1, float value2, float epsilon)
+{
+  return fabsf(value1 - value2) < epsilon;
+}
+
+/**
+ * A helper for fuzzy-comparing Vector2 objects
+ * @param[in] vector1 the first object
+ * @param[in] vector2 the second object
+ * @param[in] epsilon difference threshold
+ * @returns true if difference is smaller than epsilon threshold, false otherwise
+ */
+template <>
+inline bool CompareType<Vector2>(Vector2 vector1, Vector2 vector2, float epsilon)
+{
+  return fabsf(vector1.x - vector2.x)<epsilon && fabsf(vector1.y - vector2.y)<epsilon;
+}
+
+/**
+ * A helper for fuzzy-comparing Vector3 objects
+ * @param[in] vector1 the first object
+ * @param[in] vector2 the second object
+ * @param[in] epsilon difference threshold
+ * @returns true if difference is smaller than epsilon threshold, false otherwise
+ */
+template <>
+inline bool CompareType<Vector3>(Vector3 vector1, Vector3 vector2, float epsilon)
+{
+  return fabsf(vector1.x - vector2.x)<epsilon &&
+         fabsf(vector1.y - vector2.y)<epsilon &&
+         fabsf(vector1.z - vector2.z)<epsilon;
+}
+
+
+/**
+ * A helper for fuzzy-comparing Vector4 objects
+ * @param[in] vector1 the first object
+ * @param[in] vector2 the second object
+ * @param[in] epsilon difference threshold
+ * @returns true if difference is smaller than epsilon threshold, false otherwise
+ */
+template <>
+inline bool CompareType<Vector4>(Vector4 vector1, Vector4 vector2, float epsilon)
+{
+  return fabsf(vector1.x - vector2.x)<epsilon &&
+         fabsf(vector1.y - vector2.y)<epsilon &&
+         fabsf(vector1.z - vector2.z)<epsilon &&
+         fabsf(vector1.w - vector2.w)<epsilon;
+}
+
+template <>
+inline bool CompareType<Quaternion>(Quaternion q1, Quaternion q2, float epsilon)
+{
+  Quaternion q2N = -q2; // These quaternions represent the same rotation
+  return CompareType<Vector4>(q1.mVector, q2.mVector, epsilon) || CompareType<Vector4>(q1.mVector, q2N.mVector, epsilon);
+}
+
+template <>
+inline bool CompareType<Radian>(Radian q1, Radian q2, float epsilon)
+{
+  return CompareType<float>(q1.radian, q2.radian, epsilon);
+}
+
+template <>
+inline bool CompareType<Degree>(Degree q1, Degree q2, float epsilon)
+{
+  return CompareType<float>(q1.degree, q2.degree, epsilon);
+}
+
+bool operator==(TimePeriod a, TimePeriod b);
+std::ostream& operator<<( std::ostream& ostream, TimePeriod value );
+std::ostream& operator<<( std::ostream& ostream, Radian angle );
+std::ostream& operator<<( std::ostream& ostream, Degree angle );
+
+/**
+ * Test whether two values are equal.
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<typename TypeA, typename TypeB>
+inline void DALI_TEST_EQUALS(TypeA value1, TypeB value2, const char* location)
+{
+  if (!(value1 == value2))
+  {
+    std::ostringstream o;
+    o << value1 << " == " << value2 << std::endl;
+    fprintf(stderr, "%s, checking %s", location, o.str().c_str());
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+template<typename Type>
+inline void DALI_TEST_EQUALS(Type value1, Type value2, float epsilon, const char* location)
+{
+  if( !CompareType<Type>(value1, value2, epsilon) )
+  {
+    std::ostringstream o;
+    o << value1 << " == " << value2 << std::endl;
+    fprintf(stderr, "%s, checking %s", location, o.str().c_str());
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+/**
+ * Test whether two TimePeriods are within a certain distance of each other.
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] epsilon The values must be within this distance of each other
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<>
+inline void DALI_TEST_EQUALS<TimePeriod>( TimePeriod value1, TimePeriod value2, float epsilon, const char* location)
+{
+  if ((fabs(value1.durationSeconds - value2.durationSeconds) > epsilon))
+  {
+    fprintf(stderr, "%s, checking durations %f == %f, epsilon %f\n", location, value1.durationSeconds, value2.durationSeconds, epsilon);
+    tet_result(TET_FAIL);
+  }
+  else if ((fabs(value1.delaySeconds - value2.delaySeconds) > epsilon))
+  {
+    fprintf(stderr, "%s, checking delays %f == %f, epsilon %f\n", location, value1.delaySeconds, value2.delaySeconds, epsilon);
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+/**
+ * Test whether two Matrix3 objects are equal.
+ * @param[in] matrix1 The first object
+ * @param[in] matrix2 The second object
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, const char* location);
+
+/** Test whether two Matrix3 objects are equal (fuzzy compare).
+ * @param[in] matrix1 The first object
+ * @param[in] matrix2 The second object
+ * @param[in] epsilon The epsilon to use for comparison
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const Matrix3& matrix1, const Matrix3& matrix2, float epsilon, const char* location);
+
+/**
+ * Test whether two Matrix objects are equal.
+ * @param[in] matrix1 The first object
+ * @param[in] matrix2 The second object
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, const char* location);
+
+/**
+ * Test whether two Matrix objects are equal (fuzzy-compare).
+ * @param[in] matrix1 The first object
+ * @param[in] matrix2 The second object
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const Matrix& matrix1, const Matrix& matrix2, float epsilon, const char* location);
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<>
+inline void DALI_TEST_EQUALS<const char*>( const char* str1, const char* str2, const char* location)
+{
+  if (strcmp(str1, str2))
+  {
+    fprintf(stderr, "%s, checking '%s' == '%s'\n", location, str1, str2);
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template<>
+inline void DALI_TEST_EQUALS<const std::string&>( const std::string &str1, const std::string &str2, const char* location)
+{
+  DALI_TEST_EQUALS(str1.c_str(), str2.c_str(), location);
+}
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const std::string &str1, const char* str2, const char* location);
+
+/**
+ * Test whether two strings are equal.
+ * @param[in] str1 The first string
+ * @param[in] str2 The second string
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+void DALI_TEST_EQUALS( const char* str1, const std::string &str2, const char* location);
+
+/**
+ * Test whether one unsigned integer value is greater than another.
+ * Test succeeds if value1 > value2
+ * @param[in] value1 The first value
+ * @param[in] value2 The second value
+ * @param[in] location The TEST_LOCATION macro should be used here
+ */
+template< typename T >
+void DALI_TEST_GREATER( T value1, T value2, const char* location)
+{
+  if (!(value1 > value2))
+  {
+    std::cerr << location << ", checking " << value1 <<" > " << value2 << "\n";
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+}
+
+/**
+ * Test whether the assertion condition that failed and thus triggered the
+ * exception \b e contained a given substring.
+ * @param[in] e The exception that we expect was fired by a runtime assertion failure.
+ * @param[in] conditionSubString The text that we expect to be present in an
+ *                               assertion which triggered the exception.
+ * @param[in] location The TEST_LOCATION macro should be used here.
+ */
+void DALI_TEST_ASSERT( DaliException& e, std::string conditionSubString, const char* location );
+
+/**
+ * Print the assert
+ * @param[in] e The exception that we expect was fired by a runtime assertion failure.
+ */
+inline void DALI_TEST_PRINT_ASSERT( DaliException& e )
+{
+  tet_printf("Assertion %s failed at %s\n", e.condition, e.location );
+}
+
+// Functor to test whether an Applied signal is emitted
+struct ConstraintAppliedCheck
+{
+  ConstraintAppliedCheck( bool& signalReceived );
+  void operator()( Constraint& constraint );
+  void Reset();
+  void CheckSignalReceived();
+  void CheckSignalNotReceived();
+  bool& mSignalReceived; // owned by individual tests
+};
+
+/**
+ * A Helper to test default functions
+ */
+template <typename T>
+struct DefaultFunctionCoverage
+{
+  DefaultFunctionCoverage()
+  {
+    T a;
+    T *b = new T(a);
+    DALI_TEST_CHECK(b);
+    a = *b;
+    delete b;
+  }
+};
+
+
+// Helper to Create buffer image
+BufferImage CreateBufferImage();
+
+#endif // __DALI_TEST_SUITE_UTILS_H__
diff --git a/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.cpp
new file mode 100644 (file)
index 0000000..3fdae8a
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "mesh-builder.h"
+
+namespace Dali
+{
+
+Material CreateMaterial(float opacity)
+{
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc" );
+  Material material = Material::New(shader);
+
+  Vector4 color = Color::WHITE;
+  color.a = opacity;
+  material.SetProperty(Material::Property::COLOR, color);
+  return material;
+}
+
+Material CreateMaterial(float opacity, Image image)
+{
+  Shader shader = Shader::New( "vertexSrc", "fragmentSrc" );
+  Material material = Material::New(shader);
+
+  Vector4 color = Color::WHITE;
+  color.a = opacity;
+  material.SetProperty(Material::Property::COLOR, color);
+
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  material.AddSampler( sampler );
+
+  return material;
+}
+
+PropertyBuffer CreatePropertyBuffer()
+{
+  Property::Map texturedQuadVertexFormat;
+  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+  texturedQuadVertexFormat["aVertexCoord"] = Property::VECTOR2;
+
+  PropertyBuffer vertexData = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+  return vertexData;
+}
+
+Geometry CreateQuadGeometry(void)
+{
+  PropertyBuffer vertexData = CreatePropertyBuffer();
+  return CreateQuadGeometryFromBuffer( vertexData );
+}
+
+Geometry CreateQuadGeometryFromBuffer( PropertyBuffer vertexData )
+{
+  const float halfQuadSize = .5f;
+  struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+  TexturedQuadVertex texturedQuadVertexData[4] = {
+    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+  vertexData.SetData(texturedQuadVertexData);
+
+  unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
+  Property::Map indexFormat;
+  indexFormat["indices"] = Property::INTEGER;
+  PropertyBuffer indices = PropertyBuffer::New( indexFormat, sizeof(indexData)/sizeof(indexData[0]) );
+  indices.SetData(indexData);
+
+  Geometry geometry = Geometry::New();
+  geometry.AddVertexBuffer( vertexData );
+  geometry.SetIndexBuffer( indices );
+
+  return geometry;
+}
+
+
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h b/automated-tests/src/dali/dali-test-suite-utils/mesh-builder.h
new file mode 100644 (file)
index 0000000..a123808
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef MESH_BUILDER_H
+#define MESH_BUILDER_H
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/object/property-buffer.h>
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/devel-api/rendering/material.h>
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/devel-api/rendering/renderer.h>
+
+namespace Dali
+{
+
+Material CreateMaterial(float opacity);
+Material CreateMaterial(float opacity, Image image);
+Geometry CreateQuadGeometry();
+Geometry CreateQuadGeometryFromBuffer( PropertyBuffer vertexData );
+PropertyBuffer CreatePropertyBuffer();
+
+}
+
+#endif // MESH_BUILDER_H
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-application.cpp
new file mode 100644 (file)
index 0000000..5d17a1d
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-application.h"
+
+namespace Dali
+{
+
+
+TestApplication::TestApplication( size_t surfaceWidth,
+                                  size_t surfaceHeight,
+                                  float  horizontalDpi,
+                                  float  verticalDpi,
+                                  ResourcePolicy::DataRetention policy)
+: mCore( NULL ),
+  mSurfaceWidth( surfaceWidth ),
+  mSurfaceHeight( surfaceHeight ),
+  mFrame( 0u ),
+  mDpi( horizontalDpi, verticalDpi ),
+  mLastVSyncTime(0u),
+  mDataRetentionPolicy(policy)
+{
+  Initialize();
+}
+
+TestApplication::TestApplication( bool   initialize,
+                                  size_t surfaceWidth,
+                                  size_t surfaceHeight,
+                                  float  horizontalDpi,
+                                  float  verticalDpi,
+                                  ResourcePolicy::DataRetention policy)
+: mCore( NULL ),
+  mSurfaceWidth( surfaceWidth ),
+  mSurfaceHeight( surfaceHeight ),
+  mFrame( 0u ),
+  mDpi( horizontalDpi, verticalDpi ),
+  mLastVSyncTime(0u),
+  mDataRetentionPolicy( policy )
+{
+  if ( initialize )
+  {
+    Initialize();
+  }
+}
+
+void TestApplication::Initialize()
+{
+  mCore = Dali::Integration::Core::New(
+    mRenderController,
+    mPlatformAbstraction,
+    mGlAbstraction,
+    mGlSyncAbstraction,
+    mGestureManager,
+    mDataRetentionPolicy);
+
+  mCore->ContextCreated();
+  mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
+  mCore->SetDpi( mDpi.x, mDpi.y );
+
+  Dali::Integration::Log::LogFunction logFunction(&TestApplication::LogMessage);
+  Dali::Integration::Log::InstallLogFunction(logFunction);
+
+  mCore->SceneCreated();
+}
+
+TestApplication::~TestApplication()
+{
+  Dali::Integration::Log::UninstallLogFunction();
+  delete mCore;
+}
+
+void TestApplication::LogMessage(Dali::Integration::Log::DebugPriority level, std::string& message)
+{
+  switch(level)
+  {
+    case Dali::Integration::Log::DebugInfo:
+      fprintf(stderr, "INFO: %s", message.c_str());
+      break;
+    case Dali::Integration::Log::DebugWarning:
+      fprintf(stderr, "WARN: %s", message.c_str());
+      break;
+    case Dali::Integration::Log::DebugError:
+      fprintf(stderr, "ERROR: %s", message.c_str());
+      break;
+    default:
+      fprintf(stderr, "DEFAULT: %s", message.c_str());
+      break;
+  }
+}
+
+Dali::Integration::Core& TestApplication::GetCore()
+{
+  return *mCore;
+}
+
+TestPlatformAbstraction& TestApplication::GetPlatform()
+{
+  return mPlatformAbstraction;
+}
+
+TestRenderController& TestApplication::GetRenderController()
+{
+  return mRenderController;
+}
+
+TestGlAbstraction& TestApplication::GetGlAbstraction()
+{
+  return mGlAbstraction;
+}
+
+TestGlSyncAbstraction& TestApplication::GetGlSyncAbstraction()
+{
+  return mGlSyncAbstraction;
+}
+
+TestGestureManager& TestApplication::GetGestureManager()
+{
+  return mGestureManager;
+}
+
+void TestApplication::ProcessEvent(const Integration::Event& event)
+{
+  mCore->QueueEvent(event);
+  mCore->ProcessEvents();
+}
+
+void TestApplication::SendNotification()
+{
+  mCore->ProcessEvents();
+}
+
+void TestApplication::SetSurfaceWidth( unsigned int width, unsigned height )
+{
+  mSurfaceWidth = width;
+  mSurfaceHeight = height;
+
+  mCore->SurfaceResized( mSurfaceWidth, mSurfaceHeight );
+}
+
+void TestApplication::DoUpdate( unsigned int intervalMilliseconds )
+{
+  unsigned int seconds(0u), microseconds(0u);
+  mPlatformAbstraction.GetTimeMicroseconds( seconds, microseconds );
+  mLastVSyncTime = ( seconds * 1e3 ) + ( microseconds / 1e3 );
+  unsigned int nextVSyncTime = mLastVSyncTime + 16;
+
+  // Update Time values
+  mPlatformAbstraction.IncrementGetTimeResult( intervalMilliseconds );
+
+  float elapsedSeconds = intervalMilliseconds / 1e3f;
+  mCore->Update( elapsedSeconds, mLastVSyncTime, nextVSyncTime, mStatus );
+}
+
+bool TestApplication::Render( unsigned int intervalMilliseconds  )
+{
+  DoUpdate( intervalMilliseconds );
+  mCore->Render( mRenderStatus );
+
+  mFrame++;
+
+  return mStatus.KeepUpdating() || mRenderStatus.NeedsUpdate();
+}
+
+unsigned int TestApplication::GetUpdateStatus()
+{
+  return mStatus.KeepUpdating();
+}
+
+bool TestApplication::UpdateOnly( unsigned int intervalMilliseconds  )
+{
+  DoUpdate( intervalMilliseconds );
+  return mStatus.KeepUpdating();
+}
+
+bool TestApplication::RenderOnly( )
+{
+  // Update Time values
+  mCore->Render( mRenderStatus );
+
+  mFrame++;
+
+  return mRenderStatus.NeedsUpdate();
+}
+
+void TestApplication::ResetContext()
+{
+  mCore->ContextDestroyed();
+  mCore->ContextCreated();
+}
+
+
+} // Namespace dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-application.h b/automated-tests/src/dali/dali-test-suite-utils/test-application.h
new file mode 100644 (file)
index 0000000..ed33f52
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef __DALI_TEST_APPLICATION_H__
+#define __DALI_TEST_APPLICATION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <test-platform-abstraction.h>
+#include "test-gesture-manager.h"
+#include "test-gl-sync-abstraction.h"
+#include "test-gl-abstraction.h"
+#include "test-render-controller.h"
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/resource-policies.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+class DALI_IMPORT_API TestApplication : public ConnectionTracker
+{
+public:
+
+  // Default values derived from H2 device.
+  static const unsigned int DEFAULT_SURFACE_WIDTH = 480;
+  static const unsigned int DEFAULT_SURFACE_HEIGHT = 800;
+
+#ifdef _CPP11
+  static constexpr float DEFAULT_HORIZONTAL_DPI = 220.0f;
+  static constexpr float DEFAULT_VERTICAL_DPI   = 217.0f;
+#else
+  static const float DEFAULT_HORIZONTAL_DPI = 220.0f;
+  static const float DEFAULT_VERTICAL_DPI   = 217.0f;
+#endif
+
+  static const unsigned int DEFAULT_RENDER_INTERVAL = 1;
+
+  TestApplication( size_t surfaceWidth  = DEFAULT_SURFACE_WIDTH,
+                   size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
+                   float  horizontalDpi = DEFAULT_HORIZONTAL_DPI,
+                   float  verticalDpi   = DEFAULT_VERTICAL_DPI,
+                   ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA);
+
+  TestApplication( bool   initialize,
+                   size_t surfaceWidth  = DEFAULT_SURFACE_WIDTH,
+                   size_t surfaceHeight = DEFAULT_SURFACE_HEIGHT,
+                   float  horizontalDpi = DEFAULT_HORIZONTAL_DPI,
+                   float  verticalDpi   = DEFAULT_VERTICAL_DPI,
+                   ResourcePolicy::DataRetention policy = ResourcePolicy::DALI_DISCARDS_ALL_DATA);
+
+  void Initialize();
+  virtual ~TestApplication();
+  static void LogMessage( Dali::Integration::Log::DebugPriority level, std::string& message );
+  Dali::Integration::Core& GetCore();
+  TestPlatformAbstraction& GetPlatform();
+  TestRenderController& GetRenderController();
+  TestGlAbstraction& GetGlAbstraction();
+  TestGlSyncAbstraction& GetGlSyncAbstraction();
+  TestGestureManager& GetGestureManager();
+  void ProcessEvent(const Integration::Event& event);
+  void SendNotification();
+  void SetSurfaceWidth( unsigned int width, unsigned height );
+  bool Render( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
+  unsigned int GetUpdateStatus();
+  bool UpdateOnly( unsigned int intervalMilliseconds = DEFAULT_RENDER_INTERVAL );
+  bool RenderOnly( );
+  void ResetContext();
+
+private:
+  void DoUpdate( unsigned int intervalMilliseconds );
+
+protected:
+  TestPlatformAbstraction   mPlatformAbstraction;
+  TestRenderController      mRenderController;
+  TestGlAbstraction         mGlAbstraction;
+  TestGlSyncAbstraction     mGlSyncAbstraction;
+  TestGestureManager        mGestureManager;
+
+  Integration::UpdateStatus mStatus;
+  Integration::RenderStatus mRenderStatus;
+
+  Integration::Core* mCore;
+
+  unsigned int mSurfaceWidth;
+  unsigned int mSurfaceHeight;
+  unsigned int mFrame;
+
+  Vector2 mDpi;
+  unsigned int mLastVSyncTime;
+  ResourcePolicy::DataRetention mDataRetentionPolicy;
+};
+
+} // Dali
+
+#endif
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp
new file mode 100644 (file)
index 0000000..2844ff1
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-gesture-manager.h"
+
+namespace Dali
+{
+
+TestGestureManager::TestGestureManager()
+{
+  Initialize();
+}
+
+/**
+ * Destructor
+ */
+TestGestureManager::~TestGestureManager()
+{
+}
+
+/**
+ * @copydoc Dali::Integration::GestureManager::Register(Gesture::Type)
+ */
+void TestGestureManager::Register(const Integration::GestureRequest& request)
+{
+  mFunctionsCalled.Register = true;
+}
+
+/**
+ * @copydoc Dali::Integration::GestureManager::Unregister(Gesture::Type)
+ */
+void TestGestureManager::Unregister(const Integration::GestureRequest& request)
+{
+  mFunctionsCalled.Unregister = true;
+}
+
+/**
+ * @copydoc Dali::Integration::GestureManager::Update(Gesture::Type)
+ */
+void TestGestureManager::Update(const Integration::GestureRequest& request)
+{
+  mFunctionsCalled.Update = true;
+}
+
+
+/** Call this every test */
+void TestGestureManager::Initialize()
+{
+  mFunctionsCalled.Reset();
+}
+
+bool TestGestureManager::WasCalled(TestFuncEnum func)
+{
+  switch(func)
+  {
+    case RegisterType:             return mFunctionsCalled.Register;
+    case UnregisterType:           return mFunctionsCalled.Unregister;
+    case UpdateType:               return mFunctionsCalled.Update;
+  }
+  return false;
+}
+
+void TestGestureManager::ResetCallStatistics(TestFuncEnum func)
+{
+  switch(func)
+  {
+    case RegisterType:             mFunctionsCalled.Register = false; break;
+    case UnregisterType:           mFunctionsCalled.Unregister = false; break;
+    case UpdateType:               mFunctionsCalled.Update = false; break;
+  }
+}
+
+TestGestureManager::TestFunctions::TestFunctions()
+: Register(false),
+  Unregister(false),
+  Update(false)
+{
+}
+
+void TestGestureManager::TestFunctions::Reset()
+{
+  Register = false;
+  Unregister = false;
+  Update = false;
+}
+
+
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h b/automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.h
new file mode 100644 (file)
index 0000000..4c0b766
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __DALI_TEST_GESTURE_MANAGER_H__
+#define __DALI_TEST_GESTURE_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+/**
+ * Concrete implementation of the gesture manager class.
+ */
+class DALI_IMPORT_API TestGestureManager : public Dali::Integration::GestureManager
+{
+
+public:
+
+  /**
+   * Constructor
+   */
+  TestGestureManager();
+
+  /**
+   * Destructor
+   */
+  virtual ~TestGestureManager();
+
+  /**
+   * @copydoc Dali::Integration::GestureManager::Register(Gesture::Type)
+   */
+  virtual void Register(const Integration::GestureRequest& request);
+
+  /**
+   * @copydoc Dali::Integration::GestureManager::Unregister(Gesture::Type)
+   */
+  virtual void Unregister(const Integration::GestureRequest& request);
+
+  /**
+   * @copydoc Dali::Integration::GestureManager::Update(Gesture::Type)
+   */
+  virtual void Update(const Integration::GestureRequest& request);
+
+public: // TEST FUNCTIONS
+
+  // Enumeration of Gesture Manager methods
+  enum TestFuncEnum
+  {
+    RegisterType,
+    UnregisterType,
+    UpdateType,
+  };
+
+  /** Call this every test */
+  void Initialize();
+  bool WasCalled(TestFuncEnum func);
+  void ResetCallStatistics(TestFuncEnum func);
+
+private:
+
+  struct TestFunctions
+  {
+    TestFunctions();
+    void Reset();
+
+    bool Register;
+    bool Unregister;
+    bool Update;
+  };
+
+  TestFunctions mFunctionsCalled;
+};
+
+} // Dali
+
+#endif // __DALI_TEST_GESTURE_MANAGER_H__
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp
new file mode 100644 (file)
index 0000000..d8af042
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-gl-abstraction.h"
+
+namespace Dali
+{
+
+TestGlAbstraction::TestGlAbstraction()
+{
+  Initialize();
+}
+
+TestGlAbstraction::~TestGlAbstraction() {}
+
+void TestGlAbstraction::Initialize()
+{
+  mCurrentProgram = 0;
+  mCompileStatus = GL_TRUE;
+  mLinkStatus = GL_TRUE;
+
+  mGetAttribLocationResult = 0;
+  mGetErrorResult = 0;
+  mGetStringResult = NULL;
+  mIsBufferResult = 0;
+  mIsEnabledResult = 0;
+  mIsFramebufferResult = 0;
+  mIsProgramResult = 0;
+  mIsRenderbufferResult = 0;
+  mIsShaderResult = 0;
+  mIsTextureResult = 0;
+  mVertexAttribArrayChanged = false;
+
+  mCheckFramebufferStatusResult = 0;
+  mFramebufferStatus = 0;
+  mFramebufferColorAttached = 0;
+  mFramebufferDepthAttached = 0;
+  mFramebufferStencilAttached = 0;
+
+  mNumBinaryFormats = 0;
+  mBinaryFormats = 0;
+  mProgramBinaryLength = 0;
+  mGetProgramBinaryCalled = false;
+
+  mLastAutoTextureIdUsed = 0;
+
+  mLastShaderIdUsed = 0;
+  mLastProgramIdUsed = 0;
+  mLastUniformIdUsed = 0;
+  mLastShaderCompiled = 0;
+  mLastClearBitMask = 0;
+  mClearCount = 0;
+
+  mLastBlendEquationRgb   = 0;
+  mLastBlendEquationAlpha = 0;
+  mLastBlendFuncSrcRgb    = 0;
+  mLastBlendFuncDstRgb    = 0;
+  mLastBlendFuncSrcAlpha  = 0;
+  mLastBlendFuncDstAlpha  = 0;
+
+  mUniforms.clear();
+  mProgramUniforms1i.clear();
+  mProgramUniforms1f.clear();
+  mProgramUniforms2f.clear();
+  mProgramUniforms3f.clear();
+  mProgramUniforms4f.clear();
+}
+
+void TestGlAbstraction::PreRender()
+{
+}
+
+void TestGlAbstraction::PostRender()
+{
+}
+
+} // Namespace dali
+
+bool BlendEnabled(const Dali::TraceCallStack& callStack)
+{
+  std::stringstream out;
+  out << GL_BLEND;
+  bool blendEnabled = callStack.FindMethodAndParams("Enable", out.str());
+  return blendEnabled;
+}
+
+bool BlendDisabled(const Dali::TraceCallStack& callStack)
+{
+  std::stringstream out;
+  out << GL_BLEND;
+  bool blendEnabled = callStack.FindMethodAndParams("Disable", out.str());
+  return blendEnabled;
+}
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h
new file mode 100644 (file)
index 0000000..51df9ce
--- /dev/null
@@ -0,0 +1,1999 @@
+#ifndef __TEST_GL_ABSTRACTION_H__
+#define __TEST_GL_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <string>
+#include <map>
+#include <cstdio>
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/core.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+
+static const unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 64;
+static const char *mStdAttribs[MAX_ATTRIBUTE_CACHE_SIZE] =
+{
+    "aPosition",    // ATTRIB_POSITION
+    "aNormal",      // ATTRIB_NORMAL
+    "aTexCoord",    // ATTRIB_TEXCOORD
+    "aColor",       // ATTRIB_COLOR
+    "aBoneWeights", // ATTRIB_BONE_WEIGHTS
+    "aBoneIndices"  // ATTRIB_BONE_INDICES
+};
+
+class DALI_IMPORT_API TestGlAbstraction: public Dali::Integration::GlAbstraction
+{
+public:
+  TestGlAbstraction();
+  ~TestGlAbstraction();
+  void Initialize();
+
+  void PreRender();
+  void PostRender();
+
+  /* OpenGL ES 2.0 */
+
+  inline void ActiveTexture( GLenum textureUnit )
+  {
+    mActiveTextureUnit = textureUnit - GL_TEXTURE0;
+  }
+
+  inline GLenum GetActiveTextureUnit() const
+  {
+    return mActiveTextureUnit + GL_TEXTURE0;
+  }
+
+  inline void AttachShader( GLuint program, GLuint shader )
+  {
+    std::stringstream out;
+    out << program << ", " << shader;
+    mShaderTrace.PushCall("AttachShader", out.str());
+  }
+
+  inline void BindAttribLocation( GLuint program, GLuint index, const char* name )
+  {
+  }
+
+  inline void BindBuffer( GLenum target, GLuint buffer )
+  {
+  }
+
+  inline void BindFramebuffer( GLenum target, GLuint framebuffer )
+  {
+    //Add 010 bit;
+    mFramebufferStatus |= 2;
+  }
+
+  inline void BindRenderbuffer( GLenum target, GLuint renderbuffer )
+  {
+  }
+
+  /**
+   * This method can be used by test cases, to query the texture IDs that have been bound by BindTexture.
+   * @return A vector containing the IDs that were bound.
+   */
+  inline const std::vector<GLuint>& GetBoundTextures() const
+  {
+    return mBoundTextures;
+  }
+
+  /**
+   * Query the texture IDs that have been bound with BindTexture, with a specific active texture unit.
+   * @param[in] activeTextureUnit The specific active texture unit.
+   * @return A vector containing the IDs that were bound.
+   */
+  inline const std::vector<GLuint>& GetBoundTextures( GLuint activeTextureUnit ) const
+  {
+    return mActiveTextures[ activeTextureUnit - GL_TEXTURE0 ].mBoundTextures;
+  }
+
+  /**
+   * This method can be used by test cases, to clear the record of texture IDs that have been bound by BindTexture.
+   */
+  inline void ClearBoundTextures()
+  {
+    mBoundTextures.clear();
+
+    for( unsigned int i=0; i<MIN_TEXTURE_UNIT_LIMIT; ++i )
+    {
+      mActiveTextures[ i ].mBoundTextures.clear();
+    }
+  }
+
+  inline void BindTexture( GLenum target, GLuint texture )
+  {
+    // Record the bound textures for future checks
+    if( texture )
+    {
+      mBoundTextures.push_back( texture );
+
+      if( mActiveTextureUnit < MIN_TEXTURE_UNIT_LIMIT )
+      {
+        mActiveTextures[ mActiveTextureUnit ].mBoundTextures.push_back( texture );
+      }
+    }
+
+    std::stringstream out;
+    out << target << ", " << texture;
+    mTextureTrace.PushCall("BindTexture", out.str());
+  }
+
+  inline void BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+  {
+    mLastBlendColor.r = red;
+    mLastBlendColor.g = green;
+    mLastBlendColor.b = blue;
+    mLastBlendColor.a = alpha;
+  }
+
+  inline const Vector4& GetLastBlendColor() const
+  {
+    return mLastBlendColor;
+  }
+
+  inline void BlendEquation( GLenum mode )
+  {
+    mLastBlendEquationRgb   = mode;
+    mLastBlendEquationAlpha = mode;
+  }
+
+  inline void BlendEquationSeparate( GLenum modeRgb, GLenum modeAlpha )
+  {
+    mLastBlendEquationRgb   = modeRgb;
+    mLastBlendEquationAlpha = modeAlpha;
+  }
+
+  inline GLenum GetLastBlendEquationRgb() const
+  {
+    return mLastBlendEquationRgb;
+  }
+
+  inline GLenum GetLastBlendEquationAlpha() const
+  {
+    return mLastBlendEquationAlpha;
+  }
+
+  inline void BlendFunc(GLenum sfactor, GLenum dfactor)
+  {
+    mLastBlendFuncSrcRgb = sfactor;
+    mLastBlendFuncDstRgb = dfactor;
+    mLastBlendFuncSrcAlpha = sfactor;
+    mLastBlendFuncDstAlpha = dfactor;
+  }
+
+  inline void BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+  {
+    mLastBlendFuncSrcRgb = srcRGB;
+    mLastBlendFuncDstRgb = dstRGB;
+    mLastBlendFuncSrcAlpha = srcAlpha;
+    mLastBlendFuncDstAlpha = dstAlpha;
+  }
+
+  inline GLenum GetLastBlendFuncSrcRgb() const
+  {
+    return mLastBlendFuncSrcRgb;
+  }
+
+  inline GLenum GetLastBlendFuncDstRgb() const
+  {
+    return mLastBlendFuncDstRgb;
+  }
+
+  inline GLenum GetLastBlendFuncSrcAlpha() const
+  {
+    return mLastBlendFuncSrcAlpha;
+  }
+
+  inline GLenum GetLastBlendFuncDstAlpha() const
+  {
+    return mLastBlendFuncDstAlpha;
+  }
+
+  inline void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage)
+  {
+     mBufferDataCalls.push_back(size);
+  }
+
+  inline void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
+  {
+     mBufferSubDataCalls.push_back(size);
+  }
+
+  inline GLenum CheckFramebufferStatus(GLenum target)
+  {
+    //If it has the three last bits set to 1 - 111, then the three minimum functions to create a
+    //Framebuffer texture have been called
+    if( mFramebufferStatus == 7 )
+    {
+      return GL_FRAMEBUFFER_COMPLETE;
+    }
+
+    return mCheckFramebufferStatusResult;
+  }
+
+  inline GLenum CheckFramebufferColorAttachment()
+  {
+    return mFramebufferColorAttached;
+  }
+
+  inline GLenum CheckFramebufferDepthAttachment()
+  {
+    return mFramebufferDepthAttached;
+  }
+
+  inline GLenum CheckFramebufferStencilAttachment()
+  {
+    return mFramebufferStencilAttached;
+  }
+
+  inline void Clear(GLbitfield mask)
+  {
+    mClearCount++;
+    mLastClearBitMask = mask;
+  }
+
+  inline void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+  {
+  }
+
+  inline void ClearDepthf(GLclampf depth)
+  {
+  }
+
+  inline void ClearStencil(GLint s)
+  {
+  }
+
+  inline void ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+  {
+  }
+
+  inline void CompileShader(GLuint shader)
+  {
+    std::stringstream out;
+    out << shader;
+    mShaderTrace.PushCall("CompileShader", out.str());
+  }
+
+  inline void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data)
+  {
+  }
+
+  inline void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
+  {
+  }
+
+  inline void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+  {
+  }
+
+  inline void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline GLuint CreateProgram(void)
+  {
+    mShaderTrace.PushCall("CreateProgram", "");
+
+    ++mLastProgramIdUsed;
+    mUniforms[mLastProgramIdUsed] = UniformIDMap();
+    return mLastProgramIdUsed;
+  }
+
+  inline GLuint CreateShader(GLenum type)
+  {
+    std::stringstream out;
+    out << type;
+    mShaderTrace.PushCall("CreateShader", out.str());
+
+    return ++mLastShaderIdUsed;
+  }
+
+  inline void CullFace(GLenum mode)
+  {
+    std::stringstream out;
+    out << mode;
+    mCullFaceTrace.PushCall("CullFace", out.str());
+  }
+
+  inline void DeleteBuffers(GLsizei n, const GLuint* buffers)
+  {
+  }
+
+  inline void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+  {
+  }
+
+  inline void DeleteProgram(GLuint program)
+  {
+    std::stringstream out;
+    out << program;
+    mShaderTrace.PushCall("DeleteProgram", out.str());
+  }
+
+  inline void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+  {
+  }
+
+  inline void DeleteShader(GLuint shader)
+  {
+    std::stringstream out;
+    out << shader;
+    mShaderTrace.PushCall("DeleteShader", out.str());
+  }
+
+  inline void DeleteTextures(GLsizei n, const GLuint* textures)
+  {
+    std::stringstream out;
+    out << n << ", " << textures << " = [" ;
+
+    for(GLsizei i=0; i<n; i++)
+    {
+      out << textures[i] << ", " ;
+      mDeletedTextureIds.push_back(textures[i]);
+    }
+    out << "]";
+    mTextureTrace.PushCall("DeleteTextures", out.str());
+  }
+
+  inline bool CheckNoTexturesDeleted()
+  {
+    return mDeletedTextureIds.size() == 0;
+  }
+
+  inline bool CheckTextureDeleted( GLuint textureId )
+  {
+    bool found = false;
+
+    for(std::vector<GLuint>::iterator iter=mDeletedTextureIds.begin(); iter != mDeletedTextureIds.end(); ++iter)
+    {
+      if(*iter == textureId)
+      {
+        found = true;
+        break;
+      }
+    }
+    return found;
+  }
+
+  inline void ClearDeletedTextures()
+  {
+    mDeletedTextureIds.clear();
+  }
+
+  inline void DepthFunc(GLenum func)
+  {
+  }
+
+  inline void DepthMask(GLboolean flag)
+  {
+  }
+
+  inline void DepthRangef(GLclampf zNear, GLclampf zFar)
+  {
+  }
+
+  inline void DetachShader(GLuint program, GLuint shader)
+  {
+    std::stringstream out;
+    out << program << ", " << shader;
+    mShaderTrace.PushCall("DetachShader", out.str());
+  }
+
+  inline void Disable(GLenum cap)
+  {
+    std::stringstream out;
+    out << cap;
+    mCullFaceTrace.PushCall("Disable", out.str());
+  }
+
+  inline void DisableVertexAttribArray(GLuint index)
+  {
+    SetVertexAttribArray( index, false );
+  }
+
+  inline void DrawArrays(GLenum mode, GLint first, GLsizei count)
+  {
+    std::stringstream out;
+    out << mode << ", " << first << ", " << count;
+    mDrawTrace.PushCall("DrawArrays", out.str());
+  }
+
+  inline void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
+  {
+    std::stringstream out;
+    out << mode << ", " << count << ", " << type << ", indices";
+    mDrawTrace.PushCall("DrawElements", out.str());
+  }
+
+  inline void Enable(GLenum cap)
+  {
+    std::stringstream out;
+    out << cap;
+    mCullFaceTrace.PushCall("Enable", out.str());
+  }
+
+  inline void EnableVertexAttribArray(GLuint index)
+  {
+    SetVertexAttribArray( index, true);
+  }
+
+  inline void Finish(void)
+  {
+  }
+
+  inline void Flush(void)
+  {
+  }
+
+  inline void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+  {
+    if (attachment == GL_DEPTH_ATTACHMENT)
+    {
+      mFramebufferDepthAttached = true;
+    }
+    else if (attachment == GL_STENCIL_ATTACHMENT)
+    {
+      mFramebufferStencilAttached = true;
+    }
+  }
+
+  inline void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+  {
+    //Add 100 bit;
+    mFramebufferStatus |= 4;
+
+    //We check 4 attachment colors
+    if ((attachment == GL_COLOR_ATTACHMENT0) || (attachment == GL_COLOR_ATTACHMENT1) || (attachment == GL_COLOR_ATTACHMENT2)  || (attachment == GL_COLOR_ATTACHMENT4))
+    {
+      mFramebufferColorAttached = true;
+    }
+  }
+
+  inline void FrontFace(GLenum mode)
+  {
+  }
+
+  inline void GenBuffers(GLsizei n, GLuint* buffers)
+  {
+    // avoids an assert in GpuBuffers
+    *buffers = 1u;
+  }
+
+  inline void GenerateMipmap(GLenum target)
+  {
+  }
+
+  inline void GenFramebuffers(GLsizei n, GLuint* framebuffers)
+  {
+    for( int i = 0; i < n; i++ )
+    {
+      framebuffers[i] = i + 1;
+    }
+
+    //Add 001 bit, this function needs to be called the first one in the chain
+    mFramebufferStatus = 1;
+  }
+
+  inline void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+  {
+    for( int i = 0; i < n; i++ )
+    {
+      renderbuffers[i] = i + 1;
+    }
+  }
+
+  /**
+   * This method can be used by test cases, to manipulate the texture IDs generated by GenTextures.
+   * @param[in] ids A vector containing the next IDs to be generated
+   */
+  inline void SetNextTextureIds( const std::vector<GLuint>& ids )
+  {
+    mNextTextureIds = ids;
+  }
+
+  inline const std::vector<GLuint>& GetNextTextureIds()
+  {
+    return mNextTextureIds;
+  }
+
+  inline void GenTextures(GLsizei n, GLuint* textures)
+  {
+    for( int i=0; i<n; ++i )
+    {
+      if( !mNextTextureIds.empty() )
+      {
+        *(textures+i) = mNextTextureIds[0];
+        mNextTextureIds.erase( mNextTextureIds.begin() );
+      }
+      else
+      {
+        *(textures+i) = ++mLastAutoTextureIdUsed;
+      }
+    }
+
+    std::stringstream out;
+    for(int i=0; i<n; i++)
+    {
+      out << textures[i];
+      if(i<n-1)
+      {
+        out << ", ";
+      }
+    }
+    mTextureTrace.PushCall("GenTextures", out.str());
+  }
+
+  inline void GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+  {
+  }
+
+  inline void GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name)
+  {
+  }
+
+  inline void GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+  {
+  }
+
+  inline int  GetAttribLocation(GLuint program, const char* name)
+  {
+    std::string attribName(name);
+
+    for( unsigned int i = 0; i < ATTRIB_TYPE_LAST; ++i )
+    {
+      if( mStdAttribs[i] == attribName )
+      {
+        return i;
+      }
+    }
+
+    // 0 is a valid location
+    return 0;
+  }
+
+  inline void GetBooleanv(GLenum pname, GLboolean* params)
+  {
+  }
+
+  inline void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+  }
+
+  inline GLenum GetError(void)
+  {
+    return mGetErrorResult;
+  }
+
+  inline void GetFloatv(GLenum pname, GLfloat* params)
+  {
+  }
+
+  inline void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetIntegerv(GLenum pname, GLint* params)
+  {
+    switch( pname )
+    {
+      case GL_MAX_TEXTURE_SIZE:
+        *params = 2048;
+        break;
+      case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
+        *params = 8;
+        break;
+      case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
+        *params = mNumBinaryFormats;
+        break;
+      case GL_PROGRAM_BINARY_FORMATS_OES:
+        *params = mBinaryFormats;
+        break;
+    }
+  }
+
+  inline void GetProgramiv(GLuint program, GLenum pname, GLint* params)
+  {
+    switch( pname ) {
+      case GL_LINK_STATUS:
+        *params = mLinkStatus;
+        break;
+      case GL_PROGRAM_BINARY_LENGTH_OES:
+        *params = mProgramBinaryLength;
+        break;
+    }
+  }
+
+  inline void GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, char* infolog)
+  {
+  }
+
+
+  inline void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetShaderiv(GLuint shader, GLenum pname, GLint* params)
+  {
+    switch( pname ) {
+      case GL_COMPILE_STATUS:
+        *params = mCompileStatus;
+        break;
+    }
+  }
+
+  inline void GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog)
+  {
+  }
+
+  inline void GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+  {
+  }
+
+  inline const GLubyte* GetString(GLenum name)
+  {
+    return mGetStringResult;
+  }
+
+  inline void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+  {
+  }
+
+  inline void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetUniformfv(GLuint program, GLint location, GLfloat* params)
+  {
+  }
+
+  inline void GetUniformiv(GLuint program, GLint location, GLint* params)
+  {
+  }
+
+  inline GLint GetUniformLocation(GLuint program, const char* name)
+  {
+    ProgramUniformMap::iterator it = mUniforms.find(program);
+    if( it == mUniforms.end() )
+    {
+      // Not a valid program ID
+      mGetErrorResult = GL_INVALID_OPERATION;
+      return -1;
+    }
+
+    UniformIDMap& uniformIDs = it->second;
+    UniformIDMap::iterator it2 = uniformIDs.find( name );
+    if( it2 == uniformIDs.end() )
+    {
+      // Uniform not found, so add it...
+      uniformIDs[name] = ++mLastUniformIdUsed;
+      return mLastUniformIdUsed;
+    }
+
+    return it2->second;
+  }
+
+  inline void GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+  {
+  }
+
+  inline void GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetVertexAttribPointerv(GLuint index, GLenum pname, void** pointer)
+  {
+  }
+
+  inline void Hint(GLenum target, GLenum mode)
+  {
+  }
+
+  inline GLboolean IsBuffer(GLuint buffer)
+  {
+    return mIsBufferResult;
+  }
+
+  inline GLboolean IsEnabled(GLenum cap)
+  {
+    return mIsEnabledResult;
+  }
+
+  inline GLboolean IsFramebuffer(GLuint framebuffer)
+  {
+    return mIsFramebufferResult;
+  }
+
+  inline GLboolean IsProgram(GLuint program)
+  {
+    return mIsProgramResult;
+  }
+
+  inline GLboolean IsRenderbuffer(GLuint renderbuffer)
+  {
+    return mIsRenderbufferResult;
+  }
+
+  inline GLboolean IsShader(GLuint shader)
+  {
+    return mIsShaderResult;
+  }
+
+  inline GLboolean IsTexture(GLuint texture)
+  {
+    return mIsTextureResult;
+  }
+
+  inline void LineWidth(GLfloat width)
+  {
+  }
+
+  inline void LinkProgram(GLuint program)
+  {
+    std::stringstream out;
+    out << program;
+    mShaderTrace.PushCall("LinkProgram", out.str());
+  }
+
+  inline void PixelStorei(GLenum pname, GLint param)
+  {
+  }
+
+  inline void PolygonOffset(GLfloat factor, GLfloat units)
+  {
+  }
+
+  inline void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+  {
+  }
+
+  inline void ReleaseShaderCompiler(void)
+  {
+  }
+
+  inline void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline void SampleCoverage(GLclampf value, GLboolean invert)
+  {
+  }
+
+  inline void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+    mScissorParams.x = x;
+    mScissorParams.y = y;
+    mScissorParams.width = width;
+    mScissorParams.height = height;
+  }
+
+  inline void ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length)
+  {
+  }
+
+  inline void ShaderSource(GLuint shader, GLsizei count, const char** string, const GLint* length)
+  {
+    std::string stringBuilder;
+    for(int i = 0; i < count; ++i)
+    {
+      stringBuilder += string[i];
+    }
+    mShaderSources[shader] = stringBuilder;
+    mLastShaderCompiled = shader;
+  }
+
+  inline void GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, char* source)
+  {
+    const std::string shaderSource = mShaderSources[shader];
+    if( static_cast<int>(shaderSource.length()) < bufsize )
+    {
+      strcpy(source, shaderSource.c_str());
+      *length = shaderSource.length();
+    }
+    else
+    {
+      *length = bufsize -1;
+      strncpy(source, shaderSource.c_str(), *length);
+      source[*length] = 0x0;
+    }
+  }
+
+  inline std::string GetShaderSource(GLuint shader)
+  {
+    return mShaderSources[shader];
+  }
+
+  inline void StencilFunc(GLenum func, GLint ref, GLuint mask)
+  {
+  }
+
+  inline void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+  {
+  }
+
+  inline void StencilMask(GLuint mask)
+  {
+  }
+
+  inline void StencilMaskSeparate(GLenum face, GLuint mask)
+  {
+  }
+
+  inline void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+  {
+  }
+
+  inline void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+  {
+  }
+
+  inline void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels)
+  {
+    std::stringstream out;
+    out << width << ", " << height;
+    mTextureTrace.PushCall("TexImage2D", out.str());
+  }
+
+  inline void TexParameterf(GLenum target, GLenum pname, GLfloat param)
+  {
+    std::stringstream out;
+    out << target << ", " << pname << ", " << param;
+    mTexParamaterTrace.PushCall("TexParameterf", out.str());
+  }
+
+  inline void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+  {
+    std::stringstream out;
+    out << target << ", " << pname << ", " << params[0];
+    mTexParamaterTrace.PushCall("TexParameterfv", out.str());
+  }
+
+  inline void TexParameteri(GLenum target, GLenum pname, GLint param)
+  {
+    std::stringstream out;
+    out << target << ", " << pname << ", " << param;
+    mTexParamaterTrace.PushCall("TexParameteri", out.str());
+  }
+
+  inline void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
+  {
+    std::stringstream out;
+    out << target << ", " << pname << ", " << params[0];
+    mTexParamaterTrace.PushCall("TexParameteriv", out.str());
+  }
+
+  inline void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels)
+  {
+    std::stringstream out;
+    out << xoffset << ", " << yoffset << ", " << width << ", " << height;
+    mTextureTrace.PushCall("TexSubImage2D", out.str());
+  }
+
+  inline void Uniform1f(GLint location, GLfloat x)
+  {
+    if( ! mProgramUniforms1f.SetUniformValue( mCurrentProgram, location, x ) )
+    {
+      mGetErrorResult = GL_INVALID_OPERATION;
+    }
+  }
+
+  inline void Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniforms1f.SetUniformValue( mCurrentProgram, location, v[i] ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void Uniform1i(GLint location, GLint x)
+  {
+    if( ! mProgramUniforms1i.SetUniformValue( mCurrentProgram, location, x ) )
+    {
+      mGetErrorResult = GL_INVALID_OPERATION;
+    }
+  }
+
+  inline void Uniform1iv(GLint location, GLsizei count, const GLint* v)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniforms1i.SetUniformValue( mCurrentProgram,
+                                                 location,
+                                                 v[i] ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void Uniform2f(GLint location, GLfloat x, GLfloat y)
+  {
+    if( ! mProgramUniforms2f.SetUniformValue( mCurrentProgram,
+                                               location,
+                                               Vector2( x, y ) ) )
+    {
+      mGetErrorResult = GL_INVALID_OPERATION;
+    }
+  }
+
+  inline void Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniforms2f.SetUniformValue( mCurrentProgram,
+                                                 location,
+                                                 Vector2( v[2*i], v[2*i+1] ) ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void Uniform2i(GLint location, GLint x, GLint y)
+  {
+  }
+
+  inline void Uniform2iv(GLint location, GLsizei count, const GLint* v)
+  {
+  }
+
+  inline void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+  {
+    if( ! mProgramUniforms3f.SetUniformValue( mCurrentProgram,
+                                               location,
+                                               Vector3( x, y, z ) ) )
+    {
+      mGetErrorResult = GL_INVALID_OPERATION;
+    }
+  }
+
+  inline void Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniforms3f.SetUniformValue(
+          mCurrentProgram,
+          location,
+          Vector3( v[3*i], v[3*i+1], v[3*i+2] ) ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void Uniform3i(GLint location, GLint x, GLint y, GLint z)
+  {
+  }
+
+  inline void Uniform3iv(GLint location, GLsizei count, const GLint* v)
+  {
+  }
+
+  inline void Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+  {
+    if( ! mProgramUniforms4f.SetUniformValue( mCurrentProgram,
+                                              location,
+                                              Vector4( x, y, z, w ) ) )
+    {
+      mGetErrorResult = GL_INVALID_OPERATION;
+    }
+  }
+
+  inline void Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniforms4f.SetUniformValue(
+          mCurrentProgram,
+          location,
+          Vector4( v[4*i], v[4*i+1], v[4*i+2], v[4*i+3] ) ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+  {
+  }
+
+  inline void Uniform4iv(GLint location, GLsizei count, const GLint* v)
+  {
+  }
+
+  inline void UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniformsMat3.SetUniformValue(
+            mCurrentProgram,
+            location,
+            Matrix3( value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], value[8] ) ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+    for( int i = 0; i < count; ++i )
+    {
+      if( ! mProgramUniformsMat4.SetUniformValue(
+          mCurrentProgram,
+          location,
+          Matrix( value ) ) )
+      {
+        mGetErrorResult = GL_INVALID_OPERATION;
+        break;
+      }
+    }
+  }
+
+  inline void UseProgram(GLuint program)
+  {
+    mCurrentProgram = program;
+  }
+
+  inline void ValidateProgram(GLuint program)
+  {
+  }
+
+  inline void VertexAttrib1f(GLuint indx, GLfloat x)
+  {
+  }
+
+  inline void VertexAttrib1fv(GLuint indx, const GLfloat* values)
+  {
+  }
+
+  inline void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
+  {
+  }
+
+  inline void VertexAttrib2fv(GLuint indx, const GLfloat* values)
+  {
+  }
+
+  inline void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
+  {
+  }
+
+  inline void VertexAttrib3fv(GLuint indx, const GLfloat* values)
+  {
+  }
+
+  inline void VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+  {
+  }
+
+  inline void VertexAttrib4fv(GLuint indx, const GLfloat* values)
+  {
+  }
+
+  inline void VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr)
+  {
+  }
+
+  inline void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+  }
+
+  /* OpenGL ES 3.0 */
+
+  inline void ReadBuffer(GLenum mode)
+  {
+  }
+
+  inline void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
+  {
+  }
+
+  inline void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+  {
+  }
+
+  inline void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+  {
+  }
+
+  inline void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+  {
+  }
+
+  inline void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+  {
+  }
+
+  inline void GenQueries(GLsizei n, GLuint* ids)
+  {
+  }
+
+  inline void DeleteQueries(GLsizei n, const GLuint* ids)
+  {
+  }
+
+  inline GLboolean IsQuery(GLuint id)
+  {
+    return false;
+  }
+
+  inline void BeginQuery(GLenum target, GLuint id)
+  {
+  }
+
+  inline void EndQuery(GLenum target)
+  {
+  }
+
+  inline void GetQueryiv(GLenum target, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+  {
+  }
+
+  inline GLboolean UnmapBuffer(GLenum target)
+  {
+    return false;
+  }
+
+  inline void GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+  {
+  }
+
+  inline void DrawBuffers(GLsizei n, const GLenum* bufs)
+  {
+  }
+
+  inline void UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+  {
+  }
+
+  inline void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+  {
+  }
+
+  inline void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+  {
+  }
+
+  inline GLvoid* MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+  {
+    return NULL;
+  }
+
+  inline void FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+  {
+  }
+
+  inline void BindVertexArray(GLuint array)
+  {
+  }
+
+  inline void DeleteVertexArrays(GLsizei n, const GLuint* arrays)
+  {
+  }
+
+  inline void GenVertexArrays(GLsizei n, GLuint* arrays)
+  {
+  }
+
+  inline GLboolean IsVertexArray(GLuint array)
+  {
+    return false;
+  }
+
+  inline void GetIntegeri_v(GLenum target, GLuint index, GLint* data)
+  {
+  }
+
+  inline void BeginTransformFeedback(GLenum primitiveMode)
+  {
+  }
+
+  inline void EndTransformFeedback(void)
+  {
+  }
+
+  inline void BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+  {
+  }
+
+  inline void BindBufferBase(GLenum target, GLuint index, GLuint buffer)
+  {
+  }
+
+  inline void TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
+  {
+  }
+
+  inline void GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
+  {
+  }
+
+  inline void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
+  {
+  }
+
+  inline void GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
+  {
+  }
+
+  inline void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+  {
+  }
+
+  inline void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+  {
+  }
+
+  inline void VertexAttribI4iv(GLuint index, const GLint* v)
+  {
+  }
+
+  inline void VertexAttribI4uiv(GLuint index, const GLuint* v)
+  {
+  }
+
+  inline void GetUniformuiv(GLuint program, GLint location, GLuint* params)
+  {
+  }
+
+  inline GLint GetFragDataLocation(GLuint program, const GLchar *name)
+  {
+    return -1;
+  }
+
+  inline void Uniform1ui(GLint location, GLuint v0)
+  {
+  }
+
+  inline void Uniform2ui(GLint location, GLuint v0, GLuint v1)
+  {
+  }
+
+  inline void Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+  {
+  }
+
+  inline void Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+  {
+  }
+
+  inline void Uniform1uiv(GLint location, GLsizei count, const GLuint* value)
+  {
+  }
+
+  inline void Uniform2uiv(GLint location, GLsizei count, const GLuint* value)
+  {
+  }
+
+  inline void Uniform3uiv(GLint location, GLsizei count, const GLuint* value)
+  {
+  }
+
+  inline void Uniform4uiv(GLint location, GLsizei count, const GLuint* value)
+  {
+  }
+
+  inline void ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
+  {
+  }
+
+  inline void ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
+  {
+  }
+
+  inline void ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+  {
+  }
+
+  inline void ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+  {
+  }
+
+  inline const GLubyte* GetStringi(GLenum name, GLuint index)
+  {
+    return NULL;
+  }
+
+  inline void CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+  {
+  }
+
+  inline void GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
+  {
+  }
+
+  inline void GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
+  {
+  }
+
+  inline GLuint GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
+  {
+    return GL_INVALID_INDEX;
+  }
+
+  inline void GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
+  {
+  }
+
+  inline void UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+  {
+  }
+
+  inline void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+  {
+  }
+
+  inline void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
+  {
+  }
+
+  inline GLsync FenceSync(GLenum condition, GLbitfield flags)
+  {
+    return NULL;
+  }
+
+  inline GLboolean IsSync(GLsync sync)
+  {
+    return false;
+  }
+
+  inline void DeleteSync(GLsync sync)
+  {
+  }
+
+  inline GLenum ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+  {
+    return 0;
+  }
+
+  inline void WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+  {
+  }
+
+  inline void GetInteger64v(GLenum pname, GLint64* params)
+  {
+  }
+
+  inline void GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
+  {
+  }
+
+  inline void GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
+  {
+  }
+
+  inline void GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
+  {
+  }
+
+  inline void GenSamplers(GLsizei count, GLuint* samplers)
+  {
+  }
+
+  inline void DeleteSamplers(GLsizei count, const GLuint* samplers)
+  {
+  }
+
+  inline GLboolean IsSampler(GLuint sampler)
+  {
+    return false;
+  }
+
+  inline void BindSampler(GLuint unit, GLuint sampler)
+  {
+  }
+
+  inline void SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+  {
+  }
+
+  inline void SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
+  {
+  }
+
+  inline void SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+  {
+  }
+
+  inline void SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
+  {
+  }
+
+  inline void GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
+  {
+  }
+
+  inline void GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+  {
+  }
+
+  inline void VertexAttribDivisor(GLuint index, GLuint divisor)
+  {
+  }
+
+  inline void BindTransformFeedback(GLenum target, GLuint id)
+  {
+  }
+
+  inline void DeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+  {
+  }
+
+  inline void GenTransformFeedbacks(GLsizei n, GLuint* ids)
+  {
+  }
+
+  inline GLboolean IsTransformFeedback(GLuint id)
+  {
+    return false;
+  }
+
+  inline void PauseTransformFeedback(void)
+  {
+  }
+
+  inline void ResumeTransformFeedback(void)
+  {
+  }
+
+  inline void GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+  {
+    mGetProgramBinaryCalled = true;
+  }
+
+  inline void ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+  {
+  }
+
+  inline void ProgramParameteri(GLuint program, GLenum pname, GLint value)
+  {
+  }
+
+  inline void InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+  {
+  }
+
+  inline void InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline void TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+  {
+  }
+
+  inline void TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+  {
+  }
+
+  inline void GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+  {
+  }
+
+public: // TEST FUNCTIONS
+  inline void SetCompileStatus( GLuint value ) { mCompileStatus = value; }
+  inline void SetLinkStatus( GLuint value ) { mLinkStatus = value; }
+  inline void SetGetAttribLocationResult(  int result) { mGetAttribLocationResult = result; }
+  inline void SetGetErrorResult(  GLenum result) { mGetErrorResult = result; }
+  inline void SetGetStringResult(  GLubyte* result) { mGetStringResult = result; }
+  inline void SetIsBufferResult(  GLboolean result) { mIsBufferResult = result; }
+  inline void SetIsEnabledResult(  GLboolean result) { mIsEnabledResult = result; }
+  inline void SetIsFramebufferResult(  GLboolean result) { mIsFramebufferResult = result; }
+  inline void SetIsProgramResult(  GLboolean result) { mIsProgramResult = result; }
+  inline void SetIsRenderbufferResult(  GLboolean result) { mIsRenderbufferResult = result; }
+  inline void SetIsShaderResult(  GLboolean result) { mIsShaderResult = result; }
+  inline void SetIsTextureResult(  GLboolean result) { mIsTextureResult = result; }
+  inline void SetCheckFramebufferStatusResult(  GLenum result) { mCheckFramebufferStatusResult = result; }
+  inline void SetNumBinaryFormats( GLint numFormats ) { mNumBinaryFormats = numFormats; }
+  inline void SetBinaryFormats( GLint binaryFormats ) { mBinaryFormats = binaryFormats; }
+  inline void SetProgramBinaryLength( GLint length ) { mProgramBinaryLength = length; }
+
+  inline bool GetVertexAttribArrayState(GLuint index)
+  {
+    if( index >= MAX_ATTRIBUTE_CACHE_SIZE )
+    {
+      // out of range
+      return false;
+    }
+    return mVertexAttribArrayState[ index ];
+  }
+  inline void ClearVertexAttribArrayChanged() {  mVertexAttribArrayChanged = false; }
+  inline bool GetVertexAttribArrayChanged()  { return mVertexAttribArrayChanged; }
+
+  //Methods for CullFace verification
+  inline void EnableCullFaceCallTrace(bool enable) { mCullFaceTrace.Enable(enable); }
+  inline void ResetCullFaceCallStack() { mCullFaceTrace.Reset(); }
+  inline TraceCallStack& GetCullFaceTrace() { return mCullFaceTrace; }
+
+  //Methods for Shader verification
+  inline void EnableShaderCallTrace(bool enable) { mShaderTrace.Enable(enable); }
+  inline void ResetShaderCallStack() { mShaderTrace.Reset(); }
+  inline TraceCallStack& GetShaderTrace() { return mShaderTrace; }
+
+  //Methods for Texture verification
+  inline void EnableTextureCallTrace(bool enable) { mTextureTrace.Enable(enable); }
+  inline void ResetTextureCallStack() { mTextureTrace.Reset(); }
+  inline TraceCallStack& GetTextureTrace() { return mTextureTrace; }
+
+  //Methods for Texture verification
+  inline void EnableTexParameterCallTrace(bool enable) { mTexParamaterTrace.Enable(enable); }
+  inline void ResetTexParameterCallStack() { mTexParamaterTrace.Reset(); }
+  inline TraceCallStack& GetTexParameterTrace() { return mTexParamaterTrace; }
+
+  //Methods for Draw verification
+  inline void EnableDrawCallTrace(bool enable) { mDrawTrace.Enable(enable); }
+  inline void ResetDrawCallStack() { mDrawTrace.Reset(); }
+  inline TraceCallStack& GetDrawTrace() { return mDrawTrace; }
+
+  template <typename T>
+  inline bool GetUniformValue( const char* name, T& value ) const
+  {
+    for( ProgramUniformMap::const_iterator program_it = mUniforms.begin();
+          program_it != mUniforms.end();
+          ++program_it )
+    {
+      const UniformIDMap &uniformIDs = program_it->second;
+
+      UniformIDMap::const_iterator uniform_it = uniformIDs.find( name );
+      if( uniform_it != uniformIDs.end() )
+      {
+        // found one matching uniform name, lets check the value...
+        GLuint programId = program_it->first;
+        GLint uniformId = uniform_it->second;
+
+        const ProgramUniformValue<T> &mProgramUniforms = GetProgramUniformsForType( value );
+        return mProgramUniforms.GetUniformValue( programId, uniformId, value );
+      }
+    }
+    return false;
+  }
+
+
+  template <typename T>
+  inline bool CheckUniformValue( const char* name, const T& value ) const
+  {
+    for( ProgramUniformMap::const_iterator program_it = mUniforms.begin();
+          program_it != mUniforms.end();
+          ++program_it )
+    {
+      const UniformIDMap &uniformIDs = program_it->second;
+
+      UniformIDMap::const_iterator uniform_it = uniformIDs.find( name );
+      if( uniform_it != uniformIDs.end() )
+      {
+        // found one matching uniform name, lets check the value...
+        GLuint programId = program_it->first;
+        GLint uniformId = uniform_it->second;
+
+        const ProgramUniformValue<T> &mProgramUniforms = GetProgramUniformsForType( value );
+        if( mProgramUniforms.CheckUniformValue( programId, uniformId, value ) )
+        {
+          // the value matches
+          return true;
+        }
+      }
+    }
+
+    fprintf(stderr, "Not found, printing possible values:\n" );
+    for( ProgramUniformMap::const_iterator program_it = mUniforms.begin();
+          program_it != mUniforms.end();
+          ++program_it )
+    {
+      const UniformIDMap &uniformIDs = program_it->second;
+
+      UniformIDMap::const_iterator uniform_it = uniformIDs.find( name );
+      if( uniform_it != uniformIDs.end() )
+      {
+        // found one matching uniform name, lets check the value...
+        GLuint programId = program_it->first;
+        GLint uniformId = uniform_it->second;
+
+        const ProgramUniformValue<T> &mProgramUniforms = GetProgramUniformsForType( value );
+        T origValue;
+        if ( mProgramUniforms.GetUniformValue(programId, uniformId, origValue) )
+        {
+          std::stringstream out;
+          out << uniform_it->first << ": " << origValue;
+          fprintf(stderr, "%s\n", out.str().c_str() );
+        }
+      }
+    }
+    return false;
+  }
+
+  template <typename T>
+  inline bool GetUniformValue( GLuint programId, GLuint uniformId, T& outValue) const
+  {
+    const ProgramUniformValue<T> &mProgramUniforms = GetProgramUniformsForType( outValue );
+    return mProgramUniforms.GetUniformValue( programId, uniformId, outValue );
+  }
+
+  inline bool GetUniformIds( const char* name, GLuint& programId, GLuint& uniformId ) const
+  {
+    for( ProgramUniformMap::const_iterator program_it = mUniforms.begin();
+          program_it != mUniforms.end();
+          ++program_it )
+    {
+      const UniformIDMap &uniformIDs = program_it->second;
+
+      UniformIDMap::const_iterator uniform_it = uniformIDs.find( name );
+      if( uniform_it != uniformIDs.end() )
+      {
+        programId = program_it->first;
+        uniformId = uniform_it->second;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  inline GLuint GetLastShaderCompiled() const
+  {
+    return mLastShaderCompiled;
+  }
+
+  inline GLuint GetLastProgramCreated() const
+  {
+    return mLastProgramIdUsed;
+  }
+
+  inline GLbitfield GetLastClearMask() const
+  {
+    return mLastClearBitMask;
+  }
+
+  enum AttribType
+  {
+    ATTRIB_UNKNOWN = -1,
+    ATTRIB_POSITION,
+    ATTRIB_NORMAL,
+    ATTRIB_TEXCOORD,
+    ATTRIB_COLOR,
+    ATTRIB_BONE_WEIGHTS,
+    ATTRIB_BONE_INDICES,
+    ATTRIB_TYPE_LAST
+  };
+
+  struct ScissorParams
+  {
+    GLint x;
+    GLint y;
+    GLsizei width;
+    GLsizei height;
+
+    ScissorParams() : x( 0 ), y( 0 ), width( 0 ), height( 0 ) { }
+  };
+
+  // Methods to check scissor tests
+  inline const ScissorParams& GetScissorParams() const { return mScissorParams; }
+
+  inline bool GetProgramBinaryCalled() const { return mGetProgramBinaryCalled; }
+
+  inline unsigned int GetClearCountCalled() const { return mClearCount; }
+
+  typedef std::vector<size_t> BufferDataCalls;
+  inline const BufferDataCalls& GetBufferDataCalls() const { return mBufferDataCalls; }
+  inline void ResetBufferDataCalls() { mBufferDataCalls.clear(); }
+
+  typedef std::vector<size_t> BufferSubDataCalls;
+  inline const BufferSubDataCalls& GetBufferSubDataCalls() const { return mBufferSubDataCalls; }
+  inline void ResetBufferSubDataCalls() { mBufferSubDataCalls.clear(); }
+
+private:
+  GLuint     mCurrentProgram;
+  GLuint     mCompileStatus;
+  BufferDataCalls mBufferDataCalls;
+  BufferSubDataCalls mBufferSubDataCalls;
+  GLuint     mLinkStatus;
+  GLint      mGetAttribLocationResult;
+  GLenum     mGetErrorResult;
+  GLubyte*   mGetStringResult;
+  GLboolean  mIsBufferResult;
+  GLboolean  mIsEnabledResult;
+  GLboolean  mIsFramebufferResult;
+  GLboolean  mIsProgramResult;
+  GLboolean  mIsRenderbufferResult;
+  GLboolean  mIsShaderResult;
+  GLboolean  mIsTextureResult;
+  GLenum     mActiveTextureUnit;
+  GLenum     mCheckFramebufferStatusResult;
+  GLint      mFramebufferStatus;
+  GLenum     mFramebufferColorAttached;
+  GLenum     mFramebufferDepthAttached;
+  GLenum     mFramebufferStencilAttached;
+  GLint      mNumBinaryFormats;
+  GLint      mBinaryFormats;
+  GLint      mProgramBinaryLength;
+  bool       mVertexAttribArrayState[MAX_ATTRIBUTE_CACHE_SIZE];
+  bool       mVertexAttribArrayChanged;                            // whether the vertex attrib array has been changed
+  bool       mGetProgramBinaryCalled;
+  typedef std::map< GLuint, std::string> ShaderSourceMap;
+  ShaderSourceMap mShaderSources;
+  GLuint     mLastShaderCompiled;
+  GLbitfield mLastClearBitMask;
+  unsigned int mClearCount;
+
+  Vector4 mLastBlendColor;
+  GLenum  mLastBlendEquationRgb;
+  GLenum  mLastBlendEquationAlpha;
+  GLenum  mLastBlendFuncSrcRgb;
+  GLenum  mLastBlendFuncDstRgb;
+  GLenum  mLastBlendFuncSrcAlpha;
+  GLenum  mLastBlendFuncDstAlpha;
+
+  // Data for manipulating the IDs returned by GenTextures
+  GLuint mLastAutoTextureIdUsed;
+  std::vector<GLuint> mNextTextureIds;
+  std::vector<GLuint> mDeletedTextureIds;
+  std::vector<GLuint> mBoundTextures;
+
+  struct ActiveTextureType
+  {
+    std::vector<GLuint> mBoundTextures;
+  };
+
+  ActiveTextureType mActiveTextures[ MIN_TEXTURE_UNIT_LIMIT ];
+
+  TraceCallStack mCullFaceTrace;
+  TraceCallStack mShaderTrace;
+  TraceCallStack mTextureTrace;
+  TraceCallStack mTexParamaterTrace;
+  TraceCallStack mDrawTrace;
+
+  // Shaders & Uniforms
+  GLuint mLastShaderIdUsed;
+  GLuint mLastProgramIdUsed;
+  GLuint mLastUniformIdUsed;
+  typedef std::map< std::string, GLint > UniformIDMap;
+  typedef std::map< GLuint, UniformIDMap > ProgramUniformMap;
+  ProgramUniformMap mUniforms;
+
+  template <typename T>
+  struct ProgramUniformValue : public std::map< GLuint, std::map< GLint, T > >
+  {
+  public:
+    typedef std::map< GLint, T > UniformValueMap;
+    typedef std::map< GLuint, UniformValueMap > Map;
+
+    bool SetUniformValue( GLuint program, GLuint uniform, const T& value )
+    {
+      if( program == 0 )
+      {
+        return false;
+      }
+
+      typename Map::iterator it = Map::find( program );
+      if( it == Map::end() )
+      {
+        // if its the first uniform for this program add it
+        std::pair< typename Map::iterator, bool > result =
+            Map::insert( typename Map::value_type( program, UniformValueMap() ) );
+        it = result.first;
+      }
+
+      UniformValueMap& uniforms = it->second;
+      uniforms[uniform] = value;
+
+      return true;
+    }
+
+    bool CheckUniformValue( GLuint program, GLuint uniform, const T& value ) const
+    {
+      T uniformValue;
+      if ( GetUniformValue( program, uniform, uniformValue ) )
+      {
+        return value == uniformValue;
+      }
+
+      return false;
+    }
+
+    bool GetUniformValue( GLuint program, GLuint uniform, T& value ) const
+    {
+      if( program == 0 )
+      {
+        return false;
+      }
+
+      typename Map::const_iterator it = Map::find( program );
+      if( it == Map::end() )
+      {
+        // Uniform values always initialised as 0
+        value = GetZero();
+        return true;
+      }
+
+      const UniformValueMap& uniforms = it->second;
+      typename UniformValueMap::const_iterator it2 = uniforms.find( uniform );
+      if( it2 == uniforms.end() )
+      {
+        // Uniform values always initialised as 0
+        value = GetZero();
+        return true;
+      }
+      value = it2->second;
+
+      return true;
+    }
+
+    T GetZero() const;
+  };
+  ProgramUniformValue<int> mProgramUniforms1i;
+  ProgramUniformValue<float> mProgramUniforms1f;
+  ProgramUniformValue<Vector2> mProgramUniforms2f;
+  ProgramUniformValue<Vector3> mProgramUniforms3f;
+  ProgramUniformValue<Vector4> mProgramUniforms4f;
+  ProgramUniformValue<Matrix> mProgramUniformsMat4;
+  ProgramUniformValue<Matrix3> mProgramUniformsMat3;
+
+  inline const ProgramUniformValue<int>& GetProgramUniformsForType( const int ) const
+  {
+    return mProgramUniforms1i;
+  }
+  inline const ProgramUniformValue<float>& GetProgramUniformsForType( const float ) const
+  {
+    return mProgramUniforms1f;
+  }
+  inline const ProgramUniformValue<Vector2>& GetProgramUniformsForType( const Vector2& ) const
+  {
+    return mProgramUniforms2f;
+  }
+  inline const ProgramUniformValue<Vector3>& GetProgramUniformsForType( const Vector3& ) const
+  {
+    return mProgramUniforms3f;
+  }
+  inline const ProgramUniformValue<Vector4>& GetProgramUniformsForType( const Vector4& ) const
+  {
+    return mProgramUniforms4f;
+  }
+  inline const ProgramUniformValue<Matrix>& GetProgramUniformsForType( const Matrix& ) const
+  {
+    return mProgramUniformsMat4;
+  }
+  inline const ProgramUniformValue<Matrix3>& GetProgramUniformsForType( const Matrix3& ) const
+  {
+    return mProgramUniformsMat3;
+  }
+  inline void SetVertexAttribArray(GLuint index, bool state)
+  {
+    if( index >= MAX_ATTRIBUTE_CACHE_SIZE )
+    {
+      // out of range
+      return;
+    }
+    mVertexAttribArrayState[ index ] = state;
+    mVertexAttribArrayChanged = true;
+  }
+
+  ScissorParams mScissorParams;
+};
+
+template <>
+inline int TestGlAbstraction::ProgramUniformValue<int>::GetZero() const
+{
+  return 0;
+}
+
+template <>
+inline float TestGlAbstraction::ProgramUniformValue<float>::GetZero() const
+{
+  return 0.0f;
+}
+
+template <>
+inline Vector2 TestGlAbstraction::ProgramUniformValue<Vector2>::GetZero() const
+{
+  return Vector2::ZERO;
+}
+
+template <>
+inline Vector3 TestGlAbstraction::ProgramUniformValue<Vector3>::GetZero() const
+{
+  return Vector3::ZERO;
+}
+
+template <>
+inline Vector4 TestGlAbstraction::ProgramUniformValue<Vector4>::GetZero() const
+{
+  return Vector4::ZERO;
+}
+
+template <>
+inline Matrix TestGlAbstraction::ProgramUniformValue<Matrix>::GetZero() const
+{
+  return Matrix();
+}
+
+template <>
+inline Matrix3 TestGlAbstraction::ProgramUniformValue<Matrix3>::GetZero() const
+{
+  return Matrix3( Matrix() );
+}
+
+} // namespace Dali
+
+bool BlendEnabled(const Dali::TraceCallStack& callStack);
+bool BlendDisabled(const Dali::TraceCallStack& callStack);
+
+
+
+
+#endif // __TEST_GL_ES_H__
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp
new file mode 100644 (file)
index 0000000..533355c
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-gl-sync-abstraction.h"
+
+namespace Dali
+{
+
+TestSyncObject::TestSyncObject(TraceCallStack& trace)
+: synced(false),
+  mTrace(trace)
+{
+}
+
+TestSyncObject::~TestSyncObject()
+{
+}
+
+bool TestSyncObject::IsSynced()
+{
+  mTrace.PushCall("SyncObject::IsSynced", ""); // Trace the method
+  return synced;
+}
+
+
+
+TestGlSyncAbstraction::TestGlSyncAbstraction()
+{
+  Initialize();
+}
+
+/**
+ * Destructor
+ */
+TestGlSyncAbstraction::~TestGlSyncAbstraction()
+{
+  for( SyncIter iter=mSyncObjects.begin(), end=mSyncObjects.end(); iter != end; ++iter )
+  {
+    delete *iter;
+  }
+}
+
+/**
+ * Initialize the sync objects - clear down the map
+ */
+void TestGlSyncAbstraction::Initialize()
+{
+  mSyncObjects.clear();
+}
+
+/**
+ * Create a sync object
+ * @return the sync object
+ */
+Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::CreateSyncObject( )
+{
+  mTrace.PushCall("CreateSyncObject", ""); // Trace the method
+
+  TestSyncObject* syncObject = new TestSyncObject(mTrace);
+  mSyncObjects.push_back( syncObject );
+  return syncObject;
+}
+
+/**
+ * Destroy a sync object
+ * @param[in] syncObject The object to destroy
+ */
+void TestGlSyncAbstraction::DestroySyncObject( Integration::GlSyncAbstraction::SyncObject* syncObject )
+{
+  std::stringstream out;
+  out << syncObject;
+  mTrace.PushCall("DestroySyncObject", out.str()); // Trace the method
+
+  for( SyncIter iter=mSyncObjects.begin(), end=mSyncObjects.end(); iter != end; ++iter )
+  {
+    if( *iter == syncObject )
+    {
+      delete *iter;
+      mSyncObjects.erase(iter);
+      break;
+    }
+  }
+}
+
+
+Integration::GlSyncAbstraction::SyncObject* TestGlSyncAbstraction::GetLastSyncObject( )
+{
+  if( !mSyncObjects.empty() )
+  {
+    return mSyncObjects.back();
+  }
+  return NULL;
+}
+
+/**
+ * Test method to trigger the object sync behaviour.
+ * @param[in]
+ * @param[in] sync The sync value to set
+ */
+void TestGlSyncAbstraction::SetObjectSynced( Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync )
+{
+  TestSyncObject* testSyncObject = static_cast<TestSyncObject*>(syncObject);
+  testSyncObject->synced = sync;
+}
+
+/**
+ * Turn trace on
+ */
+void TestGlSyncAbstraction::EnableTrace(bool enable) { mTrace.Enable(enable); }
+
+/**
+ * Reset the trace callstack
+ */
+void TestGlSyncAbstraction::ResetTrace() { mTrace.Reset(); }
+
+/**
+ * Get the trace object (allows test case to find methods on it)
+ */
+TraceCallStack& TestGlSyncAbstraction::GetTrace() { return mTrace; }
+
+
+} // Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.h
new file mode 100644 (file)
index 0000000..e233176
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __TEST_GL_SYNC_ABSTRACTION_H__
+#define __TEST_GL_SYNC_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <string>
+#include <map>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/core.h>
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+
+class DALI_IMPORT_API TestSyncObject : public Integration::GlSyncAbstraction::SyncObject
+{
+public:
+  TestSyncObject(TraceCallStack& trace);
+  ~TestSyncObject();
+  bool IsSynced();
+  bool synced;
+  TraceCallStack& mTrace;
+};
+
+/**
+ * Class to emulate the GL sync functions with tracing
+ */
+class DALI_IMPORT_API TestGlSyncAbstraction: public Integration::GlSyncAbstraction
+{
+public:
+  /**
+   * Constructor
+   */
+  TestGlSyncAbstraction();
+
+  /**
+   * Destructor
+   */
+  ~TestGlSyncAbstraction();
+
+  /**
+   * Initialize the sync objects - clear down the map
+   */
+  void Initialize();
+
+  /**
+   * Create a sync object
+   * @return the sync object
+   */
+  virtual Integration::GlSyncAbstraction::SyncObject* CreateSyncObject( );
+
+  /**
+   * Destroy a sync object
+   * @param[in] syncObject The object to destroy
+   */
+  virtual void DestroySyncObject( Integration::GlSyncAbstraction::SyncObject* syncObject );
+
+
+public: // TEST FUNCTIONS
+  Integration::GlSyncAbstraction::SyncObject* GetLastSyncObject( );
+
+  /**
+   * Test method to trigger the object sync behaviour.
+   * @param[in]
+   * @param[in] sync The sync value to set
+   */
+  void SetObjectSynced( Integration::GlSyncAbstraction::SyncObject* syncObject, bool sync );
+
+  /**
+   * Turn trace on
+   */
+  void EnableTrace(bool enable);
+
+  /**
+   * Reset the trace callstack
+   */
+  void ResetTrace();
+
+  /**
+   * Get the trace object (allows test case to find methods on it)
+   */
+  TraceCallStack& GetTrace();
+
+private:
+  typedef std::vector<TestSyncObject*>   SyncContainer;
+  typedef SyncContainer::iterator SyncIter;
+  SyncContainer mSyncObjects;  ///< The sync objects
+  TraceCallStack mTrace; ///< the trace call stack for testing
+};
+
+} // Dali
+
+#endif // __TEST_GL_SYNC_ABSTRACTION_H__
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-harness.cpp
new file mode 100644 (file)
index 0000000..55beebc
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test-harness.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
+#include <cstring>
+#include <testcase.h>
+
+namespace TestHarness
+{
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+namespace
+{
+const char* RED_COLOR="\e[1;31m";
+const char* GREEN_COLOR="\e[1;32m";
+const char* ASCII_RESET="\e[0m";
+const char* ASCII_BOLD="\e[1m";
+}
+
+
+int RunTestCase( struct ::testcase_s& testCase )
+{
+  int result = EXIT_STATUS_TESTCASE_FAILED;
+
+// dont want to catch exception as we want to be able to get
+// gdb stack trace from the first error
+// by default tests should all always pass with no exceptions
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+
+  return result;
+}
+
+
+int RunTestCaseInChildProcess( struct ::testcase_s& testCase, bool suppressOutput )
+{
+  int testResult = EXIT_STATUS_TESTCASE_FAILED;
+
+  int pid = fork();
+  if( pid == 0 ) // Child process
+  {
+    if( suppressOutput )
+    {
+      close(STDOUT_FILENO);
+      close(STDERR_FILENO);
+    }
+    exit( RunTestCase( testCase ) );
+  }
+  else if(pid == -1)
+  {
+    perror("fork");
+    exit(EXIT_STATUS_FORK_FAILED);
+  }
+  else // Parent process
+  {
+    int status = 0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(EXIT_STATUS_WAITPID_FAILED);
+    }
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", testCase.name, testResult);
+        }
+      }
+    }
+    else if(WIFSIGNALED(status) )
+    {
+      testResult = EXIT_STATUS_TESTCASE_ABORTED;
+
+#ifdef WCOREDUMP
+      if(WCOREDUMP(status))
+      {
+        printf("Test case %s failed: due to a crash\n", testCase.name);
+      }
+#endif
+      printf("Test case %s failed: exit with signal %s\n", testCase.name, strsignal(WTERMSIG(status)));
+    }
+    else if(WIFSTOPPED(status))
+    {
+      printf("Test case %s failed: stopped with signal %s\n", testCase.name, strsignal(WSTOPSIG(status)));
+    }
+  }
+  return testResult;
+}
+
+void OutputStatistics( int numPasses, int numFailures )
+{
+  const char* failureColor = GREEN_COLOR;
+  if( numFailures > 0 )
+  {
+    failureColor = RED_COLOR;
+  }
+  printf("\rNumber of test passes:   %s%4d (%5.2f%%)%s\n", ASCII_BOLD, numPasses, 100.0f * (float)numPasses / (numPasses+numFailures),  ASCII_RESET);
+  printf("%sNumber of test failures:%s %s%4d%s\n", failureColor, ASCII_RESET, ASCII_BOLD, numFailures, ASCII_RESET);
+
+}
+
+
+int RunAll(const char* processName, ::testcase tc_array[], bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+
+  // Run test cases in child process( to kill output/handle signals ), but run serially.
+  for( unsigned int i=0; tc_array[i].name; i++)
+  {
+    int result = RunTestCaseInChildProcess( tc_array[i], true );
+    if( result == 0 )
+    {
+      numPasses++;
+    }
+    else
+    {
+      numFailures++;
+    }
+  }
+
+  OutputStatistics(numPasses, numFailures);
+
+  return numFailures;
+}
+
+
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(  const char* processName, ::testcase tc_array[], bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
+
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+
+  while( tc_array[nextTestCase].name || numRunningChildren > 0)
+  {
+    // Create more children (up to the max number or til the end of the array)
+    while( numRunningChildren < MAX_NUM_CHILDREN && tc_array[nextTestCase].name )
+    {
+      int pid = fork();
+      if( pid == 0 ) // Child process
+      {
+        close(STDOUT_FILENO);
+        close(STDERR_FILENO);
+        exit( RunTestCase( tc_array[nextTestCase] ) );
+      }
+      else if(pid == -1)
+      {
+        perror("fork");
+        exit(EXIT_STATUS_FORK_FAILED);
+      }
+      else // Parent process
+      {
+        TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+        children[pid] = tc;
+        nextTestCase++;
+        numRunningChildren++;
+      }
+    }
+
+    // Wait for the next child to finish
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(EXIT_STATUS_WAITPID_FAILED);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
+
+    else if( WIFSIGNALED(status) || WIFSTOPPED(status))
+    {
+      status = WIFSIGNALED(status)?WTERMSIG(status):WSTOPSIG(status);
+
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %s\n", iter->second.testCaseName, strsignal(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %s\n", childPid, strsignal(status));
+        }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  OutputStatistics( numPasses, numFailures );
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      char* testCaseStrapline;
+      int numChars = asprintf(&testCaseStrapline, "Test case %s", tc_array[failedTestCases[i]].name );
+      printf("\n%s\n", testCaseStrapline);
+      for(int j=0; j<numChars; j++)
+      {
+        printf("=");
+      }
+      printf("\n");
+      RunTestCaseInChildProcess( tc_array[failedTestCases[i] ], false );
+    }
+  }
+
+  return numFailures;
+}
+
+
+
+int FindAndRunTestCase(::testcase tc_array[], const char* testCaseName)
+{
+  int result = EXIT_STATUS_TESTCASE_NOT_FOUND;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+void Usage(const char* program)
+{
+  printf("Usage: \n"
+         "   %s <testcase name>\t\t Execute a test case\n"
+         "   %s \t\t Execute all test cases in parallel\n"
+         "   %s -r\t\t Execute all test cases in parallel, rerunning failed test cases\n",
+         program, program, program);
+}
+
+} // namespace
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-harness.h b/automated-tests/src/dali/dali-test-suite-utils/test-harness.h
new file mode 100644 (file)
index 0000000..e6dc517
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef TEST_HARNESS_H
+#define TEST_HARNESS_H
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <testcase.h>
+
+namespace TestHarness
+{
+
+enum ExitStatus
+{
+  EXIT_STATUS_TESTCASE_SUCCEEDED,   // 0
+  EXIT_STATUS_TESTCASE_FAILED,      // 1
+  EXIT_STATUS_TESTCASE_ABORTED,     // 2
+  EXIT_STATUS_FORK_FAILED,          // 3
+  EXIT_STATUS_WAITPID_FAILED,       // 4
+  EXIT_STATUS_BAD_ARGUMENT,         // 5
+  EXIT_STATUS_TESTCASE_NOT_FOUND    // 6
+};
+
+const int MAX_NUM_CHILDREN(16);
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
+
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+/**
+ * Run a test case
+ * @param[in] testCase The Testkit-lite test case to run
+ */
+int RunTestCase( struct testcase_s& testCase );
+
+/**
+ * Run all test cases in parallel
+ * @param[in] processName The name of this process
+ * @param[in] tc_array The array of auto-generated testkit-lite test cases
+ * @param[in] reRunFailed True if failed test cases should be re-run
+ * @return 0 on success
+ */
+int RunAllInParallel(const char* processName, testcase tc_array[], bool reRunFailed);
+
+/**
+ * Run all test cases in serial
+ * @param[in] processName The name of this process
+ * @param[in] tc_array The array of auto-generated testkit-lite test cases
+ * @param[in] reRunFailed True if failed test cases should be re-run
+ * @return 0 on success
+ */
+int RunAll(const char* processName, testcase tc_array[], bool reRunFailed);
+
+/**
+ * Find the named test case in the given array, and run it
+ * @param[in] tc_array The array of auto-generated testkit-lite test cases
+ * @param[in] testCaseName the name of the test case to run
+ * @return 0 on success
+ */
+int FindAndRunTestCase(::testcase tc_array[], const char* testCaseName);
+
+/**
+ * Display usage instructions for this program
+ * @param[in] program The name of this program
+ */
+void Usage(const char* program);
+
+} // namespace TestHarness
+
+#endif
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h b/automated-tests/src/dali/dali-test-suite-utils/test-intrusive-ptr.h
new file mode 100644 (file)
index 0000000..03aafe3
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __TEST_INTRUSIVE_PTR_H__
+#define __TEST_INTRUSIVE_PTR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+namespace Dali
+{
+
+template <typename T>
+struct UtcCoverageIntrusivePtr
+{
+  typedef IntrusivePtr<T> (*Creator)();
+
+  void Check( Creator creator)
+  {
+    IntrusivePtr<T> a = creator();
+    IntrusivePtr<T> b = creator();
+
+    DALI_TEST_CHECK( a.Get() );
+
+    a.Reset();
+
+    T* pB = b.Detach();
+
+    a.Reset(pB);
+
+    DALI_TEST_CHECK(a);
+
+    a.Reset();
+
+  };
+
+};
+
+} // Dali
+
+#endif
+
+
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.cpp
new file mode 100644 (file)
index 0000000..d143d35
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include "test-application.h"
+#include "test-native-image.h"
+
+
+namespace Dali
+{
+
+TestNativeImagePointer TestNativeImage::New(int width, int height)
+{
+  return new TestNativeImage(width, height);
+}
+
+TestNativeImage::TestNativeImage(int width, int height)
+: mWidth(width), mHeight(height), mExtensionCreateCalls(0), mExtensionDestroyCalls(0), mTargetTextureCalls(0)
+{
+}
+
+TestNativeImage::~TestNativeImage()
+{
+}
+
+} // namespace dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-native-image.h b/automated-tests/src/dali/dali-test-suite-utils/test-native-image.h
new file mode 100644 (file)
index 0000000..4a39cb1
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __TEST_NATIVE_IMAGE_H__
+#define __TEST_NATIVE_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/native-image-interface.h>
+
+namespace Dali
+{
+class TestNativeImage;
+typedef IntrusivePtr<TestNativeImage> TestNativeImagePointer;
+
+class DALI_IMPORT_API TestNativeImage : public Dali::NativeImageInterface
+{
+public:
+  static TestNativeImagePointer New(int width, int height);
+
+  inline virtual bool GlExtensionCreate() { ++mExtensionCreateCalls; return true;};
+  inline virtual void GlExtensionDestroy() { ++mExtensionDestroyCalls; };
+  inline virtual GLenum TargetTexture() { ++mTargetTextureCalls; return 1;};
+  inline virtual void PrepareTexture() {};
+  inline virtual unsigned int GetWidth() const {return mWidth;};
+  inline virtual unsigned int GetHeight() const {return mHeight;};
+  inline virtual bool RequiresBlending() const {return true;};
+
+private:
+  TestNativeImage(int width, int height);
+  virtual ~TestNativeImage();
+
+  int mWidth;
+  int mHeight;
+public:
+  int mExtensionCreateCalls;
+  int mExtensionDestroyCalls;
+  int mTargetTextureCalls;
+};
+
+} // Dali
+
+#endif
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp
new file mode 100644 (file)
index 0000000..95082fd
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-platform-abstraction.h"
+#include "dali-test-suite-utils.h"
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+
+/**
+ * Constructor
+ */
+TestPlatformAbstraction::TestPlatformAbstraction()
+: mTrace(),
+  mSeconds( 0u ),
+  mMicroSeconds( 0u ),
+  mIsLoadingResult( false ),
+  mGetDefaultFontFamilyResult(),
+  mGetDefaultFontStyleResult(),
+  mGetDefaultFontSizeResult( 0 ),
+  mResources(),
+  mRequest( NULL ),
+  mSize(),
+  mClosestSize(),
+  mLoadFileResult(),
+  mSaveFileResult( false )
+{
+  Initialize();
+}
+
+/**
+ * Destructor
+ */
+TestPlatformAbstraction::~TestPlatformAbstraction()
+{
+}
+
+/**
+ * @copydoc PlatformAbstraction::GetTimeMicroseconds()
+ */
+void TestPlatformAbstraction::GetTimeMicroseconds(unsigned int &seconds, unsigned int &microSeconds)
+{
+  seconds = mSeconds;
+  microSeconds = mMicroSeconds;
+  mTrace.PushCall("GetTimeMicroseconds", "");
+}
+
+/**
+ * @copydoc PlatformAbstraction::Suspend()
+ */
+void TestPlatformAbstraction::Suspend()
+{
+  mTrace.PushCall("Suspend", "");
+}
+
+/**
+ * @copydoc PlatformAbstraction::Resume()
+ */
+void TestPlatformAbstraction::Resume()
+{
+  mTrace.PushCall("Resume", "");
+}
+
+ImageDimensions TestPlatformAbstraction::GetClosestImageSize( const std::string& filename,
+                                                              ImageDimensions size,
+                                                              FittingMode::Type fittingMode,
+                                                              SamplingMode::Type samplingMode,
+                                                              bool orientationCorrection )
+{
+  ImageDimensions closestSize = ImageDimensions( mClosestSize.x, mClosestSize.y );
+  mTrace.PushCall("GetClosestImageSize", "");
+  return closestSize;
+}
+
+ImageDimensions TestPlatformAbstraction::GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
+                                                   ImageDimensions size,
+                                                   FittingMode::Type fittingMode,
+                                                   SamplingMode::Type samplingMode,
+                                                   bool orientationCorrection )
+{
+  ImageDimensions closestSize = ImageDimensions( mClosestSize.x, mClosestSize.y );
+  mTrace.PushCall("GetClosestImageSize", "");
+  return closestSize;
+}
+
+
+/**
+ * @copydoc PlatformAbstraction::LoadResource()
+ */
+void TestPlatformAbstraction::LoadResource(const Integration::ResourceRequest& request)
+{
+  std::ostringstream out;
+  out << "Type:" << request.GetType()->id << ", Path: " << request.GetPath() << std::endl ;
+
+  mTrace.PushCall("LoadResource", out.str());
+  if(mRequest != NULL)
+  {
+    delete mRequest;
+    tet_infoline ("Warning: multiple resource requests not handled by Test Suite. You may see unexpected errors");
+  }
+  mRequest = new Integration::ResourceRequest(request);
+}
+
+Integration::ResourcePointer TestPlatformAbstraction::LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath )
+{
+  mTrace.PushCall("LoadResourceSynchronously", "");
+  return mResources.loadedResource;
+}
+
+Integration::BitmapPtr TestPlatformAbstraction::DecodeBuffer( const Integration::ResourceType& resourceType, uint8_t * buffer, size_t size )
+{
+  mTrace.PushCall("DecodeBuffer", "");
+  return Integration::BitmapPtr();
+}
+
+/**
+ * @copydoc PlatformAbstraction::CancelLoad()
+ */
+void TestPlatformAbstraction::CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId)
+{
+  mTrace.PushCall("CancelLoad", "");
+}
+
+/**
+ * @copydoc PlatformAbstraction::GetResources()
+ */
+void TestPlatformAbstraction::GetResources(Integration::ResourceCache& cache)
+{
+  mTrace.PushCall("GetResources", "");
+
+  if(mResources.loaded)
+  {
+    cache.LoadResponse( mResources.loadedId, mResources.loadedType, mResources.loadedResource, Integration::RESOURCE_COMPLETELY_LOADED );
+  }
+  if(mResources.loadFailed)
+  {
+    cache.LoadFailed( mResources.loadFailedId, mResources.loadFailure );
+  }
+}
+
+/**
+ * @copydoc PlatformAbstraction::IsLoading()
+ */
+bool TestPlatformAbstraction::IsLoading()
+{
+  mTrace.PushCall("IsLoading", "");
+  return mIsLoadingResult;
+}
+
+/**
+ * @copydoc PlatformAbstraction::GetDefaultFontSize()
+ */
+int TestPlatformAbstraction::GetDefaultFontSize() const
+{
+  mTrace.PushCall("GetDefaultFontSize", "");
+  return mGetDefaultFontSizeResult;
+}
+
+/**
+ * @copydoc PlatformAbstraction::SetDpi()
+ */
+void TestPlatformAbstraction::SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical)
+{
+  mTrace.PushCall("SetDpi", "");
+}
+
+/**
+ * @copydoc PlatformAbstraction::LoadFile()
+ */
+bool TestPlatformAbstraction::LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
+{
+  mTrace.PushCall("LoadFile", "");
+  if( mLoadFileResult.loadResult )
+  {
+    buffer = mLoadFileResult.buffer;
+  }
+
+  return mLoadFileResult.loadResult;
+}
+
+/**
+ * @copydoc PlatformAbstraction::LoadShaderBinaryFile()
+ */
+bool TestPlatformAbstraction::LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const
+{
+  mTrace.PushCall("LoadShaderBinaryFile", "");
+  if( mLoadFileResult.loadResult )
+  {
+    buffer = mLoadFileResult.buffer;
+  }
+
+  return mLoadFileResult.loadResult;
+}
+
+/**
+ * @copydoc PlatformAbstraction::SaveFile()
+ */
+bool TestPlatformAbstraction::SaveFile(const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const
+{
+  mTrace.PushCall("SaveFile", "");
+  return false;
+}
+
+void TestPlatformAbstraction::JoinLoaderThreads()
+{
+  mTrace.PushCall("JoinLoaderThreads", "");
+}
+
+/** Call this every test */
+void TestPlatformAbstraction::Initialize()
+{
+  mTrace.Reset();
+  mTrace.Enable(true);
+  memset(&mResources, 0, sizeof(Resources));
+  mSeconds=0;
+  mMicroSeconds=0;
+  mIsLoadingResult=false;
+
+  if(mRequest)
+  {
+    delete mRequest;
+    mRequest = 0;
+  }
+}
+
+bool TestPlatformAbstraction::WasCalled(TestFuncEnum func)
+{
+  switch(func)
+  {
+    case GetTimeMicrosecondsFunc:             return mTrace.FindMethod("GetTimeMicroseconds");
+    case SuspendFunc:                         return mTrace.FindMethod("Suspend");
+    case ResumeFunc:                          return mTrace.FindMethod("Resume");
+    case LoadResourceFunc:                    return mTrace.FindMethod("LoadResource");
+    case LoadFileFunc:                        return mTrace.FindMethod("LoadFile");
+    case SaveFileFunc:                        return mTrace.FindMethod("SaveFile");
+    case CancelLoadFunc:                      return mTrace.FindMethod("CancelLoad");
+    case GetResourcesFunc:                    return mTrace.FindMethod("GetResources");
+    case IsLoadingFunc:                       return mTrace.FindMethod("IsLoading");
+    case SetDpiFunc:                          return mTrace.FindMethod("SetDpi");
+    case JoinLoaderThreadsFunc:               return mTrace.FindMethod("JoinLoaderThreads");
+  }
+  return false;
+}
+
+void TestPlatformAbstraction::SetGetTimeMicrosecondsResult(size_t sec, size_t usec)
+{
+  mSeconds = sec;
+  mMicroSeconds = usec;
+}
+
+void TestPlatformAbstraction::IncrementGetTimeResult(size_t milliseconds)
+{
+  mMicroSeconds += milliseconds * 1000u;
+  unsigned int additionalSeconds = mMicroSeconds / 1000000u;
+
+  mSeconds += additionalSeconds;
+  mMicroSeconds -= additionalSeconds * 1000000u;
+}
+
+void TestPlatformAbstraction::SetIsLoadingResult(bool result)
+{
+  mIsLoadingResult = result;
+}
+
+void TestPlatformAbstraction::ClearReadyResources()
+{
+  memset(&mResources, 0, sizeof(Resources));
+}
+
+void TestPlatformAbstraction::SetResourceLoaded(Integration::ResourceId  loadedId,
+                                                Integration::ResourceTypeId  loadedType,
+                                                Integration::ResourcePointer loadedResource)
+{
+  mResources.loaded = true;
+  mResources.loadedId = loadedId;
+  mResources.loadedType = loadedType;
+  mResources.loadedResource = loadedResource;
+}
+
+void TestPlatformAbstraction::SetResourceLoadFailed(Integration::ResourceId  id,
+                                                    Integration::ResourceFailure failure)
+{
+  mResources.loadFailed = true;
+  mResources.loadFailedId = id;
+  mResources.loadFailure = failure;
+}
+
+Integration::ResourceRequest* TestPlatformAbstraction::GetRequest()
+{
+  return mRequest;
+}
+
+void TestPlatformAbstraction::DiscardRequest()
+{
+  delete mRequest;
+  mRequest = NULL;
+}
+
+void TestPlatformAbstraction::SetClosestImageSize(const Vector2& size)
+{
+  mClosestSize = size;
+}
+
+void TestPlatformAbstraction::SetLoadFileResult( bool result, Dali::Vector< unsigned char >& buffer )
+{
+  mLoadFileResult.loadResult = result;
+  if( result )
+  {
+    mLoadFileResult.buffer = buffer;
+  }
+}
+
+void TestPlatformAbstraction::SetSaveFileResult( bool result )
+{
+  mSaveFileResult = result;
+}
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.h
new file mode 100644 (file)
index 0000000..9408801
--- /dev/null
@@ -0,0 +1,236 @@
+#ifndef __DALI_TEST_PLATFORM_ABSTRACTION_H__
+#define __DALI_TEST_PLATFORM_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+#include <cstring>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/platform-abstraction.h>
+
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+
+/**
+ * Concrete implementation of the platform abstraction class.
+ */
+class DALI_IMPORT_API TestPlatformAbstraction : public Dali::Integration::PlatformAbstraction
+{
+
+public:
+
+  struct Resources
+  {
+    bool                         loaded;
+    Integration::ResourceId      loadedId;
+    Integration::ResourceTypeId  loadedType;
+    Integration::ResourcePointer loadedResource;
+
+    bool                         loadFailed;
+    Integration::ResourceId      loadFailedId;
+    Integration::ResourceFailure loadFailure;
+  };
+
+  struct LoadFileResult
+  {
+    inline LoadFileResult()
+    : loadResult(false)
+    {
+
+    }
+
+    bool loadResult;
+    Dali::Vector< unsigned char> buffer;
+  };
+
+  /**
+   * Constructor
+   */
+  TestPlatformAbstraction();
+
+  /**
+   * Destructor
+   */
+  virtual ~TestPlatformAbstraction();
+
+  /**
+   * @copydoc PlatformAbstraction::GetTimeMicroseconds()
+   */
+  virtual void GetTimeMicroseconds(unsigned int &seconds, unsigned int &microSeconds);
+
+  /**
+   * @copydoc PlatformAbstraction::Suspend()
+   */
+  virtual void Suspend();
+
+  /**
+   * @copydoc PlatformAbstraction::Resume()
+   */
+  virtual void Resume();
+
+  virtual ImageDimensions GetClosestImageSize( const std::string& filename,
+                                                 ImageDimensions size,
+                                                 FittingMode::Type fittingMode,
+                                                 SamplingMode::Type samplingMode,
+                                                 bool orientationCorrection );
+
+  virtual ImageDimensions GetClosestImageSize( Integration::ResourcePointer resourceBuffer,
+                                               ImageDimensions size,
+                                               FittingMode::Type fittingMode,
+                                               SamplingMode::Type samplingMode,
+                                               bool orientationCorrection );
+
+  /**
+   * @copydoc PlatformAbstraction::LoadResource()
+   */
+  virtual void LoadResource(const Integration::ResourceRequest& request);
+
+  /**
+   * @copydoc PlatformAbstraction::LoadResourceSynchronously()
+   */
+  virtual Integration::ResourcePointer LoadResourceSynchronously( const Integration::ResourceType& resourceType, const std::string& resourcePath );
+
+  /**
+   * @copydoc PlatformAbstraction::DecodeBuffer()
+   */
+  virtual Integration::BitmapPtr DecodeBuffer( const Dali::Integration::ResourceType& resourceType, uint8_t * buffer, size_t size );
+
+  /**
+   * @copydoc PlatformAbstraction::CancelLoad()
+   */
+  virtual void CancelLoad(Integration::ResourceId id, Integration::ResourceTypeId typeId);
+
+  /**
+   * @copydoc PlatformAbstraction::GetResources()
+   */
+  virtual void GetResources(Integration::ResourceCache& cache);
+
+  /**
+   * @copydoc PlatformAbstraction::IsLoading()
+   */
+  virtual bool IsLoading();
+
+  /**
+   * @copydoc PlatformAbstraction::GetDefaultFontSize()
+   */
+  virtual int GetDefaultFontSize() const;
+
+  /**
+   * @copydoc PlatformAbstraction::SetDpi()
+   */
+  virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical);
+
+  /**
+   * @copydoc PlatformAbstraction::LoadFile()
+   */
+  virtual bool LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const;
+
+  /**
+   * @copydoc PlatformAbstraction::LoadShaderBinaryFile()
+   */
+  virtual bool LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const;
+
+  /**
+   * @copydoc PlatformAbstraction::SaveFile()
+   */
+  virtual bool SaveFile(const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const;
+
+ /**
+  * @copydoc PlatformAbstraction::SaveShaderBinaryFile()
+  */
+  virtual bool SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const { return false; }
+
+  virtual void JoinLoaderThreads();
+
+public: // TEST FUNCTIONS
+
+  // Enumeration of Platform Abstraction methods
+  typedef enum
+  {
+    GetTimeMicrosecondsFunc,
+    SuspendFunc,
+    ResumeFunc,
+    LoadResourceFunc,
+    SaveFileFunc,
+    LoadFileFunc,
+    CancelLoadFunc,
+    GetResourcesFunc,
+    IsLoadingFunc,
+    SetDpiFunc,
+    JoinLoaderThreadsFunc,
+  } TestFuncEnum;
+
+  /** Call this every test */
+  void Initialize();
+
+  inline void EnableTrace(bool enable) { mTrace.Enable(enable); }
+  inline void ResetTrace() { mTrace.Reset(); }
+  inline TraceCallStack& GetTrace() { return mTrace; }
+
+  bool WasCalled(TestFuncEnum func);
+
+  void SetGetTimeMicrosecondsResult(size_t sec, size_t usec);
+
+  void IncrementGetTimeResult(size_t milliseconds);
+
+  void SetIsLoadingResult(bool result);
+
+  void ClearReadyResources();
+
+  void SetResourceLoaded(Integration::ResourceId  loadedId,
+                         Integration::ResourceTypeId  loadedType,
+                         Integration::ResourcePointer loadedResource);
+
+  void SetResourceLoadFailed(Integration::ResourceId  id,
+                             Integration::ResourceFailure failure);
+
+  Integration::ResourceRequest* GetRequest();
+
+  void DiscardRequest();
+
+  void SetClosestImageSize(const Vector2& size);
+
+  void SetLoadFileResult( bool result, Dali::Vector< unsigned char >& buffer );
+
+  void SetSaveFileResult( bool result );
+
+private:
+  mutable TraceCallStack        mTrace;
+  size_t                        mSeconds;
+  size_t                        mMicroSeconds;
+  bool                          mIsLoadingResult;
+  std::string                   mGetDefaultFontFamilyResult;
+  std::string                   mGetDefaultFontStyleResult;
+  int                           mGetDefaultFontSizeResult;
+  Resources                     mResources;
+  Integration::ResourceRequest* mRequest;
+  Vector2                       mSize;
+  Vector2                       mClosestSize;
+
+  LoadFileResult                mLoadFileResult;
+  bool                          mSaveFileResult;
+};
+
+} // Dali
+
+#endif /* __DALI_TET_PLATFORM_ABSTRACTION_H__ */
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp
new file mode 100644 (file)
index 0000000..f3b04ad
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-render-controller.h"
+
+namespace Dali
+{
+
+TestRenderController::TestRenderController()
+{
+  Initialize();
+}
+
+TestRenderController::~TestRenderController()
+{
+}
+
+void TestRenderController::RequestUpdate()
+{
+  mRequestUpdateCalled = true;
+}
+
+void TestRenderController::RequestProcessEventsOnIdle()
+{
+  mRequestProcessEventsOnIdleCalled = true;
+}
+
+bool TestRenderController::WasCalled(TestRenderControllerFuncEnum func)
+{
+  switch(func)
+  {
+    case RequestUpdateFunc: return mRequestUpdateCalled;
+    case RequestProcessEventsOnIdleFunc: return mRequestProcessEventsOnIdleCalled;
+  }
+
+  return false;
+}
+
+void TestRenderController::Initialize()
+{
+  mRequestUpdateCalled = false;
+  mRequestProcessEventsOnIdleCalled = false;
+}
+
+
+} // namespace dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h b/automated-tests/src/dali/dali-test-suite-utils/test-render-controller.h
new file mode 100644 (file)
index 0000000..b00fbf0
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __TEST_RENDER_CONTROLLER_H__
+#define __TEST_RENDER_CONTROLLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/render-controller.h>
+
+namespace Dali
+{
+
+class DALI_IMPORT_API TestRenderController : public Dali::Integration::RenderController
+{
+public:
+  TestRenderController();
+  ~TestRenderController();
+
+  virtual void RequestUpdate();
+  virtual void RequestProcessEventsOnIdle();
+
+  typedef enum
+  {
+    RequestUpdateFunc,
+    RequestProcessEventsOnIdleFunc,
+  } TestRenderControllerFuncEnum;
+
+  bool WasCalled(TestRenderControllerFuncEnum func);
+  void Initialize();
+
+
+private:
+  bool mRequestUpdateCalled;
+  bool mRequestProcessEventsOnIdleCalled;
+};
+
+} // Dali
+
+#endif
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h b/automated-tests/src/dali/dali-test-suite-utils/test-touch-utils.h
new file mode 100644 (file)
index 0000000..ebae313
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef _TEST_TOUCH_UTILS_H_
+#define _TEST_TOUCH_UTILS_H_
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/actors/actor.h>
+
+namespace Dali
+{
+
+// Data for touch events
+struct TouchEventData
+{
+  TouchEventData()
+  : functorCalled(false),
+    receivedTouch(),
+    touchActor()
+  {
+  }
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    receivedTouch.points.clear();
+    receivedTouch.time = 0;
+
+    touchActor.Reset();
+  }
+
+  bool functorCalled;
+  TouchEvent receivedTouch;
+  Actor touchActor;
+};
+
+// Functor that sets the data when called
+struct TouchEventDataFunctor
+{
+  TouchEventDataFunctor(TouchEventData& data) : touchEventData(data) { }
+
+  bool operator()(Actor actor, const TouchEvent& touch)
+  {
+    touchEventData.functorCalled = true;
+    touchEventData.touchActor = actor;
+    touchEventData.receivedTouch = touch;
+    return false;
+  }
+
+  // Generate a touch-event
+  Integration::TouchEvent GenerateSingleTouch( TouchPoint::State state, Vector2 screenPosition ) const
+  {
+    Integration::TouchEvent touchEvent;
+    touchEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) );
+    return touchEvent;
+  }
+
+  TouchEventData& touchEventData;
+};
+
+
+} // namespace Dali
+
+#endif //  _TEST_TOUCH_UTILS_H_
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp
new file mode 100644 (file)
index 0000000..921088b
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "test-trace-call-stack.h"
+
+namespace Dali
+{
+/**
+ * Constructor
+ */
+TraceCallStack::TraceCallStack() : mTraceActive(false) { }
+
+/**
+ * Destructor
+ */
+TraceCallStack::~TraceCallStack() { }
+
+/**
+ * Turn on / off tracing
+ */
+void TraceCallStack::Enable(bool enable) { mTraceActive = enable; }
+
+bool TraceCallStack::IsEnabled() { return mTraceActive; }
+
+/**
+ * Push a call onto the stack if the trace is active
+ * @param[in] method The name of the method
+ * @param[in] params A comma separated list of parameter values
+ */
+void TraceCallStack::PushCall(std::string method, std::string params)
+{
+  if(mTraceActive)
+  {
+    std::vector< std::string > functionCall;
+    functionCall.push_back(method);
+    functionCall.push_back(params);
+    mCallStack.push_back( functionCall );
+  }
+}
+
+/**
+ * Search for a method in the stack
+ * @param[in] method The name of the method
+ * @return true if the method was in the stack
+ */
+bool TraceCallStack::FindMethod(std::string method) const
+{
+  bool found = false;
+  for( size_t i=0; i < mCallStack.size(); i++ )
+  {
+    if( 0 == mCallStack[i][0].compare(method) )
+    {
+      found = true;
+      break;
+    }
+  }
+  return found;
+}
+
+int TraceCallStack::CountMethod(std::string method) const
+{
+  int numCalls = 0;
+  for( size_t i=0; i < mCallStack.size(); i++ )
+  {
+    if( 0 == mCallStack[i][0].compare(method) )
+    {
+      numCalls++;
+    }
+  }
+  return numCalls;
+}
+
+
+/**
+ * Search for a method in the stack with the given parameter list
+ * @param[in] method The name of the method
+ * @param[in] params A comma separated list of parameter values
+ * @return true if the method was in the stack
+ */
+bool TraceCallStack::FindMethodAndParams(std::string method, std::string params) const
+{
+  bool found = false;
+  for( size_t i=0; i < mCallStack.size(); i++ )
+  {
+    if( 0 == mCallStack[i][0].compare(method) && 0 == mCallStack[i][1].compare(params) )
+    {
+      found = true;
+      break;
+    }
+  }
+  return found;
+}
+
+/**
+ * Test if the given method and parameters are at a given index in the stack
+ * @param[in] index Index in the call stack
+ * @param[in] method Name of method to test
+ * @param[in] params A comma separated list of parameter values to test
+ */
+bool TraceCallStack::TestMethodAndParams(int index, std::string method, std::string params) const
+{
+  return ( 0 == mCallStack[index][0].compare(method) && 0 == mCallStack[index][1].compare(params) );
+}
+
+/**
+ * Reset the call stack
+ */
+void TraceCallStack::Reset()
+{
+  mCallStack.clear();
+}
+
+
+} // namespace Dali
diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h b/automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.h
new file mode 100644 (file)
index 0000000..25b77f8
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __TEST_TRACE_CALL_STACK_H__
+#define __TEST_TRACE_CALL_STACK_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <string>
+#include <vector>
+
+namespace Dali
+{
+
+/**
+ * Helper class to track method calls in the abstraction and search for them in test cases
+ */
+class TraceCallStack
+{
+public:
+  /**
+   * Constructor
+   */
+  TraceCallStack();
+
+  /**
+   * Destructor
+   */
+  ~TraceCallStack();
+
+  /**
+   * Turn on / off tracing
+   */
+  void Enable(bool enable);
+
+  bool IsEnabled();
+
+  /**
+   * Push a call onto the stack if the trace is active
+   * @param[in] method The name of the method
+   * @param[in] params A comma separated list of parameter values
+   */
+  void PushCall(std::string method, std::string params);
+
+
+  /**
+   * Search for a method in the stack
+   * @param[in] method The name of the method
+   * @return true if the method was in the stack
+   */
+  bool FindMethod(std::string method) const;
+
+  /**
+   * Count how many times a method was called
+   * @param[in] method The name of the method
+   * @return The number of times it was called
+   */
+  int CountMethod(std::string method) const;
+
+  /**
+   * Search for a method in the stack with the given parameter list
+   * @param[in] method The name of the method
+   * @param[in] params A comma separated list of parameter values
+   * @return true if the method was in the stack
+   */
+  bool FindMethodAndParams(std::string method, std::string params) const;
+
+  /**
+   * Test if the given method and parameters are at a given index in the stack
+   * @param[in] index Index in the call stack
+   * @param[in] method Name of method to test
+   * @param[in] params A comma separated list of parameter values to test
+   */
+  bool TestMethodAndParams(int index, std::string method, std::string params) const;
+
+  /**
+   * Reset the call stack
+   */
+  void Reset();
+
+  /**
+   * Get the call stack
+   * @return The call stack object (Vector of vector[2] of method/paramlist strings)
+   */
+  inline const std::vector< std::vector< std::string > >& GetCallStack() { return mCallStack; }
+
+private:
+  bool mTraceActive; ///< True if the trace is active
+  std::vector< std::vector< std::string > > mCallStack; ///< The call stack
+};
+
+} // namespace dali
+
+#endif //__TEST_TRACE_CALL_STACK_H__
diff --git a/automated-tests/src/dali/tct-dali-core.cpp b/automated-tests/src/dali/tct-dali-core.cpp
new file mode 100644 (file)
index 0000000..f8bd4de
--- /dev/null
@@ -0,0 +1,40 @@
+#include <string.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <test-harness.h>
+#include "tct-dali-core.h"
+
+int main(int argc, char * const argv[])
+{
+  int result = TestHarness::EXIT_STATUS_BAD_ARGUMENT;
+
+  const char* optString = "r";
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'r':
+        optRerunFailed = true;
+        break;
+      case '?':
+        TestHarness::Usage(argv[0]);
+        exit(TestHarness::EXIT_STATUS_BAD_ARGUMENT);
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optind == argc ) // no testcase name in argument list
+  {
+    result = TestHarness::RunAllInParallel(argv[0], tc_array, optRerunFailed);
+  }
+  else
+  {
+    // optind is index of next argument - interpret as testcase name
+    result = TestHarness::FindAndRunTestCase(tc_array, argv[optind]);
+  }
+  return result;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Actor.cpp b/automated-tests/src/dali/utc-Dali-Actor.cpp
new file mode 100644 (file)
index 0000000..3ba9bd9
--- /dev/null
@@ -0,0 +1,2910 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "assert.h"
+#include <dali/public-api/dali-core.h>
+#include <string>
+#include <cfloat>   // For FLT_MAX
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali-test-suite-utils.h>
+
+//& set: DaliActor
+
+using std::string;
+using namespace Dali;
+
+
+void utc_dali_actor_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_actor_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+bool gTouchCallBackCalled=false;
+bool gHoverCallBackCalled=false;
+
+/**
+ * Simulates a Down Touch at 25.0, 25.0.
+ * @param[in] app Test Application instance.
+ */
+int SimulateTouchForSetOverlayHitTest(TestApplication& app)
+{
+  app.SendNotification();
+  app.Render(1);
+  app.SendNotification();
+  app.Render(1);
+
+  gTouchCallBackCalled = false;
+
+  // simulate a touch event
+  Dali::TouchPoint point( 0, TouchPoint::Down, 25.0f, 25.0f );
+  Dali::Integration::TouchEvent event;
+  event.AddPoint( point );
+  app.ProcessEvent( event );
+
+  app.SendNotification();
+  app.Render(1);
+  app.SendNotification();
+  app.Render(1);
+  END_TEST;
+}
+
+
+static bool gTestConstraintCalled;
+
+struct TestConstraint
+{
+  void operator()( Vector4& color, const PropertyInputContainer& /* inputs */ )
+  {
+    gTestConstraintCalled = true;
+  }
+};
+
+/**
+ * TestConstraint reference.
+ * When constraint is called, the resultRef is updated
+ * with the value supplied.
+ */
+template<typename T>
+struct TestConstraintRef
+{
+  TestConstraintRef(unsigned int& resultRef, unsigned int value)
+  : mResultRef(resultRef),
+    mValue(value)
+  {
+  }
+
+  void operator()( T& current, const PropertyInputContainer& /* inputs */ )
+  {
+    mResultRef = mValue;
+  }
+
+  unsigned int& mResultRef;
+  unsigned int mValue;
+};
+
+static bool TestCallback(Actor actor, const TouchEvent& event)
+{
+  gTouchCallBackCalled = true;
+  return false;
+  END_TEST;
+}
+
+static bool TestCallback3(Actor actor, const HoverEvent& event)
+{
+  gHoverCallBackCalled = true;
+  return false;
+  END_TEST;
+}
+
+static Vector3 gSetSize;
+static bool gSetSizeCallBackCalled;
+void SetSizeCallback( Actor actor, const Vector3& size )
+{
+  gSetSizeCallBackCalled = true;
+  gSetSize = size;
+}
+// validation stuff for onstage & offstage signals
+static std::vector< std::string > gActorNamesOnOffStage;
+static int gOnStageCallBackCalled;
+void OnStageCallback( Actor actor )
+{
+  ++gOnStageCallBackCalled;
+  gActorNamesOnOffStage.push_back( actor.GetName() );
+  DALI_TEST_CHECK( actor.OnStage() == true );
+}
+static int gOffStageCallBackCalled;
+void OffStageCallback( Actor actor )
+{
+  ++gOffStageCallBackCalled;
+  gActorNamesOnOffStage.push_back( actor.GetName() );
+  DALI_TEST_CHECK( actor.OnStage() == false );
+}
+
+struct PositionComponentConstraint
+{
+  PositionComponentConstraint(){}
+
+  void operator()( Vector3& pos, const PropertyInputContainer& inputs )
+  {
+    const Matrix& m = inputs[0]->GetMatrix();
+    Vector3 scale;
+    Quaternion rot;
+    m.GetTransformComponents(pos, rot, scale);
+  }
+};
+
+// OnRelayout
+
+static bool gOnRelayoutCallBackCalled = 0;
+static std::vector< std::string > gActorNamesRelayout;
+
+void OnRelayoutCallback( Actor actor )
+{
+  ++gOnRelayoutCallBackCalled;
+  gActorNamesRelayout.push_back( actor.GetName() );
+}
+
+} // anonymous namespace
+
+
+//& purpose: Testing New API
+int UtcDaliActorNew(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(actor);
+  END_TEST;
+}
+
+//& purpose: Testing Dali::Actor::DownCast()
+int UtcDaliActorDownCastP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Actor::DownCast()");
+
+  Actor actor = Actor::New();
+  BaseHandle object(actor);
+  Actor actor2 = Actor::DownCast(object);
+  DALI_TEST_CHECK(actor2);
+  END_TEST;
+}
+
+//& purpose: Testing Dali::Actor::DownCast()
+int UtcDaliActorDownCastN(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Actor::DownCast()");
+
+  BaseHandle unInitializedObject;
+  Actor actor = Actor::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!actor);
+  END_TEST;
+}
+
+//& purpose: Testing Dali::Actor::GetName()
+int UtcDaliActorGetName(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(actor.GetName().empty());
+  END_TEST;
+}
+
+//& purpose: Testing Dali::Actor::SetName()
+int UtcDaliActorSetName(void)
+{
+  TestApplication application;
+
+  string str("ActorName");
+  Actor actor = Actor::New();
+
+  actor.SetName(str);
+  DALI_TEST_CHECK(actor.GetName() == str);
+  END_TEST;
+}
+
+int UtcDaliActorGetId(void)
+{
+  tet_infoline("Testing Dali::Actor::UtcDaliActorGetId()");
+  TestApplication application;
+
+  Actor first = Actor::New();
+  Actor second = Actor::New();
+  Actor third = Actor::New();
+
+  DALI_TEST_CHECK(first.GetId() != second.GetId());
+  DALI_TEST_CHECK(second.GetId() != third.GetId());
+  END_TEST;
+}
+
+int UtcDaliActorIsRoot(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK(!actor.IsRoot());
+
+  // get the root layer
+  actor = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_CHECK( actor.IsRoot() );
+  END_TEST;
+}
+
+int UtcDaliActorOnStage(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( !actor.OnStage() );
+
+  // get the root layer
+  actor = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_CHECK( actor.OnStage() );
+  END_TEST;
+}
+
+int UtcDaliActorIsLayer(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( !actor.IsLayer() );
+
+  // get the root layer
+  actor = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_CHECK( actor.IsLayer() );
+  END_TEST;
+}
+
+int UtcDaliActorGetLayer(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  Layer layer = actor.GetLayer();
+
+  DALI_TEST_CHECK(layer);
+
+  // get the root layers layer
+  actor = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_CHECK( actor.GetLayer() );
+  END_TEST;
+}
+
+int UtcDaliActorAddP(void)
+{
+  tet_infoline("Testing Actor::Add");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor child = Actor::New();
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+
+  parent.Add(child);
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+
+  Actor parent2 = Actor::New();
+  parent2.Add( child );
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+
+  // try Adding to same parent again, works
+  parent2.Add( child );
+  DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+
+  // try reparenting an orphaned child
+  {
+    Actor temporaryParent = Actor::New();
+    temporaryParent.Add( child );
+    DALI_TEST_EQUALS( parent2.GetChildCount(), 0u, TEST_LOCATION );
+  }
+  // temporaryParent has now died, reparent the orphaned child
+  parent2.Add( child );
+  DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorAddN(void)
+{
+  tet_infoline("Testing Actor::Add");
+  TestApplication application;
+
+  Actor child = Actor::New();
+
+  Actor parent2 = Actor::New();
+  parent2.Add( child );
+
+  // try illegal Add
+  try
+  {
+    parent2.Add( parent2 );
+    tet_printf("Assertion test failed - no Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "this != &child", TEST_LOCATION);
+    DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  // try reparenting root
+  try
+  {
+    parent2.Add( Stage::GetCurrent().GetLayer( 0 ) );
+    tet_printf("Assertion test failed - no Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "!child.IsRoot()", TEST_LOCATION);
+    DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  // try Add empty
+  try
+  {
+    Actor empty;
+    parent2.Add( empty );
+    tet_printf("Assertion test failed - no Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "actor", TEST_LOCATION);
+    DALI_TEST_EQUALS( parent2.GetChildCount(), 1u, TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliActorRemoveN(void)
+{
+  tet_infoline("Testing Actor::Remove");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor child = Actor::New();
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+
+  parent.Add(child);
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+
+  parent.Remove(child);
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+
+  // remove again, no problem
+  parent.Remove(child);
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+
+  // add child back
+  parent.Add(child);
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+  // try Remove self, its a no-op
+  parent.Remove( parent );
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+
+  // try Remove empty
+  try
+  {
+    Actor empty;
+    parent.Remove( empty );
+    tet_printf("Assertion test failed - no Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "actor", TEST_LOCATION);
+    DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliActorRemoveP(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor child = Actor::New();
+  Actor random = Actor::New();
+
+  Stage::GetCurrent().Add( parent );
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 0);
+
+  parent.Add(child);
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 1);
+
+  parent.Remove(random);
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 1);
+
+  Stage::GetCurrent().Remove( parent );
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 1);
+  END_TEST;
+}
+
+int UtcDaliActorGetChildCount(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor child = Actor::New();
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 0);
+
+  parent.Add(child);
+
+  DALI_TEST_CHECK(parent.GetChildCount() == 1);
+  END_TEST;
+}
+
+int UtcDaliActorGetChildren01(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor first  = Actor::New();
+  Actor second = Actor::New();
+  Actor third  = Actor::New();
+
+  parent.Add(first);
+  parent.Add(second);
+  parent.Add(third);
+
+  DALI_TEST_CHECK(parent.GetChildAt(0) == first);
+  DALI_TEST_CHECK(parent.GetChildAt(1) == second);
+  DALI_TEST_CHECK(parent.GetChildAt(2) == third);
+  END_TEST;
+}
+
+int UtcDaliActorGetChildren02(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor first  = Actor::New();
+  Actor second = Actor::New();
+  Actor third  = Actor::New();
+
+  parent.Add(first);
+  parent.Add(second);
+  parent.Add(third);
+
+  const Actor& constParent = parent;
+
+  DALI_TEST_CHECK(constParent.GetChildAt(0) == first);
+  DALI_TEST_CHECK(constParent.GetChildAt(1) == second);
+  DALI_TEST_CHECK(constParent.GetChildAt(2) == third);
+  END_TEST;
+}
+
+int UtcDaliActorGetParent01(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor child = Actor::New();
+
+  parent.Add(child);
+
+  DALI_TEST_CHECK(child.GetParent() == parent);
+  END_TEST;
+}
+
+int UtcDaliActorGetParent02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(!actor.GetParent());
+  END_TEST;
+}
+
+int UtcDaliActorSetParentOrigin(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.7f, 0.8f, 0.9f);
+  DALI_TEST_CHECK(vector != actor.GetCurrentParentOrigin());
+
+  actor.SetParentOrigin(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentParentOrigin());
+
+  Stage::GetCurrent().Add( actor );
+
+  actor.SetParentOrigin( Vector3( 0.1f, 0.2f, 0.3f ) );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentParentOrigin(), TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentParentOrigin(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.7f, 0.8f, 0.9f);
+  DALI_TEST_CHECK(vector != actor.GetCurrentParentOrigin());
+
+  actor.SetParentOrigin(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentParentOrigin());
+  END_TEST;
+}
+
+int UtcDaliActorSetAnchorPoint(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.7f, 0.8f, 0.9f);
+  DALI_TEST_CHECK(vector != actor.GetCurrentAnchorPoint());
+
+  actor.SetAnchorPoint(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentAnchorPoint());
+
+  Stage::GetCurrent().Add( actor );
+
+  actor.SetAnchorPoint( Vector3( 0.1f, 0.2f, 0.3f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentAnchorPoint(), TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentAnchorPoint(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.7f, 0.8f, 0.9f);
+  DALI_TEST_CHECK(vector != actor.GetCurrentAnchorPoint());
+
+  actor.SetAnchorPoint(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentAnchorPoint());
+  END_TEST;
+}
+
+// SetSize(float width, float height)
+int UtcDaliActorSetSize01(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector.x, vector.y);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+  END_TEST;
+}
+
+// SetSize(float width, float height, float depth)
+int UtcDaliActorSetSize02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector.x, vector.y, vector.z);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+  END_TEST;
+}
+
+// SetSize(Vector2 size)
+int UtcDaliActorSetSize03(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(Vector2(vector.x, vector.y));
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+  END_TEST;
+}
+
+// SetSize(Vector3 size)
+int UtcDaliActorSetSize04(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+
+  Stage::GetCurrent().Add( actor );
+  actor.SetSize( Vector3( 0.1f, 0.2f, 0.3f ) );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentSize(), TEST_LOCATION );
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentSize(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 20.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+  END_TEST;
+}
+
+int UtcDaliActorGetNaturalSize(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector( 0.0f, 0.0f, 0.0f );
+
+  DALI_TEST_CHECK( actor.GetNaturalSize() == vector );
+
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentSizeImmediate(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 20.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetTargetSize());
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector);
+
+  DALI_TEST_CHECK(vector == actor.GetTargetSize());
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetTargetSize());
+  DALI_TEST_CHECK(vector == actor.GetCurrentSize());
+
+  // Animation
+  // Build the animation
+  const float durationSeconds = 2.0f;
+  Animation animation = Animation::New( durationSeconds );
+  const Vector3 targetValue( 10.0f, 20.0f, 30.0f );
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE ), targetValue );
+
+  DALI_TEST_CHECK( actor.GetTargetSize() == targetValue );
+
+  // Start the animation
+  animation.Play();
+
+  application.SendNotification();
+  application.Render( static_cast<unsigned int>( durationSeconds * 1000.0f ) );
+
+  DALI_TEST_CHECK( actor.GetTargetSize() == targetValue );
+
+  END_TEST;
+}
+
+// SetPosition(float x, float y)
+int UtcDaliActorSetPosition01(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Set to random to start off with
+  actor.SetPosition(Vector3(120.0f, 120.0f, 0.0f));
+
+  Vector3 vector(100.0f, 100.0f, 0.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetPosition(vector.x, vector.y);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+
+  Stage::GetCurrent().Add( actor );
+  actor.SetPosition( Vector3( 0.1f, 0.2f, 0.3f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), actor.GetCurrentPosition(), TEST_LOCATION );
+
+  actor.SetX( 1.0f );
+  actor.SetY( 1.1f );
+  actor.SetZ( 1.2f );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector3( 1.0f, 1.1f, 1.2f ), actor.GetCurrentPosition(), TEST_LOCATION );
+
+  actor.TranslateBy( Vector3( 0.1f, 0.1f, 0.1f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector3( 1.1f, 1.2f, 1.3f ), actor.GetCurrentPosition(), Math::MACHINE_EPSILON_10000, TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+// SetPosition(float x, float y, float z)
+int UtcDaliActorSetPosition02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Set to random to start off with
+  actor.SetPosition(Vector3(120.0f, 120.0f, 120.0f));
+
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetPosition(vector.x, vector.y, vector.z);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+// SetPosition(Vector3 position)
+int UtcDaliActorSetPosition03(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Set to random to start off with
+  actor.SetPosition(Vector3(120.0f, 120.0f, 120.0f));
+
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetPosition(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+int UtcDaliActorSetX(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(100.0f, 0.0f, 0.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetX(100.0f);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+int UtcDaliActorSetY(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.0f, 100.0f, 0.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetY(100.0f);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+int UtcDaliActorSetZ(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Vector3 vector(0.0f, 0.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetZ(100.0f);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+int UtcDaliActorTranslateBy(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentPosition());
+
+  actor.SetPosition(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentPosition());
+
+  actor.TranslateBy(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector*2.0f == actor.GetCurrentPosition());
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentPosition(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 setVector(100.0f, 100.0f, 0.0f);
+  actor.SetPosition(setVector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(actor.GetCurrentPosition() == setVector);
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentWorldPosition(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Vector3 parentPosition( 1.0f, 2.0f, 3.0f );
+  parent.SetPosition( parentPosition );
+  parent.SetParentOrigin( ParentOrigin::CENTER );
+  parent.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  child.SetParentOrigin( ParentOrigin::CENTER );
+  child.SetAnchorPoint( AnchorPoint::CENTER );
+  Vector3 childPosition( 6.0f, 6.0f, 6.0f );
+  child.SetPosition( childPosition );
+  parent.Add( child );
+
+  // The actors should not have a world position yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION );
+
+  // The actors should have a world position now
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorInheritPosition(void)
+{
+  tet_infoline("Testing Actor::SetPositionInheritanceMode");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Vector3 parentPosition( 1.0f, 2.0f, 3.0f );
+  parent.SetPosition( parentPosition );
+  parent.SetParentOrigin( ParentOrigin::CENTER );
+  parent.SetAnchorPoint( AnchorPoint::CENTER );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  child.SetParentOrigin( ParentOrigin::CENTER );
+  child.SetAnchorPoint( AnchorPoint::CENTER );
+  Vector3 childPosition( 10.0f, 11.0f, 12.0f );
+  child.SetPosition( childPosition );
+  parent.Add( child );
+
+  // The actors should not have a world position yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  // first test default, which is INHERIT_PARENT_POSITION
+  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::INHERIT_PARENT_POSITION, TEST_LOCATION );
+  application.SendNotification();
+  application.Render(0); // should only really call Update as Render is not required to update scene
+  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childPosition, TEST_LOCATION );
+
+  // Change inheritance mode to use parent
+  child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION );
+  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION, TEST_LOCATION );
+  application.SendNotification();
+  application.Render(0); // should only really call Update as Render is not required to update scene
+  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), childPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+
+  // Change inheritance mode to use parent + offset
+  child.SetPositionInheritanceMode( Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION );
+  Vector3 childOffset( -1.0f, 1.0f, 0.0f );
+  child.SetPosition( childOffset );
+  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::USE_PARENT_POSITION_PLUS_LOCAL_POSITION, TEST_LOCATION );
+  application.SendNotification();
+  application.Render(0); // should only really call Update as Render is not required to update scene
+  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), childOffset, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), parentPosition + childOffset, TEST_LOCATION );
+
+  // Change inheritance mode to not inherit
+  child.SetPositionInheritanceMode( Dali::DONT_INHERIT_POSITION );
+  DALI_TEST_EQUALS( child.GetPositionInheritanceMode(), Dali::DONT_INHERIT_POSITION, TEST_LOCATION );
+  application.SendNotification();
+  application.Render(0); // should only really call Update as Render is not required to update scene
+  DALI_TEST_EQUALS( parent.GetCurrentPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), childOffset, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetCurrentWorldPosition(), parentPosition, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldPosition(), childOffset, TEST_LOCATION );
+  END_TEST;
+}
+
+// SetOrientation(float angleRadians, Vector3 axis)
+int UtcDaliActorSetOrientation01(void)
+{
+  TestApplication application;
+
+  Quaternion rotation( Radian(0.785f), Vector3(1.0f, 1.0f, 0.0f));
+  Actor actor = Actor::New();
+
+  actor.SetOrientation(rotation);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorSetOrientation02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Radian angle( 0.785f );
+  Vector3 axis(1.0f, 1.0f, 0.0f);
+
+  actor.SetOrientation( angle, axis);
+  Quaternion rotation( angle, axis );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  Stage::GetCurrent().Add( actor );
+  actor.RotateBy( Degree( 360 ), axis);
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  actor.SetOrientation( Degree( 0 ), Vector3( 1.0f, 0.0f, 0.0f ) );
+  Quaternion result( Radian( 0 ), Vector3( 1.0f, 0.0f, 0.0f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( result, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  actor.SetOrientation( angle, axis);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+// RotateBy(float angleRadians, Vector3 axis)
+int UtcDaliActorRotateBy01(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Radian angle( M_PI * 0.25f );
+  actor.RotateBy(( angle ), Vector3::ZAXIS);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(Quaternion( angle, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  Stage::GetCurrent().Add( actor );
+
+  actor.RotateBy( angle, Vector3::ZAXIS);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(Quaternion(angle * 2.0f, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+// RotateBy(Quaternion relativeRotation)
+int UtcDaliActorRotateBy02(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Radian angle( M_PI * 0.25f );
+  Quaternion rotation(angle, Vector3::ZAXIS);
+  actor.RotateBy(rotation);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+
+  actor.RotateBy(rotation);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(Quaternion(angle * 2.0f, Vector3::ZAXIS), actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentOrientation(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+
+  Quaternion rotation(Radian(0.785f), Vector3(1.0f, 1.0f, 0.0f));
+  actor.SetOrientation(rotation);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(rotation, actor.GetCurrentOrientation(), 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentWorldOrientation(void)
+{
+  tet_infoline("Testing Actor::GetCurrentWorldRotation");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Radian rotationAngle( Degree(90.0f) );
+  Quaternion rotation( rotationAngle, Vector3::YAXIS );
+  parent.SetOrientation( rotation );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  child.SetOrientation( rotation );
+  parent.Add( child );
+
+  // The actors should not have a world rotation yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), 0.001, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( parent.GetCurrentOrientation(), rotation, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentOrientation(), rotation, 0.001, TEST_LOCATION );
+
+  // The actors should have a world rotation now
+  DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion( rotationAngle, Vector3::YAXIS ), 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), Quaternion( rotationAngle * 2.0f, Vector3::YAXIS ), 0.001, TEST_LOCATION );
+
+  // turn off child rotation inheritance
+  child.SetInheritOrientation( false );
+  DALI_TEST_EQUALS( child.IsOrientationInherited(), false, TEST_LOCATION );
+  application.SendNotification();
+  application.Render(0);
+
+  // The actors should have a world rotation now
+  DALI_TEST_EQUALS( parent.GetCurrentWorldOrientation(), Quaternion( rotationAngle, Vector3::YAXIS ), 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldOrientation(), rotation, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+// SetScale(float scale)
+int UtcDaliActorSetScale01(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Set to random value first - GetCurrentScale() asserts if called before SetScale()
+  actor.SetScale(0.25f);
+
+  Vector3 scale(10.0f, 10.0f, 10.0f);
+  DALI_TEST_CHECK(actor.GetCurrentScale() != scale);
+
+  actor.SetScale(scale.x);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(actor.GetCurrentScale() == scale);
+  END_TEST;
+}
+
+// SetScale(float scaleX, float scaleY, float scaleZ)
+int UtcDaliActorSetScale02(void)
+{
+  TestApplication application;
+  Vector3 scale(10.0f, 10.0f, 10.0f);
+
+  Actor actor = Actor::New();
+
+  // Set to random value first - GetCurrentScale() asserts if called before SetScale()
+  actor.SetScale(Vector3(12.0f, 1.0f, 2.0f));
+
+  DALI_TEST_CHECK(actor.GetCurrentScale() != scale);
+
+  actor.SetScale(scale.x, scale.y, scale.z);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(actor.GetCurrentScale() == scale);
+
+  // add to stage and test
+  Stage::GetCurrent().Add( actor );
+  actor.SetScale( 2.0f, 2.0f, 2.0f );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector3( 2.0f, 2.0f, 2.0f ), actor.GetCurrentScale(), 0.001, TEST_LOCATION);
+
+  Stage::GetCurrent().Remove( actor );
+
+  END_TEST;
+}
+
+// SetScale(Vector3 scale)
+int UtcDaliActorSetScale03(void)
+{
+  TestApplication application;
+  Vector3 scale(10.0f, 10.0f, 10.0f);
+
+  Actor actor = Actor::New();
+
+  // Set to random value first - GetCurrentScale() asserts if called before SetScale()
+  actor.SetScale(Vector3(12.0f, 1.0f, 2.0f));
+
+  DALI_TEST_CHECK(actor.GetCurrentScale() != scale);
+
+  actor.SetScale(scale);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(actor.GetCurrentScale() == scale);
+  END_TEST;
+}
+
+int UtcDaliActorScaleBy(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  Vector3 vector(100.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentScale());
+
+  actor.SetScale(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector == actor.GetCurrentScale());
+
+  actor.ScaleBy(vector);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(vector*100.0f == actor.GetCurrentScale());
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentScale(void)
+{
+  TestApplication application;
+  Vector3 scale(12.0f, 1.0f, 2.0f);
+
+  Actor actor = Actor::New();
+
+  actor.SetScale(scale);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(actor.GetCurrentScale() == scale);
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentWorldScale(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Vector3 parentScale( 1.0f, 2.0f, 3.0f );
+  parent.SetScale( parentScale );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  Vector3 childScale( 2.0f, 2.0f, 2.0f );
+  child.SetScale( childScale );
+  parent.Add( child );
+
+  // The actors should not have a scale yet
+  DALI_TEST_EQUALS( parent.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // The actors should not have a world scale yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldScale(), Vector3::ONE, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldScale(), Vector3::ONE, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( parent.GetCurrentScale(), parentScale, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentScale(), childScale, TEST_LOCATION );
+
+  // The actors should have a world scale now
+  DALI_TEST_EQUALS( parent.GetCurrentWorldScale(), parentScale, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldScale(), parentScale * childScale, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorInheritScale(void)
+{
+  tet_infoline("Testing Actor::SetInheritScale");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Vector3 parentScale( 1.0f, 2.0f, 3.0f );
+  parent.SetScale( parentScale );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  Vector3 childScale( 2.0f, 2.0f, 2.0f );
+  child.SetScale( childScale );
+  parent.Add( child );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( child.IsScaleInherited(), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldScale(), parentScale * childScale, TEST_LOCATION );
+
+  child.SetInheritScale( false );
+  DALI_TEST_EQUALS( child.IsScaleInherited(), false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( child.GetCurrentWorldScale(), childScale, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorSetVisible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetVisible(false);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(actor.IsVisible() == false);
+
+  actor.SetVisible(true);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(actor.IsVisible() == true);
+
+  // put actor on stage
+  Stage::GetCurrent().Add( actor );
+  actor.SetVisible(false);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(actor.IsVisible() == false);
+  END_TEST;
+}
+
+int UtcDaliActorIsVisible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(actor.IsVisible() == true);
+  END_TEST;
+}
+
+int UtcDaliActorSetOpacity(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  // initial opacity is 1
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 1.0f, TEST_LOCATION );
+
+  actor.SetOpacity( 0.4f);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.4f, TEST_LOCATION );
+
+  // change opacity, actor is on stage to change is not immediate
+  actor.SetOpacity( actor.GetCurrentOpacity() + 0.1f );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.5f, TEST_LOCATION );
+
+  // put actor on stage
+  Stage::GetCurrent().Add( actor );
+
+  // change opacity, actor is on stage to change is not immediate
+  actor.SetOpacity( 0.9f );
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.5f, TEST_LOCATION );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.9f, TEST_LOCATION );
+
+  // change opacity, actor is on stage to change is not immediate
+  actor.SetOpacity( actor.GetCurrentOpacity() - 0.9f );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS(actor.GetCurrentOpacity(), 0.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentOpacity(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK(actor.GetCurrentOpacity() != 0.5f);
+
+  actor.SetOpacity(0.5f);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(actor.GetCurrentOpacity() == 0.5f);
+  END_TEST;
+}
+
+int UtcDaliActorSetSensitive(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+
+  bool sensitive = !actor.IsSensitive();
+
+  actor.SetSensitive(sensitive);
+
+  DALI_TEST_CHECK(sensitive == actor.IsSensitive());
+  END_TEST;
+}
+
+int UtcDaliActorIsSensitive(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  actor.SetSensitive(false);
+
+  DALI_TEST_CHECK(false == actor.IsSensitive());
+  END_TEST;
+}
+
+int UtcDaliActorSetColor(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  Vector4 color(1.0f, 1.0f, 1.0f, 0.5f);
+
+  DALI_TEST_CHECK(color != actor.GetCurrentColor());
+
+  actor.SetColor(color);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(color == actor.GetCurrentColor());
+
+  actor.SetColor( actor.GetCurrentColor() + Vector4( -0.4f, -0.5f, -0.6f, -0.4f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector4( 0.6f, 0.5f, 0.4f, 0.1f ), actor.GetCurrentColor(),  TEST_LOCATION );
+
+  Stage::GetCurrent().Add( actor );
+  actor.SetColor( color );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( color, actor.GetCurrentColor(),  TEST_LOCATION );
+
+  actor.SetColor( actor.GetCurrentColor() + Vector4( 1.1f, 1.1f, 1.1f, 1.1f ) );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  // Actor color is not clamped
+  DALI_TEST_EQUALS( Vector4( 2.1f, 2.1f, 2.1f, 1.6f ), actor.GetCurrentColor(),  TEST_LOCATION );
+  // world color is clamped
+  DALI_TEST_EQUALS( Vector4( 1.0f, 1.0f, 1.0f, 1.0f ), actor.GetCurrentWorldColor(),  TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( actor );
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentColor(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  Vector4 color(1.0f, 1.0f, 1.0f, 0.5f);
+
+  actor.SetColor(color);
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK(color == actor.GetCurrentColor());
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentWorldColor(void)
+{
+  tet_infoline("Actor::GetCurrentWorldColor");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Vector4 parentColor( 1.0f, 0.5f, 0.0f, 0.8f );
+  parent.SetColor( parentColor );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  Vector4 childColor( 0.5f, 0.6f, 0.5f, 1.0f );
+  child.SetColor( childColor );
+  parent.Add( child );
+
+  DALI_TEST_EQUALS( parent.GetCurrentColor(), Color::WHITE, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentColor(), Color::WHITE, TEST_LOCATION );
+
+  // verify the default color mode
+  DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, child.GetColorMode(), TEST_LOCATION );
+
+  // The actors should not have a world color yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldColor(), Color::WHITE, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldColor(), Color::WHITE, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( parent.GetCurrentColor(), parentColor, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION );
+
+  // The actors should have a world color now
+  DALI_TEST_EQUALS( parent.GetCurrentWorldColor(), parentColor, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldColor(), Vector4( childColor.r, childColor.g, childColor.b, childColor.a * parentColor.a), TEST_LOCATION );
+
+  // use own color
+  child.SetColorMode( USE_OWN_COLOR );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( child.GetCurrentWorldColor(), childColor, TEST_LOCATION );
+
+  // use parent color
+  child.SetColorMode( USE_PARENT_COLOR );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldColor(), parentColor, TEST_LOCATION );
+
+  // use parent alpha
+  child.SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA );
+  application.SendNotification();
+  application.Render(0);
+  Vector4 expectedColor( childColor );
+  expectedColor.a *= parentColor.a;
+  DALI_TEST_EQUALS( child.GetCurrentColor(), childColor, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldColor(), expectedColor, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorSetColorMode(void)
+{
+  tet_infoline("Actor::SetColorMode");
+  TestApplication application;
+  Actor actor = Actor::New();
+  Actor child = Actor::New();
+  actor.Add( child );
+
+  actor.SetColorMode( USE_OWN_COLOR );
+  DALI_TEST_EQUALS( USE_OWN_COLOR, actor.GetColorMode(), TEST_LOCATION );
+
+  actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_COLOR );
+  DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_COLOR, actor.GetColorMode(), TEST_LOCATION );
+
+  actor.SetColorMode( USE_PARENT_COLOR );
+  DALI_TEST_EQUALS( USE_PARENT_COLOR, actor.GetColorMode(), TEST_LOCATION );
+
+  actor.SetColorMode( USE_OWN_MULTIPLY_PARENT_ALPHA );
+  DALI_TEST_EQUALS( USE_OWN_MULTIPLY_PARENT_ALPHA, actor.GetColorMode(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorScreenToLocal(void)
+{
+  TestApplication application;
+  Actor actor = Actor::New();
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetPosition(10.0f, 10.0f);
+  Stage::GetCurrent().Add(actor);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  float localX;
+  float localY;
+
+  DALI_TEST_CHECK( actor.ScreenToLocal(localX, localY, 50.0f, 50.0f) );
+
+  DALI_TEST_EQUALS(localX, 40.0f, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(localY, 40.0f, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliActorSetLeaveRequired(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  actor.SetLeaveRequired(false);
+  DALI_TEST_CHECK(actor.GetLeaveRequired() == false);
+
+  actor.SetLeaveRequired(true);
+  DALI_TEST_CHECK(actor.GetLeaveRequired() == true);
+  END_TEST;
+}
+
+int UtcDaliActorGetLeaveRequired(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(actor.GetLeaveRequired() == false);
+  END_TEST;
+}
+
+int UtcDaliActorSetKeyboardFocusable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  actor.SetKeyboardFocusable(true);
+  DALI_TEST_CHECK(actor.IsKeyboardFocusable() == true);
+
+  actor.SetKeyboardFocusable(false);
+  DALI_TEST_CHECK(actor.IsKeyboardFocusable() == false);
+  END_TEST;
+}
+
+int UtcDaliActorIsKeyboardFocusable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK(actor.IsKeyboardFocusable() == false);
+  END_TEST;
+}
+
+int UtcDaliActorRemoveConstraints(void)
+{
+  tet_infoline(" UtcDaliActorRemoveConstraints");
+  TestApplication application;
+
+  gTestConstraintCalled = false;
+
+  Actor actor = Actor::New();
+
+  Constraint constraint = Constraint::New<Vector4>( actor, Actor::Property::COLOR, TestConstraint() );
+  constraint.Apply();
+  actor.RemoveConstraints();
+
+  DALI_TEST_CHECK( gTestConstraintCalled == false );
+
+  Stage::GetCurrent().Add( actor );
+  constraint.Apply();
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  actor.RemoveConstraints();
+
+  DALI_TEST_CHECK( gTestConstraintCalled == true );
+  END_TEST;
+}
+
+int UtcDaliActorRemoveConstraintTag(void)
+{
+  tet_infoline(" UtcDaliActorRemoveConstraintTag");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // 1. Apply Constraint1 and Constraint2, and test...
+  unsigned int result1 = 0u;
+  unsigned int result2 = 0u;
+
+  unsigned constraint1Tag = 1u;
+  Constraint constraint1 = Constraint::New<Vector4>( actor, Actor::Property::COLOR, TestConstraintRef<Vector4>(result1, 1) );
+  constraint1.SetTag( constraint1Tag );
+  constraint1.Apply();
+
+  unsigned constraint2Tag = 2u;
+  Constraint constraint2 = Constraint::New<Vector4>( actor, Actor::Property::COLOR, TestConstraintRef<Vector4>(result2, 2) );
+  constraint2.SetTag( constraint2Tag );
+  constraint2.Apply();
+
+  Stage::GetCurrent().Add( actor );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION );
+
+  // 2. Remove Constraint1 and test...
+  result1 = 0;
+  result2 = 0;
+  actor.RemoveConstraints(constraint1Tag);
+  // make color property dirty, which will trigger constraints to be reapplied.
+  actor.SetColor( Color::WHITE );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( result1, 0u, TEST_LOCATION );  ///< constraint 1 should not apply now.
+  DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION );
+
+  // 3. Re-Apply Constraint1 and test...
+  result1 = 0;
+  result2 = 0;
+  constraint1.Apply();
+  // make color property dirty, which will trigger constraints to be reapplied.
+  actor.SetColor( Color::WHITE );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( result2, 2u, TEST_LOCATION );
+
+  // 2. Remove Constraint2 and test...
+  result1 = 0;
+  result2 = 0;
+  actor.RemoveConstraints(constraint2Tag);
+  // make color property dirty, which will trigger constraints to be reapplied.
+  actor.SetColor( Color::WHITE );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( result1, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( result2, 0u, TEST_LOCATION ); ///< constraint 2 should not apply now.
+
+  // 2. Remove Constraint1 as well and test...
+  result1 = 0;
+  result2 = 0;
+  actor.RemoveConstraints(constraint1Tag);
+  // make color property dirty, which will trigger constraints to be reapplied.
+  actor.SetColor( Color::WHITE );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( result1, 0u, TEST_LOCATION ); ///< constraint 1 should not apply now.
+  DALI_TEST_EQUALS( result2, 0u, TEST_LOCATION ); ///< constraint 2 should not apply now.
+  END_TEST;
+}
+
+int UtcDaliActorTouchedSignal(void)
+{
+  TestApplication application;
+
+  gTouchCallBackCalled = false;
+
+  // get the root layer
+  Actor actor = Stage::GetCurrent().GetRootLayer();
+  DALI_TEST_CHECK( gTouchCallBackCalled == false );
+
+  application.SendNotification();
+  application.Render();
+
+  // connect to its touch signal
+  actor.TouchedSignal().Connect( TestCallback );
+
+  // simulate a touch event in the middle of the screen
+  Vector2 touchPoint( Stage::GetCurrent().GetSize() * 0.5 );
+  Dali::TouchPoint point( 1, TouchPoint::Down, touchPoint.x, touchPoint.y );
+  Dali::Integration::TouchEvent event;
+  event.AddPoint( point );
+  application.ProcessEvent( event );
+
+  DALI_TEST_CHECK( gTouchCallBackCalled == true );
+  END_TEST;
+}
+
+int UtcDaliActorHoveredSignal(void)
+{
+  TestApplication application;
+
+  gHoverCallBackCalled = false;
+
+  // get the root layer
+  Actor actor = Stage::GetCurrent().GetRootLayer();
+  DALI_TEST_CHECK( gHoverCallBackCalled == false );
+
+  application.SendNotification();
+  application.Render();
+
+  // connect to its hover signal
+  actor.HoveredSignal().Connect( TestCallback3 );
+
+  // simulate a hover event in the middle of the screen
+  Vector2 touchPoint( Stage::GetCurrent().GetSize() * 0.5 );
+  Dali::TouchPoint point( 1, TouchPoint::Motion, touchPoint.x, touchPoint.y );
+  Dali::Integration::HoverEvent event;
+  event.AddPoint( point );
+  application.ProcessEvent( event );
+
+  DALI_TEST_CHECK( gHoverCallBackCalled == true );
+  END_TEST;
+}
+
+int UtcDaliActorOnOffStageSignal(void)
+{
+  tet_infoline("Testing Dali::Actor::OnStageSignal() and OffStageSignal()");
+
+  TestApplication application;
+
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  Actor parent = Actor::New();
+  parent.SetName( "parent" );
+  parent.OnStageSignal().Connect( OnStageCallback );
+  parent.OffStageSignal().Connect( OffStageCallback );
+  // sanity check
+  DALI_TEST_CHECK( gOnStageCallBackCalled == 0 );
+  DALI_TEST_CHECK( gOffStageCallBackCalled == 0 );
+
+  // add parent to stage
+  Stage::GetCurrent().Add( parent );
+  // onstage emitted, offstage not
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+
+  // test adding a child, should get onstage emitted
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  Actor child = Actor::New();
+  child.SetName( "child" );
+  child.OnStageSignal().Connect( OnStageCallback );
+  child.OffStageSignal().Connect( OffStageCallback );
+  parent.Add( child ); // add child
+  // onstage emitted, offstage not
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+
+  // test removing parent from stage
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  Stage::GetCurrent().Remove( parent );
+  // onstage not emitted, offstage is
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 1 ], TEST_LOCATION );
+
+  // test adding parent back to stage
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  Stage::GetCurrent().Add( parent );
+  // onstage emitted, offstage not
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 1 ], TEST_LOCATION );
+
+  // test removing child
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  parent.Remove( child );
+  // onstage not emitted, offstage is
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( "child", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+
+  // test removing parent
+  // clean test data
+  gOnStageCallBackCalled = gOffStageCallBackCalled = 0;
+  gActorNamesOnOffStage.clear();
+
+  Stage::GetCurrent().Remove( parent );
+  // onstage not emitted, offstage is
+  DALI_TEST_EQUALS(  gOnStageCallBackCalled, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( gOffStageCallBackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( "parent", gActorNamesOnOffStage[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorFindChildByName(void)
+{
+  tet_infoline("Testing Dali::Actor::FindChildByName()");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetName( "parent" );
+  Actor first  = Actor::New();
+  first .SetName( "first" );
+  Actor second = Actor::New();
+  second.SetName( "second" );
+
+  parent.Add(first);
+  first.Add(second);
+
+  Actor found = parent.FindChildByName( "foo" );
+  DALI_TEST_CHECK( !found );
+
+  found = parent.FindChildByName( "parent" );
+  DALI_TEST_CHECK( found == parent );
+
+  found = parent.FindChildByName( "first" );
+  DALI_TEST_CHECK( found == first );
+
+  found = parent.FindChildByName( "second" );
+  DALI_TEST_CHECK( found == second );
+  END_TEST;
+}
+
+int UtcDaliActorFindChildById(void)
+{
+  tet_infoline("Testing Dali::Actor::UtcDaliActorFindChildById()");
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  Actor first  = Actor::New();
+  Actor second = Actor::New();
+
+  parent.Add(first);
+  first.Add(second);
+
+  Actor found = parent.FindChildById( 100000 );
+  DALI_TEST_CHECK( !found );
+
+  found = parent.FindChildById( parent.GetId() );
+  DALI_TEST_CHECK( found == parent );
+
+  found = parent.FindChildById( first.GetId() );
+  DALI_TEST_CHECK( found == first );
+
+  found = parent.FindChildById( second.GetId() );
+  DALI_TEST_CHECK( found == second );
+  END_TEST;
+}
+
+int UtcDaliActorHitTest(void)
+{
+  struct HitTestData
+  {
+  public:
+    HitTestData( const Vector3& scale, const Vector2& touchPoint, bool result )
+    : mScale( scale ),
+      mTouchPoint( touchPoint ),
+      mResult( result )
+    {}
+
+    Vector3 mScale;
+    Vector2 mTouchPoint;
+    bool mResult;
+  };
+
+  TestApplication application;
+  tet_infoline(" UtcDaliActorHitTest");
+
+  // Fill a vector with different hit tests.
+  struct HitTestData* hitTestData[] = {
+    //                    scale                     touch point           result
+    new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 289.f, 400.f ), true ),  // touch point close to the right edge (inside)
+    new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 291.f, 400.f ), false ), // touch point close to the right edge (outside)
+    new HitTestData( Vector3( 110.f, 100.f, 1.f ), Vector2( 291.f, 400.f ), true ),  // same point as above with a wider scale. Should be inside.
+    new HitTestData( Vector3( 100.f, 100.f, 1.f ), Vector2( 200.f, 451.f ), false ), // touch point close to the down edge (outside)
+    new HitTestData( Vector3( 100.f, 110.f, 1.f ), Vector2( 200.f, 451.f ), true ),  // same point as above with a wider scale. Should be inside.
+    NULL,
+  };
+
+  // get the root layer
+  Actor actor = Actor::New();
+  actor.SetAnchorPoint( AnchorPoint::CENTER );
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+
+  Stage::GetCurrent().Add( actor );
+
+  gTouchCallBackCalled = false;
+
+  unsigned int index = 0;
+  while( NULL != hitTestData[index] )
+  {
+    actor.SetSize( 1.f, 1.f );
+    actor.SetScale( hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z );
+
+    // flush the queue and render once
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_CHECK( !gTouchCallBackCalled );
+
+    // connect to its touch signal
+    actor.TouchedSignal().Connect(TestCallback);
+
+    Dali::TouchPoint point( 0, TouchPoint::Down, hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y );
+    Dali::Integration::TouchEvent event;
+    event.AddPoint( point );
+
+    // flush the queue and render once
+    application.SendNotification();
+    application.Render();
+    application.ProcessEvent( event );
+
+    DALI_TEST_CHECK( gTouchCallBackCalled == hitTestData[index]->mResult );
+
+    if( gTouchCallBackCalled != hitTestData[index]->mResult )
+      tet_printf("Test failed:\nScale %f %f %f\nTouchPoint %f, %f\nResult %d\n",
+                 hitTestData[index]->mScale.x, hitTestData[index]->mScale.y, hitTestData[index]->mScale.z,
+                 hitTestData[index]->mTouchPoint.x, hitTestData[index]->mTouchPoint.y,
+                 hitTestData[index]->mResult );
+
+    gTouchCallBackCalled = false;
+    ++index;
+  }
+  END_TEST;
+}
+
+int UtcDaliActorSetDrawMode(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorSetDrawModeOverlay");
+
+  Actor a = Actor::New();
+
+  Stage::GetCurrent().Add(a);
+  app.SendNotification();
+  app.Render(0);
+  app.SendNotification();
+  app.Render(1);
+
+  DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Ensure overlay is off by default
+
+  a.SetDrawMode( DrawMode::OVERLAY_2D );
+  app.SendNotification();
+  app.Render(1);
+
+  DALI_TEST_CHECK( DrawMode::OVERLAY_2D == a.GetDrawMode() ); // Check Actor is overlay
+
+  a.SetDrawMode( DrawMode::STENCIL );
+  app.SendNotification();
+  app.Render(1);
+
+  DALI_TEST_CHECK( DrawMode::STENCIL == a.GetDrawMode() ); // Check Actor is stencil, not overlay
+
+  a.SetDrawMode( DrawMode::NORMAL );
+  app.SendNotification();
+  app.Render(1);
+
+  DALI_TEST_CHECK( DrawMode::NORMAL == a.GetDrawMode() ); // Check Actor is not stencil
+  END_TEST;
+}
+
+int UtcDaliActorSetDrawModeOverlayRender(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorSetDrawModeOverlayRender");
+
+  app.SendNotification();
+  app.Render(1);
+
+  std::vector<GLuint> ids;
+  ids.push_back( 8 );   // first rendered actor
+  ids.push_back( 9 );   // second rendered actor
+  ids.push_back( 10 );  // third rendered actor
+  app.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage imageA = BufferImage::New(16, 16);
+  BufferImage imageB = BufferImage::New(16, 16);
+  BufferImage imageC = BufferImage::New(16, 16);
+  ImageActor a = ImageActor::New( imageA );
+  ImageActor b = ImageActor::New( imageB );
+  ImageActor c = ImageActor::New( imageC );
+
+  // Render a,b,c as regular non-overlays. so order will be:
+  // a (8)
+  // b (9)
+  // c (10)
+  Stage::GetCurrent().Add(a);
+  Stage::GetCurrent().Add(b);
+  Stage::GetCurrent().Add(c);
+
+  app.SendNotification();
+  app.Render(1);
+
+  // Should be 3 textures changes.
+  const std::vector<GLuint>& boundTextures = app.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+  typedef std::vector<GLuint>::size_type TextureSize;
+  DALI_TEST_EQUALS( boundTextures.size(), static_cast<TextureSize>( 3 ), TEST_LOCATION );
+  if( boundTextures.size() == 3 )
+  {
+    DALI_TEST_CHECK( boundTextures[0] == 8u );
+    DALI_TEST_CHECK( boundTextures[1] == 9u );
+    DALI_TEST_CHECK( boundTextures[2] == 10u );
+  }
+
+  // Now texture ids have been set, we can monitor their render order.
+  // render a as an overlay (last), so order will be:
+  // b (9)
+  // c (10)
+  // a (8)
+  a.SetDrawMode( DrawMode::OVERLAY_2D );
+  app.GetGlAbstraction().ClearBoundTextures();
+
+  app.SendNotification();
+  app.Render(1);
+
+  // Should be 3 texture changes.
+  DALI_TEST_EQUALS( boundTextures.size(), static_cast<TextureSize>(3), TEST_LOCATION );
+  if( boundTextures.size() == 3 )
+  {
+    DALI_TEST_CHECK( boundTextures[0] == 9u );
+    DALI_TEST_CHECK( boundTextures[1] == 10u );
+    DALI_TEST_CHECK( boundTextures[2] == 8u );
+  }
+  END_TEST;
+}
+
+int UtcDaliActorGetCurrentWorldMatrix(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorGetCurrentWorldMatrix");
+
+  Actor parent = Actor::New();
+  parent.SetParentOrigin(ParentOrigin::CENTER);
+  parent.SetAnchorPoint(AnchorPoint::CENTER);
+  Vector3 parentPosition( 10.0f, 20.0f, 30.0f);
+  Radian rotationAngle(Degree(85.0f));
+  Quaternion parentRotation(rotationAngle, Vector3::ZAXIS);
+  Vector3 parentScale( 1.0f, 2.0f, 3.0f );
+  parent.SetPosition( parentPosition );
+  parent.SetOrientation( parentRotation );
+  parent.SetScale( parentScale );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  Vector3 childPosition( 0.0f, 0.0f, 100.0f );
+  Radian childRotationAngle(Degree(23.0f));
+  Quaternion childRotation( childRotationAngle, Vector3::YAXIS );
+  Vector3 childScale( 2.0f, 2.0f, 2.0f );
+  child.SetPosition( childPosition );
+  child.SetOrientation( childRotation );
+  child.SetScale( childScale );
+  parent.Add( child );
+
+  // The actors should not have a world matrix yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
+
+  app.SendNotification();
+  app.Render(0);
+  app.Render();
+  app.SendNotification();
+
+  Matrix parentMatrix(false);
+  parentMatrix.SetTransformComponents(parentScale, parentRotation, parentPosition);
+
+  Vector3 childWorldPosition = parentPosition + parentRotation * parentScale * childPosition;
+  Quaternion childWorldRotation = parentRotation * childRotation;
+  Vector3 childWorldScale = parentScale * childScale;
+
+  Matrix childWorldMatrix(false);
+  childWorldMatrix.SetTransformComponents(childWorldScale, childWorldRotation, childWorldPosition);
+
+  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), parentMatrix, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), childWorldMatrix, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+
+
+int UtcDaliActorConstrainedToWorldMatrix(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorConstrainedToWorldMatrix");
+
+  Actor parent = Actor::New();
+  parent.SetParentOrigin(ParentOrigin::CENTER);
+  parent.SetAnchorPoint(AnchorPoint::CENTER);
+  Vector3 parentPosition( 10.0f, 20.0f, 30.0f);
+  Radian rotationAngle(Degree(85.0f));
+  Quaternion parentRotation(rotationAngle, Vector3::ZAXIS);
+  Vector3 parentScale( 1.0f, 2.0f, 3.0f );
+  parent.SetPosition( parentPosition );
+  parent.SetOrientation( parentRotation );
+  parent.SetScale( parentScale );
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  Constraint posConstraint = Constraint::New<Vector3>( child, Actor::Property::POSITION, PositionComponentConstraint() );
+  posConstraint.AddSource( Source( parent, Actor::Property::WORLD_MATRIX ) );
+  posConstraint.Apply();
+
+  Stage::GetCurrent().Add( child );
+
+  // The actors should not have a world matrix yet
+  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentWorldMatrix(), Matrix::IDENTITY, 0.001, TEST_LOCATION );
+
+  app.SendNotification();
+  app.Render(0);
+  app.Render();
+  app.SendNotification();
+
+  Matrix parentMatrix(false);
+  parentMatrix.SetTransformComponents(parentScale, parentRotation, parentPosition);
+
+  DALI_TEST_EQUALS( parent.GetCurrentWorldMatrix(), parentMatrix, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( child.GetCurrentPosition(), parent.GetCurrentPosition(), 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorUnparent(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorUnparent");
+
+  Actor parent = Actor::New();
+  Stage::GetCurrent().Add( parent );
+
+  Actor child = Actor::New();
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+  DALI_TEST_CHECK( !child.GetParent() );
+
+  // Test that calling Unparent with no parent is a NOOP
+  child.Unparent();
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+  DALI_TEST_CHECK( !child.GetParent() );
+
+  // Test that Unparent works
+  parent.Add( child );
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+  DALI_TEST_CHECK( parent == child.GetParent() );
+
+  child.Unparent();
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+  DALI_TEST_CHECK( !child.GetParent() );
+
+  // Test that UnparentAndReset works
+  parent.Add( child );
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 1u, TEST_LOCATION );
+  DALI_TEST_CHECK( parent == child.GetParent() );
+
+  UnparentAndReset( child );
+
+  DALI_TEST_EQUALS( parent.GetChildCount(), 0u, TEST_LOCATION );
+  DALI_TEST_CHECK( !child );
+
+  // Test that UnparentAndReset is a NOOP with empty handle
+  UnparentAndReset( child );
+
+  DALI_TEST_CHECK( !child );
+  END_TEST;
+}
+
+int UtcDaliActorGetChildAt(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorGetChildAt");
+
+  Actor parent = Actor::New();
+  Stage::GetCurrent().Add( parent );
+
+  Actor child0 = Actor::New();
+  parent.Add( child0 );
+
+  Actor child1 = Actor::New();
+  parent.Add( child1 );
+
+  Actor child2 = Actor::New();
+  parent.Add( child2 );
+
+  DALI_TEST_EQUALS( parent.GetChildAt( 0 ), child0, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetChildAt( 1 ), child1, TEST_LOCATION );
+  DALI_TEST_EQUALS( parent.GetChildAt( 2 ), child2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliActorSetGetOverlay(void)
+{
+  TestApplication app;
+  tet_infoline(" UtcDaliActorSetGetOverlay");
+
+  Actor parent = Actor::New();
+  parent.SetDrawMode(DrawMode::OVERLAY_2D );
+  DALI_TEST_CHECK( parent.GetDrawMode() == DrawMode::OVERLAY_2D );
+  END_TEST;
+}
+
+
+int UtcDaliActorCreateDestroy(void)
+{
+  Actor* actor = new Actor;
+  DALI_TEST_CHECK( actor );
+  delete actor;
+  END_TEST;
+}
+
+namespace
+{
+struct PropertyStringIndex
+{
+  const char * const name;
+  const Property::Index index;
+  const Property::Type type;
+};
+
+const PropertyStringIndex PROPERTY_TABLE[] =
+{
+  { "parent-origin",            Actor::Property::PARENT_ORIGIN,            Property::VECTOR3     },
+  { "parent-origin-x",          Actor::Property::PARENT_ORIGIN_X,          Property::FLOAT       },
+  { "parent-origin-y",          Actor::Property::PARENT_ORIGIN_Y,          Property::FLOAT       },
+  { "parent-origin-z",          Actor::Property::PARENT_ORIGIN_Z,          Property::FLOAT       },
+  { "anchor-point",             Actor::Property::ANCHOR_POINT,             Property::VECTOR3     },
+  { "anchor-point-x",           Actor::Property::ANCHOR_POINT_X,           Property::FLOAT       },
+  { "anchor-point-y",           Actor::Property::ANCHOR_POINT_Y,           Property::FLOAT       },
+  { "anchor-point-z",           Actor::Property::ANCHOR_POINT_Z,           Property::FLOAT       },
+  { "size",                     Actor::Property::SIZE,                     Property::VECTOR3     },
+  { "size-width",               Actor::Property::SIZE_WIDTH,               Property::FLOAT       },
+  { "size-height",              Actor::Property::SIZE_HEIGHT,              Property::FLOAT       },
+  { "size-depth",               Actor::Property::SIZE_DEPTH,               Property::FLOAT       },
+  { "position",                 Actor::Property::POSITION,                 Property::VECTOR3     },
+  { "position-x",               Actor::Property::POSITION_X,               Property::FLOAT       },
+  { "position-y",               Actor::Property::POSITION_Y,               Property::FLOAT       },
+  { "position-z",               Actor::Property::POSITION_Z,               Property::FLOAT       },
+  { "world-position",           Actor::Property::WORLD_POSITION,           Property::VECTOR3     },
+  { "world-position-x",         Actor::Property::WORLD_POSITION_X,         Property::FLOAT       },
+  { "world-position-y",         Actor::Property::WORLD_POSITION_Y,         Property::FLOAT       },
+  { "world-position-z",         Actor::Property::WORLD_POSITION_Z,         Property::FLOAT       },
+  { "orientation",              Actor::Property::ORIENTATION,              Property::ROTATION    },
+  { "world-orientation",        Actor::Property::WORLD_ORIENTATION,        Property::ROTATION    },
+  { "scale",                    Actor::Property::SCALE,                    Property::VECTOR3     },
+  { "scale-x",                  Actor::Property::SCALE_X,                  Property::FLOAT       },
+  { "scale-y",                  Actor::Property::SCALE_Y,                  Property::FLOAT       },
+  { "scale-z",                  Actor::Property::SCALE_Z,                  Property::FLOAT       },
+  { "world-scale",              Actor::Property::WORLD_SCALE,              Property::VECTOR3     },
+  { "visible",                  Actor::Property::VISIBLE,                  Property::BOOLEAN     },
+  { "color",                    Actor::Property::COLOR,                    Property::VECTOR4     },
+  { "color-red",                Actor::Property::COLOR_RED,                Property::FLOAT       },
+  { "color-green",              Actor::Property::COLOR_GREEN,              Property::FLOAT       },
+  { "color-blue",               Actor::Property::COLOR_BLUE,               Property::FLOAT       },
+  { "color-alpha",              Actor::Property::COLOR_ALPHA,              Property::FLOAT       },
+  { "world-color",              Actor::Property::WORLD_COLOR,              Property::VECTOR4     },
+  { "world-matrix",             Actor::Property::WORLD_MATRIX,             Property::MATRIX      },
+  { "name",                     Actor::Property::NAME,                     Property::STRING      },
+  { "sensitive",                Actor::Property::SENSITIVE,                Property::BOOLEAN     },
+  { "leave-required",           Actor::Property::LEAVE_REQUIRED,           Property::BOOLEAN     },
+  { "inherit-orientation",      Actor::Property::INHERIT_ORIENTATION,      Property::BOOLEAN     },
+  { "inherit-scale",            Actor::Property::INHERIT_SCALE,            Property::BOOLEAN     },
+  { "color-mode",               Actor::Property::COLOR_MODE,               Property::STRING      },
+  { "position-inheritance",     Actor::Property::POSITION_INHERITANCE,     Property::STRING      },
+  { "draw-mode",                Actor::Property::DRAW_MODE,                Property::STRING      },
+  { "size-mode-factor",         Actor::Property::SIZE_MODE_FACTOR,         Property::VECTOR3     },
+  { "width-resize-policy",      Actor::Property::WIDTH_RESIZE_POLICY,      Property::STRING      },
+  { "height-resize-policy",     Actor::Property::HEIGHT_RESIZE_POLICY,     Property::STRING      },
+  { "size-scale-policy",        Actor::Property::SIZE_SCALE_POLICY,        Property::STRING      },
+  { "width-for-height",         Actor::Property::WIDTH_FOR_HEIGHT,         Property::BOOLEAN     },
+  { "height-for-width",         Actor::Property::HEIGHT_FOR_WIDTH,         Property::BOOLEAN     },
+  { "padding",                  Actor::Property::PADDING,                  Property::VECTOR4     },
+  { "minimum-size",             Actor::Property::MINIMUM_SIZE,             Property::VECTOR2     },
+  { "maximum-size",             Actor::Property::MAXIMUM_SIZE,             Property::VECTOR2     },
+};
+const unsigned int PROPERTY_TABLE_COUNT = sizeof( PROPERTY_TABLE ) / sizeof( PROPERTY_TABLE[0] );
+} // unnamed namespace
+
+int UtcDaliActorProperties(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  for ( unsigned int i = 0; i < PROPERTY_TABLE_COUNT; ++i )
+  {
+    tet_printf( "Checking %s == %d\n", PROPERTY_TABLE[i].name, PROPERTY_TABLE[i].index );
+    DALI_TEST_EQUALS( actor.GetPropertyName( PROPERTY_TABLE[i].index ), PROPERTY_TABLE[i].name, TEST_LOCATION );
+    DALI_TEST_EQUALS( actor.GetPropertyIndex( PROPERTY_TABLE[i].name ), PROPERTY_TABLE[i].index, TEST_LOCATION );
+    DALI_TEST_EQUALS( actor.GetPropertyType( PROPERTY_TABLE[i].index ), PROPERTY_TABLE[i].type, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_ResizePolicies(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Defaults
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_RESIZE_POLICY ).Get< std::string >(), "USE_NATURAL_SIZE", TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_RESIZE_POLICY ).Get< std::string >(), "USE_NATURAL_SIZE", TEST_LOCATION );
+
+  // Set resize policy for all dimensions
+  actor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i)
+  {
+    DALI_TEST_EQUALS( actor.GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) ), ResizePolicy::USE_NATURAL_SIZE, TEST_LOCATION );
+  }
+
+  // Set individual dimensions
+  const char* const widthPolicy = "FILL_TO_PARENT";
+  const char* const heightPolicy = "FIXED";
+
+  actor.SetProperty( Actor::Property::WIDTH_RESIZE_POLICY, widthPolicy );
+  actor.SetProperty( Actor::Property::HEIGHT_RESIZE_POLICY, heightPolicy );
+
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_RESIZE_POLICY ).Get< std::string >(), widthPolicy, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_RESIZE_POLICY ).Get< std::string >(), heightPolicy, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_SizeScalePolicy(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Defaults
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), "USE_SIZE_SET", TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetSizeScalePolicy(), SizeScalePolicy::USE_SIZE_SET, TEST_LOCATION );
+
+  SizeScalePolicy::Type policy = SizeScalePolicy::FILL_WITH_ASPECT_RATIO;
+  actor.SetSizeScalePolicy( policy );
+  DALI_TEST_EQUALS( actor.GetSizeScalePolicy(), policy, TEST_LOCATION );
+
+  // Set
+  const char* const policy1 = "FIT_WITH_ASPECT_RATIO";
+  const char* const policy2 = "FILL_WITH_ASPECT_RATIO";
+
+  actor.SetProperty( Actor::Property::SIZE_SCALE_POLICY, policy1 );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), policy1, TEST_LOCATION );
+
+  actor.SetProperty( Actor::Property::SIZE_SCALE_POLICY, policy2 );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_SCALE_POLICY ).Get< std::string >(), policy2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_SizeModeFactor(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Defaults
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_MODE_FACTOR ).Get< Vector3 >(), Vector3( 1.0f, 1.0f, 1.0f ), TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetSizeModeFactor(), Vector3( 1.0f, 1.0f, 1.0f ), TEST_LOCATION );
+
+  Vector3 sizeMode( 1.0f, 2.0f, 3.0f );
+  actor.SetSizeModeFactor( sizeMode );
+  DALI_TEST_EQUALS( actor.GetSizeModeFactor(), sizeMode, TEST_LOCATION );
+
+  // Set
+  Vector3 sizeMode1( 2.0f, 3.0f, 4.0f );
+
+  actor.SetProperty( Actor::Property::SIZE_MODE_FACTOR, sizeMode1 );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::SIZE_MODE_FACTOR ).Get< Vector3 >(), sizeMode1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_DimensionDependency(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Defaults
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_FOR_WIDTH ).Get< bool >(), false, TEST_LOCATION );
+
+  // Set
+  actor.SetProperty( Actor::Property::WIDTH_FOR_HEIGHT, true );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), true, TEST_LOCATION );
+
+  actor.SetProperty( Actor::Property::HEIGHT_FOR_WIDTH, true );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::HEIGHT_FOR_WIDTH ).Get< bool >(), true, TEST_LOCATION );
+
+  // Test setting another resize policy
+  actor.SetProperty( Actor::Property::WIDTH_RESIZE_POLICY, "FIXED" );
+  DALI_TEST_EQUALS( actor.GetProperty( Actor::Property::WIDTH_FOR_HEIGHT ).Get< bool >(), false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_Padding(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Data
+  Vector4 padding( 1.0f, 2.0f, 3.0f, 4.0f );
+
+  // PADDING
+  actor.SetProperty( Actor::Property::PADDING, padding );
+  Vector4 paddingResult = actor.GetProperty( Actor::Property::PADDING ).Get< Vector4 >();
+
+  DALI_TEST_EQUALS( paddingResult, padding, Math::MACHINE_EPSILON_0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRelayoutProperties_MinimumMaximumSize(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Data
+  Vector2 minSize( 1.0f, 2.0f );
+
+  actor.SetProperty( Actor::Property::MINIMUM_SIZE, minSize );
+  Vector2 resultMin = actor.GetProperty( Actor::Property::MINIMUM_SIZE ).Get< Vector2 >();
+
+  DALI_TEST_EQUALS( resultMin, minSize, Math::MACHINE_EPSILON_0, TEST_LOCATION );
+
+  Vector2 maxSize( 3.0f, 4.0f );
+
+  actor.SetProperty( Actor::Property::MAXIMUM_SIZE, maxSize );
+  Vector2 resultMax = actor.GetProperty( Actor::Property::MAXIMUM_SIZE ).Get< Vector2 >();
+
+  DALI_TEST_EQUALS( resultMax, maxSize, Math::MACHINE_EPSILON_0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorGetHeightForWidth(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_EQUALS( actor.GetHeightForWidth( 1.0f ), 1.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorGetWidthForHeight(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_EQUALS( actor.GetWidthForHeight( 1.0f ), 1.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorGetRelayoutSize(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  // Add actor to stage
+  Stage::GetCurrent().Add( actor );
+
+  DALI_TEST_EQUALS( actor.GetRelayoutSize( Dimension::WIDTH ), 0.0f, TEST_LOCATION );
+
+  actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
+  actor.SetSize( Vector2( 1.0f, 0.0f ) );
+
+  // Flush the queue and render once
+  app.SendNotification();
+  app.Render();
+
+  DALI_TEST_EQUALS( actor.GetRelayoutSize( Dimension::WIDTH ), 1.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorSetPadding(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  Padding padding;
+  actor.GetPadding( padding );
+
+  DALI_TEST_EQUALS( padding.left, 0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.right, 0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.bottom, 0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.top, 0.0f, TEST_LOCATION );
+
+  Padding padding2( 1.0f, 2.0f, 3.0f, 4.0f );
+  actor.SetPadding( padding2 );
+
+  actor.GetPadding( padding );
+
+  DALI_TEST_EQUALS( padding.left, padding2.left, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.right, padding2.right, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.bottom, padding2.bottom, TEST_LOCATION );
+  DALI_TEST_EQUALS( padding.top, padding2.top, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorSetMinimumSize(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  Vector2 size = actor.GetMinimumSize();
+
+  DALI_TEST_EQUALS( size.width, 0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( size.height, 0.0f, TEST_LOCATION );
+
+  Vector2 size2( 1.0f, 2.0f );
+  actor.SetMinimumSize( size2 );
+
+  size = actor.GetMinimumSize();
+
+  DALI_TEST_EQUALS( size.width, size2.width, TEST_LOCATION );
+  DALI_TEST_EQUALS( size.height, size2.height, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorSetMaximumSize(void)
+{
+  TestApplication app;
+
+  Actor actor = Actor::New();
+
+  Vector2 size = actor.GetMaximumSize();
+
+  DALI_TEST_EQUALS( size.width, FLT_MAX, TEST_LOCATION );
+  DALI_TEST_EQUALS( size.height, FLT_MAX, TEST_LOCATION );
+
+  Vector2 size2( 1.0f, 2.0f );
+  actor.SetMaximumSize( size2 );
+
+  size = actor.GetMaximumSize();
+
+  DALI_TEST_EQUALS( size.width, size2.width, TEST_LOCATION );
+  DALI_TEST_EQUALS( size.height, size2.height, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorOnRelayoutSignal(void)
+{
+  tet_infoline("Testing Dali::Actor::OnRelayoutSignal()");
+
+  TestApplication application;
+
+  // Clean test data
+  gOnRelayoutCallBackCalled = 0;
+  gActorNamesRelayout.clear();
+
+  Actor actor = Actor::New();
+  actor.SetName( "actor" );
+  actor.OnRelayoutSignal().Connect( OnRelayoutCallback );
+
+  // Sanity check
+  DALI_TEST_CHECK( gOnRelayoutCallBackCalled == 0 );
+
+  // Add actor to stage
+  Stage::GetCurrent().Add( actor );
+
+  actor.SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
+  actor.SetSize( Vector2( 1.0f, 2.0 ) );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // OnRelayout emitted
+  DALI_TEST_EQUALS(  gOnRelayoutCallBackCalled, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( "actor", gActorNamesRelayout[ 0 ], TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliActorGetHierachyDepth(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Actor::GetHierarchyDepth()");
+
+
+  /* Build tree of actors:
+   *
+   *                      Depth
+   *
+   *       A (parent)       1
+   *      / \
+   *     B   C              2`
+   *    / \   \
+   *   D   E   F            3
+   *
+   * GetHierarchyDepth should return 1 for A, 2 for B and C, and 3 for D, E and F.
+   */
+  Stage stage( Stage::GetCurrent() );
+
+  Actor actorA = Actor::New();
+  Actor actorB = Actor::New();
+  Actor actorC = Actor::New();
+  Actor actorD = Actor::New();
+  Actor actorE = Actor::New();
+  Actor actorF = Actor::New();
+
+  //Test that root actor has depth equal 0
+  DALI_TEST_EQUALS( 0, stage.GetRootLayer().GetHierarchyDepth(), TEST_LOCATION );
+
+  //Test actors return depth -1 when not connected to the tree
+  DALI_TEST_EQUALS( -1, actorA.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorC.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorF.GetHierarchyDepth(), TEST_LOCATION );
+
+  //Create the hierarchy
+  stage.Add( actorA );
+  actorA.Add( actorB );
+  actorA.Add( actorC );
+  actorB.Add( actorD );
+  actorB.Add( actorE );
+  actorC.Add( actorF );
+
+  //Test actors return correct depth
+  DALI_TEST_EQUALS( 1, actorA.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 2, actorB.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 2, actorC.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3, actorD.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3, actorE.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3, actorF.GetHierarchyDepth(), TEST_LOCATION );
+
+  //Removing actorB from the hierarchy. actorB, actorD and actorE should now have depth equal -1
+  actorA.Remove( actorB );
+
+  DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION );
+
+  //Removing actorA from the stage. All actors should have depth equal -1
+  stage.Remove( actorA );
+
+  DALI_TEST_EQUALS( -1, actorA.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorB.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorC.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorD.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorE.GetHierarchyDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( -1, actorF.GetHierarchyDepth(), TEST_LOCATION );
+
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-AlphaFunction.cpp b/automated-tests/src/dali/utc-Dali-AlphaFunction.cpp
new file mode 100644 (file)
index 0000000..858a3eb
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+float customAlphaFunction( float progress )
+{
+  return progress;
+}
+
+void utc_dali_alpha_function_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_alpha_function_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliAlphaFunctionDefaultConstructorP(void)
+{
+  TestApplication application;
+  AlphaFunction alpha;
+
+  //Should return the default alpha function
+  DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION);
+
+  //Check the mode is BUILTIN_FUNCTION
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionConstructorFromBuiltinP(void)
+{
+  TestApplication application;
+
+  //Construct the alpha function with a built-in function
+  AlphaFunction alpha( AlphaFunction::EASE_IN_OUT);
+
+  //Check if the built-in alpha function is EASE_IN_OUT
+  DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::EASE_IN_OUT, TEST_LOCATION);
+
+  //Check the mode is BUILTIN_FUNCTION
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionConstructorFromFunctionPointerdP(void)
+{
+  TestApplication application;
+
+  //Construct the alpha function with a function pointer
+  AlphaFunction alpha( &customAlphaFunction );
+
+  //Check that the custom function points to the custom alpha function
+  DALI_TEST_EQUALS( alpha.GetCustomFunction(), &customAlphaFunction, TEST_LOCATION);
+
+  //Check the mode is CUSTOM_FUNCTION
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION);
+
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionConstructorFromControlPointsP(void)
+{
+  TestApplication application;
+
+  //Construct the alpha function with two control points
+  Vector2 controlPoint0 = Vector2(0.0f,1.0f);
+  Vector2 controlPoint1 = Vector2(1.0f,0.0f);
+  AlphaFunction alpha(controlPoint0,controlPoint1);
+
+  //Check if the control points have the correct value
+  Vector4 controlPoints = alpha.GetBezierControlPoints();
+  DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), controlPoint0, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), controlPoint1, TEST_LOCATION);
+
+  //Check the mode is BEZIER
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionConstructorFromControlPointsN(void)
+{
+  TestApplication application;
+
+  //Construct the alpha function with two control points
+  Vector2 controlPoint0 = Vector2(-10.0f,1.0f);
+  Vector2 controlPoint1 = Vector2(10.0f,0.0f);
+  AlphaFunction alpha(controlPoint0,controlPoint1);
+
+  //x components of the control points should have been clamped to [0,1] to ensure the curve is monotonic
+  Vector4 controlPoints = alpha.GetBezierControlPoints();
+  DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), Vector2(0.0f,1.0f), TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), Vector2(1.0f,0.0f), TEST_LOCATION);
+
+  //Check the mode is BEZIER
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionGetBuiltinFunctionP(void)
+{
+  TestApplication application;
+  AlphaFunction alpha( AlphaFunction::EASE_IN);
+
+  //Check if the builtin alpha function is EASE_IN
+  DALI_TEST_EQUALS( alpha.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION);
+
+  //Check the mode is BUILTIN_FUNCTION
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionGetCustomFunctionP(void)
+{
+  TestApplication application;
+  AlphaFunction alpha( &customAlphaFunction );
+
+  //Check that the custom function points to the custom alpha function
+  DALI_TEST_EQUALS( alpha.GetCustomFunction(), &customAlphaFunction, TEST_LOCATION);
+
+  //Check the mode is CUSTOM_FUNCTION
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionGetControlPointsFunctionP(void)
+{
+  TestApplication application;
+
+  Vector2 controlPoint0 = Vector2(0.0f,1.0f);
+  Vector2 controlPoint1 = Vector2(1.0f,0.0f);
+  AlphaFunction alpha( controlPoint0,controlPoint1 );
+
+  //Check if the control points have the correct value
+  Vector4 controlPoints = alpha.GetBezierControlPoints();
+  DALI_TEST_EQUALS( Vector2(controlPoints.x,controlPoints.y), controlPoint0, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(controlPoints.z,controlPoints.w), controlPoint1, TEST_LOCATION);
+
+  //Check the mode is BEZIER
+  DALI_TEST_EQUALS( alpha.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionGetModeP(void)
+{
+  TestApplication application;
+
+  //Create alpha function using a built-in function
+  AlphaFunction alphaBuiltin( AlphaFunction::EASE_IN);
+
+  //Check the mode is BUILTIN_FUNCTION
+  DALI_TEST_EQUALS( alphaBuiltin.GetMode(), AlphaFunction::BUILTIN_FUNCTION, TEST_LOCATION);
+
+  //Create alpha function with pointer to function
+  AlphaFunction alphaCustom( &customAlphaFunction );
+  //Check the mode is CUSTOM_FUNCTION
+  DALI_TEST_EQUALS( alphaCustom.GetMode(), AlphaFunction::CUSTOM_FUNCTION, TEST_LOCATION);
+
+  //Create alpha function with control points
+  Vector2 controlPoint0 = Vector2(0.0f,1.0f);
+  Vector2 controlPoint1 = Vector2(1.0f,0.0f);
+  AlphaFunction alphaBezier( controlPoint0,controlPoint1 );
+  //Check the mode is BEZIER
+  DALI_TEST_EQUALS( alphaBezier.GetMode(), AlphaFunction::BEZIER, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAlphaFunctionBezier(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(0.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(1.0f);
+
+  Vector2 controlPoint0 = Vector2(0.25f,0.5f);
+  Vector2 controlPoint1 = Vector2(0.75f,0.5f);
+  animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction(controlPoint0,controlPoint1));
+
+  // Start the animation
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+  application.SendNotification();
+  float epsilon(0.01f);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), 0.271964f, epsilon, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*40% progress*/);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), 0.432387f, epsilon, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*60% progress*/);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), 0.567613f, epsilon, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*80% progress*/);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), 0.728037f, epsilon, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-AngleAxis.cpp b/automated-tests/src/dali/utc-Dali-AngleAxis.cpp
new file mode 100644 (file)
index 0000000..515ead5
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+void utc_dali_angle_axis_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_angle_axis_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+
+int UtcDaliAngleAxisNew01(void)
+{
+  TestApplication application;
+
+  AngleAxis a;
+  DALI_TEST_EQUALS(float(a.angle), 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(a.axis, Vector3(0.0f, 0.0f, 0.0f), 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+
+
+int UtcDaliAngleAxisNew02(void)
+{
+  TestApplication application;
+
+  Degree d(75.0f);
+  AngleAxis a(d, Vector3::XAXIS);
+
+  DALI_TEST_EQUALS(a.angle, Radian(d), 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(a.axis, Vector3::XAXIS, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliAngleAxisNew03(void)
+{
+  TestApplication application;
+
+  Radian r(Math::PI_2);
+  AngleAxis a(r, Vector3::ZAXIS);
+
+  // AngleAxis stores its angle as a degree, so should only do degree comparison.
+  DALI_TEST_EQUALS(a.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(a.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAngleAxisAssign(void)
+{
+  TestApplication application;
+
+  Radian r(Math::PI_2);
+  AngleAxis a(r, Vector3::ZAXIS);
+
+  AngleAxis b = a;
+
+  // AngleAxis stores its angle as a degree, so should only do degree comparison.
+  DALI_TEST_EQUALS(b.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(b.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAngleAxisCopy(void)
+{
+  TestApplication application;
+
+  Radian r(Math::PI_2);
+  AngleAxis a(r, Vector3::ZAXIS);
+  AngleAxis b(a);
+
+  // AngleAxis stores its angle as a degree, so should only do degree comparison.
+  DALI_TEST_EQUALS(b.angle, Radian(Math::PI_2), 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(b.axis, Vector3::ZAXIS, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAngleAxisEqual(void)
+{
+  TestApplication application;
+
+  Radian r(Math::PI_2);
+  AngleAxis a(r, Vector3::ZAXIS);
+  AngleAxis b(a);
+
+  tet_result((a == b) ? TET_PASS : TET_FAIL);
+
+  b.axis = Vector3::YAXIS;
+  tet_result(!(a == b) ? TET_PASS : TET_FAIL);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Animation.cpp b/automated-tests/src/dali/utc-Dali-Animation.cpp
new file mode 100644 (file)
index 0000000..25f5235
--- /dev/null
@@ -0,0 +1,8925 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using std::max;
+using namespace Dali;
+
+void utc_dali_animation_startuP(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_animation_cleanuP(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+static const float ROTATION_EPSILON = 0.0001f;
+static const float VECTOR4_EPSILON = 0.0001f;
+
+// Functor to test whether a Finish signal is emitted
+struct AnimationFinishCheck
+{
+  AnimationFinishCheck(bool& signalReceived)
+  : mSignalReceived(signalReceived)
+  {
+  }
+
+  void operator()(Animation& animation)
+  {
+    mSignalReceived = true;
+  }
+
+  void Reset()
+  {
+    mSignalReceived = false;
+  }
+
+  void CheckSignalReceived()
+  {
+    if (!mSignalReceived)
+    {
+      tet_printf("Expected Finish signal was not received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  void CheckSignalNotReceived()
+  {
+    if (mSignalReceived)
+    {
+      tet_printf("Unexpected Finish signal was received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  bool& mSignalReceived; // owned by individual tests
+};
+
+} // anon namespace
+
+int UtcDaliAnimationConstructorP(void)
+{
+  TestApplication application;
+
+  Animation animation;
+
+  DALI_TEST_CHECK( !animation );
+  END_TEST;
+}
+
+int UtcDaliAnimationNewP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New( 1.0f );
+
+  DALI_TEST_CHECK(animation);
+  END_TEST;
+}
+
+int UtcDaliAnimationNewN(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New( -1.0f );
+
+  DALI_TEST_CHECK(animation);
+  DALI_TEST_EQUALS(animation.GetDuration(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAnimationDownCastP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::Animation::DownCast()");
+
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  BaseHandle object(animation);
+
+  Animation animation2 = Animation::DownCast(object);
+  DALI_TEST_CHECK(animation2);
+
+  Animation animation3 = DownCast< Animation >(object);
+  DALI_TEST_CHECK(animation3);
+  END_TEST;
+}
+
+int UtcDaliAnimationDownCastN(void)
+{
+  TestApplication application;
+
+  BaseHandle unInitializedObject;
+
+  Animation animation1 = Animation::DownCast( unInitializedObject );
+  DALI_TEST_CHECK( !animation1 );
+
+  Animation animation2 = DownCast< Animation >( unInitializedObject );
+  DALI_TEST_CHECK( !animation2 );
+  END_TEST;
+}
+
+int UtcDaliAnimationCopyConstructorP(void)
+{
+  TestApplication application;
+
+  // Initialize an object, ref count == 1
+  Animation animation = Animation::New( 1.0f );
+
+  Animation copy( animation );
+  DALI_TEST_CHECK( copy );
+
+  DALI_TEST_CHECK( copy.GetDuration() == animation.GetDuration() );
+  END_TEST;
+}
+
+int UtcDaliAnimationAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New( 1.0f );
+
+  Animation copy = animation;
+  DALI_TEST_CHECK( copy );
+
+  DALI_TEST_CHECK( animation == copy );
+
+  DALI_TEST_CHECK( copy.GetDuration() == animation.GetDuration() );
+  END_TEST;
+}
+
+int UtcDaliAnimationSetDurationP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION);
+
+  // Start the animation
+  Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  application.Render(2u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Restart the animation, with a different duration
+  finishCheck.Reset();
+  actor.SetPosition(Vector3::ZERO);
+  durationSeconds = 3.5f;
+  animation.SetDuration(durationSeconds);
+  DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) - 1u/*just less than the animation duration*/);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  application.Render(2u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationSetDurationN(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New( 1.0f );
+  DALI_TEST_EQUALS( animation.GetDuration(), 1.0f, TEST_LOCATION );
+
+  animation.SetDuration( -1.0f );
+  DALI_TEST_EQUALS( animation.GetDuration(), 0.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationGetDurationP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  DALI_TEST_EQUALS(animation.GetDuration(), 1.0f, TEST_LOCATION);
+
+  animation.SetDuration(2.0f);
+  DALI_TEST_EQUALS(animation.GetDuration(), 2.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAnimationSetLoopingP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.SetLooping(true);
+  DALI_TEST_CHECK(animation.IsLooping());
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+
+  // Loop 5 times
+  float intervalSeconds = 0.25f;
+  float progress = 0.0f;
+  for (int iterations = 0; iterations < 5;)
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+    progress += intervalSeconds;
+    DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION );
+
+    if (progress >= 1.0f)
+    {
+      progress = progress - 1.0f;
+      ++iterations;
+    }
+  }
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  animation.SetLooping(false);
+  DALI_TEST_CHECK(!animation.IsLooping());
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationIsLoopingP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  DALI_TEST_CHECK(!animation.IsLooping());
+
+  animation.SetLooping(true);
+  DALI_TEST_CHECK(animation.IsLooping());
+  END_TEST;
+}
+
+int UtcDaliAnimationSetEndActioN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::Bake);
+
+  Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Go back to the start
+  actor.SetPosition(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Test BakeFinal, animate again, for half the duration
+  finishCheck.Reset();
+  animation.SetEndAction(Animation::BakeFinal);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::BakeFinal);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f*0.5f) /*half of the animation duration*/);
+
+  // Stop the animation early
+  animation.Stop();
+
+  // We did NOT expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( targetPosition * 0.5f, actor.GetCurrentPosition(), VECTOR4_EPSILON, TEST_LOCATION );
+
+  // The position should be same with target position in the next frame
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Go back to the start
+  actor.SetPosition(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Test EndAction::Discard, animate again, but don't bake this time
+  finishCheck.Reset();
+  animation.SetEndAction(Animation::Discard);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::Discard);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // The position should be discarded in the next frame
+  application.Render(0);
+  DALI_TEST_EQUALS( Vector3::ZERO/*discarded*/, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( Vector3::ZERO, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationGetEndActionP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::Bake);
+
+  animation.SetEndAction(Animation::Discard);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::Discard);
+
+  animation.SetEndAction(Animation::BakeFinal);
+  DALI_TEST_CHECK(animation.GetEndAction() == Animation::BakeFinal);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationSetDisconnectActionP(void)
+{
+  TestApplication application;
+  Stage stage( Stage::GetCurrent() );
+
+  // Default: BakeFinal
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal);
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+    // Start the animation
+    animation.Play();
+
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0.5f*1000.0f)/*Only half the animation*/);
+
+    actor.Unparent();
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  }
+
+  // Bake
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    animation.SetDisconnectAction( Animation::Bake );
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+    // Start the animation
+    animation.Play();
+
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0.5f*1000.0f)/*Only half the animation*/);
+
+    actor.Unparent();
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition*0.5f, TEST_LOCATION );
+  }
+
+  // Discard
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+    animation.SetDisconnectAction( Animation::Discard );
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+    // Start the animation
+    animation.Play();
+
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0.5f*1000.0f)/*Only half the animation*/);
+
+    actor.Unparent();
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+  }
+
+  // Don't play the animation: disconnect action should not be applied
+  {
+    Actor actor = Actor::New();
+    stage.Add(actor);
+
+    // Build the animation
+    float durationSeconds(1.0f);
+    Animation animation = Animation::New(durationSeconds);
+
+    Vector3 targetPosition(10.0f, 10.0f, 10.0f);
+    animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0.5f*1000.0f)/*Only half the animation*/);
+
+    actor.Unparent();
+
+    application.SendNotification();
+    application.Render();
+
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliAnimationGetDisconnectActionP(void)
+{
+  TestApplication application;
+  Animation animation = Animation::New(1.0f);
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::BakeFinal); // default!
+
+  animation.SetDisconnectAction(Animation::Discard);
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Discard);
+
+  animation.SetDisconnectAction(Animation::Bake);
+  DALI_TEST_CHECK(animation.GetDisconnectAction() == Animation::Bake);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationSetDefaultAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  AlphaFunction func = animation.GetDefaultAlphaFunction();
+  DALI_TEST_EQUALS(func.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION);
+
+  animation.SetDefaultAlphaFunction(AlphaFunction::EASE_IN);
+  AlphaFunction func2 = animation.GetDefaultAlphaFunction();
+  DALI_TEST_EQUALS(func2.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAnimationGetDefaultAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  AlphaFunction func = animation.GetDefaultAlphaFunction();
+
+  // Test that the default is linear
+  DALI_TEST_EQUALS(func.GetBuiltinFunction(), AlphaFunction::DEFAULT, TEST_LOCATION);
+
+  animation.SetDefaultAlphaFunction(AlphaFunction::EASE_IN);
+  AlphaFunction func2 = animation.GetDefaultAlphaFunction();
+  DALI_TEST_EQUALS(func2.GetBuiltinFunction(), AlphaFunction::EASE_IN, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationSetCurrentProgressP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  Animation animation = Animation::New(0.0f);
+
+  //Set duration
+  float durationSeconds(1.0f);
+  animation.SetDuration(durationSeconds);
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation from 40% progress
+  animation.SetCurrentProgress( 0.4f );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+
+  //Set the progress to 70%
+  animation.SetCurrentProgress( 0.7f );
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 80% progress */);
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationSetCurrentProgressN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  Animation animation = Animation::New(0.0f);
+
+  //Set duration
+  float durationSeconds(1.0f);
+  animation.SetDuration(durationSeconds);
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  //Trying to set the current cursor outside the range [0..1] is ignored
+  animation.SetCurrentProgress( -1.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.SetCurrentProgress( 100.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationGetCurrentProgressP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  Animation animation = Animation::New(0.0f);
+  animation.Play();
+
+  //Test GetCurrentProgress return 0.0 as the duration is 0.0
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.SetCurrentProgress( 0.5f );
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(100.0f));
+
+  //Progress should still be 0.0
+  DALI_TEST_EQUALS( 0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  //Set duration
+  float durationSeconds(1.0f);
+  animation.SetDuration(durationSeconds);
+  application.SendNotification();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation from 40% progress
+  animation.SetCurrentProgress( 0.4f );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( 0.6f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+
+  //Set the progress to 70%
+  animation.SetCurrentProgress( 0.7f );
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 80% progress */);
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( 0.8f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationSetSpeedFactorP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  const Vector3 initialPosition(0.0f, 0.0f, 0.0f);
+  const Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add( 0.0f, initialPosition);
+  keyframes.Add( 1.0f, targetPosition );
+  animation.AnimateBetween( Property(actor, Actor::Property::POSITION), keyframes, AlphaFunction::LINEAR);
+
+  //Set speed to be x2
+  animation.SetSpeedFactor(2.0f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f) + 1u/*just beyond half the duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  finishCheck.Reset();
+
+  //Test -1 speed factor. Animation will play in reverse at normal speed
+  animation.SetSpeedFactor( -1.0f );
+
+  // Start the animation
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), initialPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+
+  //Test change speed factor on the fly
+  finishCheck.Reset();
+
+  //Set speed to be half of normal speed
+  animation.SetSpeedFactor( 0.5f );
+
+  // Start the animation
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 10% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.1f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 30% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.3f), TEST_LOCATION );
+
+  //Change speed factor while animation still playing.
+  animation.SetSpeedFactor(-1.0f);
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 10% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.1f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), initialPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( initialPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationGetSpeedFactorP(void)
+{
+  TestApplication application;
+
+  Animation animation = Animation::New(1.0f);
+  animation.SetSpeedFactor(0.5f);
+  DALI_TEST_EQUALS(animation.GetSpeedFactor(), 0.5f, TEST_LOCATION);
+
+  animation.SetSpeedFactor(-2.5f);
+  DALI_TEST_EQUALS(animation.GetSpeedFactor(), -2.5f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliAnimationSetPlayRangeP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New( durationSeconds );
+
+  bool signalReceived( false );
+  AnimationFinishCheck finishCheck( signalReceived );
+  animation.FinishedSignal().Connect( &application, finishCheck );
+  application.SendNotification();
+
+  // Set range between 0.4 and 0.8
+  animation.SetPlayRange( Vector2( 0.4f, 0.9f ) );
+  application.SendNotification();
+  DALI_TEST_EQUALS( Vector2( 0.4f, 0.9f ), animation.GetPlayRange(), TEST_LOCATION );
+
+  Vector3 targetPosition( 100.0f, 100.0f, 100.0f );
+  animation.AnimateTo( Property( actor, Actor::Property::POSITION ), targetPosition, AlphaFunction::LINEAR );
+
+  // Start the animation from 40% progress
+  animation.Play();
+
+  application.SendNotification();
+  application.Render( static_cast< unsigned int >( durationSeconds * 200.0f )/* 60% progress */ );
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.6f ), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( static_cast< unsigned int >( durationSeconds * 200.0f )/* 80% progress */ );
+
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.8f ), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render( static_cast< unsigned int >( durationSeconds*100.0f ) + 1u/*just beyond the animation duration*/ );
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), ( targetPosition * 0.9f ), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationSetPlayRangeN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  Animation animation = Animation::New(0);
+  application.SendNotification();
+
+  //PlayRange out of bounds
+  animation.SetPlayRange( Vector2(-1.0f,1.0f) );
+  application.SendNotification();
+  DALI_TEST_EQUALS( Vector2(0.0f,1.0f), animation.GetPlayRange(), TEST_LOCATION );
+  animation.SetPlayRange( Vector2(0.0f,2.0f) );
+  application.SendNotification();
+  DALI_TEST_EQUALS( Vector2(0.0f,1.0f), animation.GetPlayRange(), TEST_LOCATION );
+
+  //If playRange is not in the correct order it has to be ordered
+  animation.SetPlayRange( Vector2(0.8f,0.2f) );
+  application.SendNotification();
+  DALI_TEST_EQUALS( Vector2(0.2f,0.8f), animation.GetPlayRange(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliAnimationGetPlayRangeP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Build the animation
+  Animation animation = Animation::New( 1.0f );
+  application.SendNotification();
+
+  //If PlayRange not specified it should be 0.0-1.0 by default
+  DALI_TEST_EQUALS( Vector2( 0.0f,1.0f ), animation.GetPlayRange(), TEST_LOCATION );
+
+  // Set range between 0.4 and 0.8
+  animation.SetPlayRange( Vector2( 0.4f, 0.8f ) );
+  application.SendNotification();
+  DALI_TEST_EQUALS( Vector2( 0.4f, 0.8f ), animation.GetPlayRange(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayOffStageP(void)
+{
+  // Test that an animation can be played, when the actor is off-stage.
+  // When the actor is added to the stage, it should appear at the current position
+  // i.e. where it would have been anyway, if on-stage from the beginning.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 basePosition(Vector3::ZERO);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), basePosition, TEST_LOCATION );
+  // Not added to the stage!
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.SetDisconnectAction( Animation::Discard );
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*off-stage*/, TEST_LOCATION );
+
+  // Add to the stage
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 expectedPosition(basePosition + (targetPosition - basePosition)*0.4f);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), expectedPosition/*on-stage*/, TEST_LOCATION );
+
+  // Remove from the stage
+  Stage::GetCurrent().Remove(actor);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*back to start position*/, TEST_LOCATION );
+
+  // Add to the stage
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  expectedPosition = Vector3(basePosition + (targetPosition - basePosition)*0.8f);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), expectedPosition, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayDiscardHandleP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  // Start the animation
+  animation.Play();
+
+  // This is a test of the "Fire and Forget" behaviour
+  // Discard the animation handle!
+  animation.Reset();
+  DALI_TEST_CHECK( !animation );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.4f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayStopDiscardHandleP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 20% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  // This is a test of the "Fire and Forget" behaviour
+  // Stop the animation, and Discard the animation handle!
+  animation.Stop();
+  animation.Reset();
+  DALI_TEST_CHECK( !animation );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 40% progress */);
+
+  // We expect the animation to finish at 20% progress
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  finishCheck.Reset();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // Check that nothing has changed
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // Check that nothing has changed
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 100% progress */);
+
+  // Check that nothing has changed
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.2f), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayRangeP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  KeyFrames keyframes = KeyFrames::New();
+  keyframes.Add( 0.0f , Vector3(0.0f,0.0f,0.0f ) );
+  keyframes.Add( 1.0f , Vector3(100.0f,100.0f,100.0f ) );
+
+  animation.AnimateBetween( Property( actor, Actor::Property::POSITION), keyframes );
+
+  // Set range between 0.4 and 0.8
+  animation.SetPlayRange( Vector2(0.4f,0.8f) );
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  //Test that setting progress outside the range doesn't work
+  animation.SetCurrentProgress( 0.9f );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( animation.GetCurrentProgress(), 0.4f, TEST_LOCATION );
+  animation.SetCurrentProgress( 0.2f );
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( animation.GetCurrentProgress(), 0.4f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/* 80% progress */);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition * 0.8f, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition * 0.8f, actor.GetCurrentPosition(), TEST_LOCATION );
+
+
+  //Loop inside the range
+  finishCheck.Reset();
+  animation.SetLooping( true );
+  animation.Play();
+  application.SendNotification();
+  float intervalSeconds = 0.1f;
+  float progress = 0.4f;
+  for (int iterations = 0; iterations < 10; ++iterations )
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+    progress += intervalSeconds;
+    if (progress > 0.8f)
+    {
+      progress = progress - 0.4f;
+    }
+
+    DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION );
+  }
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+
+  //Test change range on the fly
+  animation.SetPlayRange( Vector2( 0.2f, 0.9f ) );
+  application.SendNotification();
+
+  for (int iterations = 0; iterations < 10; ++iterations )
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*intervalSeconds*1000.0f));
+
+    progress += intervalSeconds;
+    if (progress > 0.9f)
+    {
+      progress = progress - 0.7f;
+    }
+
+    DALI_TEST_EQUALS( targetPosition*progress, actor.GetCurrentPosition(), 0.001f, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayFromP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Start the animation from 40% progress
+  animation.PlayFrom( 0.4f );
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 60% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.6f), TEST_LOCATION );
+
+  animation.Play(); // Test that calling play has no effect, when animation is already playing
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 80% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), (targetPosition * 0.8f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f) + 1u/*just beyond the animation duration*/);
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPlayFromN(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  //PlayFrom with an argument outside the range [0..1] will be ignored
+  animation.PlayFrom(-1.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+
+  animation.PlayFrom(100.0f);
+  application.SendNotification();
+  DALI_TEST_EQUALS(0.0f, animation.GetCurrentProgress(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationPauseP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  Vector3 fiftyPercentProgress(targetPosition * 0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION );
+
+  // Pause the animation
+  animation.Pause();
+  application.SendNotification();
+
+  // Loop 5 times
+  for (int i=0; i<5; ++i)
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+
+    // We didn't expect the animation to finish yet
+    application.SendNotification();
+    finishCheck.CheckSignalNotReceived();
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress when paused */, TEST_LOCATION );
+  }
+
+  // Keep going
+  animation.Play();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*490.0f)/*slightly less than the animation duration*/);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( targetPosition, actor.GetCurrentPosition(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationStoP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  Vector3 fiftyPercentProgress(targetPosition * 0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION );
+
+  // Stop the animation
+  animation.Stop();
+  application.SendNotification();
+
+  // Loop 5 times
+  for (int i=0; i<5; ++i)
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+
+    // We did expect the animation to finish
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress when stopped */, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationStopSetPositionP(void)
+{
+  // Test that Animation::Stop & Actor::SetPosition can be used in conjunction
+  // i.e. to check that the animation does not interfere with the position set.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  Vector3 fiftyPercentProgress(targetPosition * 0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION );
+
+  // Stop the animation
+  animation.Stop();
+  Vector3 positionSet(2.0f, 3.0f, 4.0f);
+  actor.SetPosition(positionSet);
+  application.SendNotification();
+
+  // Loop 5 times
+  for (int i=0; i<5; ++i)
+  {
+    application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+
+    // We did expect the animation to finish
+    application.SendNotification();
+    finishCheck.CheckSignalReceived();
+    DALI_TEST_EQUALS( actor.GetCurrentPosition(), positionSet/*Animation should not interfere with this*/, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationClearP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  Vector3 fiftyPercentProgress(targetPosition * 0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress, TEST_LOCATION );
+
+  // Clear the animation
+  animation.Clear();
+  application.SendNotification();
+
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We don't expect the animation to finish now
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), fiftyPercentProgress/* Still 50% progress since the animator was destroyed */, TEST_LOCATION );
+
+  // Restart as a scale animation; this should not move the actor's position
+  finishCheck.Reset();
+  actor.SetPosition(Vector3::ZERO);
+  Vector3 targetScale(3.0f, 3.0f, 3.0f);
+  animation.AnimateTo( Property( actor, Actor::Property::SCALE ), targetScale, AlphaFunction::LINEAR );
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*Check move-animator was destroyed*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3(2.0f, 2.0f, 2.0f), TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO/*Check move-animator was destroyed*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationFinishedSignalP(void)
+{
+  TestApplication application;
+
+  // Start the empty animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByBooleanP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  const bool relativeValue(true);
+  const bool finalValue( false || relativeValue );
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Repeat with relative value "false" - this should be an NOOP
+  animation = Animation::New(durationSeconds);
+  bool noOpValue(false);
+  animation.AnimateBy(Property(actor, index), noOpValue);
+
+  // Start the animation
+  animation.Play();
+
+  finishCheck.Reset();
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByBooleanAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool relativeValue(true);
+  bool finalValue( false || relativeValue );
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_IN);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Repeat with relative value "false" - this should be an NOOP
+  animation = Animation::New(durationSeconds);
+  bool noOpValue(false);
+  animation.AnimateBy(Property(actor, index), noOpValue, AlphaFunction::EASE_IN);
+
+  // Start the animation
+  animation.Play();
+
+  finishCheck.Reset();
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByBooleanTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool relativeValue(true);
+  bool finalValue( false || relativeValue );
+  float animatorDurationSeconds(durationSeconds * 0.5f);
+  animation.AnimateBy( Property(actor, index),
+                       relativeValue,
+                       TimePeriod( animatorDurationSeconds ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*950.0f)/* 95% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/);
+
+  // We didn't expect the animation to finish yet...
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // ...however we should have reached the final value
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByBooleanAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool relativeValue(true);
+  bool finalValue( false || relativeValue );
+  float animatorDurationSeconds(durationSeconds * 0.5f);
+  animation.AnimateBy( Property(actor, index),
+                       relativeValue,
+                       AlphaFunction::EASE_IN_OUT,
+                       TimePeriod( animatorDurationSeconds ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*950.0f)/* 95% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/);
+
+  // We didn't expect the animation to finish yet...
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // ...however we should have reached the final value
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByFloatP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(50.0f);
+  float relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  float ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByFloatAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(90.0f);
+  float relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT);
+
+  float ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  float current(actor.GetProperty<float>(index));
+  DALI_TEST_CHECK( current > ninetyFivePercentProgress );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByFloatTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(30.0f);
+  float relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByFloatAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(30.0f);
+  float relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByIntegerP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(1);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(50);
+  int relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  int ninetyFivePercentProgress(static_cast<int>(startValue + relativeValue*0.95f + 0.5f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByIntegerAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(1);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(90);
+  int relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT);
+
+  int ninetyFivePercentProgress(static_cast<int>(startValue + relativeValue*0.95f + 0.5f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  int current(actor.GetProperty<int>(index));
+  DALI_TEST_CHECK( current > ninetyFivePercentProgress );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByIntegerTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(30);
+  int relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), static_cast<int>(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByIntegerAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(30);
+  int relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), static_cast<int>(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector2P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(60.0f, 60.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector2AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(100.0f, 100.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(20.0f, 20.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT);
+
+  Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector2 current(actor.GetProperty<Vector2>(index));
+  DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector2TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(30.0f, 30.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector2AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(5.0f, 5.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(10.0f, 10.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector3P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(60.0f, 60.0f, 60.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector3AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(100.0f, 100.0f, 100.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(20.0f, 20.0f, 20.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT);
+
+  Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector3 current(actor.GetProperty<Vector3>(index));
+  DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z < ninetyFivePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector3TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(30.0f, 30.0f, 30.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector3AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(5.0f, 5.0f, 5.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(10.0f, 10.0f, 10.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector4P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(60.0f, 60.0f, 60.0f, 60.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue);
+
+  Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector4AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(100.0f, 100.0f, 100.0f, 100.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(20.0f, 20.0f, 20.0f, 20.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  animation.AnimateBy(Property(actor, index), relativeValue, AlphaFunction::EASE_OUT);
+
+  Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector4 current(actor.GetProperty<Vector4>(index));
+  DALI_TEST_CHECK( current.x < ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z < ninetyFivePercentProgress.z );
+  DALI_TEST_CHECK( current.w < ninetyFivePercentProgress.w );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector4TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(30.0f, 30.0f, 30.0f, 30.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByVector4AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(5.0f, 5.0f, 5.0f, 5.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(10.0f, 10.0f, 10.0f, 10.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, index),
+                      relativeValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorPositionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 startPosition(10.0f, 10.0f, 10.0f);
+  actor.SetPosition(startPosition);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(20.0f, 20.0f, 20.0f);
+  Vector3 relativePosition(targetPosition - startPosition);
+  animation.AnimateBy(Property(actor, Actor::Property::POSITION), relativePosition);
+
+  Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorPositionAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 startPosition(10.0f, 10.0f, 10.0f);
+  actor.SetPosition(startPosition);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(20.0f, 20.0f, 20.0f);
+  Vector3 relativePosition(targetPosition - startPosition);
+  animation.AnimateBy(Property(actor, Actor::Property::POSITION), relativePosition, AlphaFunction::EASE_OUT);
+
+  Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector3 current(actor.GetCurrentPosition());
+  DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorPositionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 startPosition(10.0f, 10.0f, 10.0f);
+  actor.SetPosition(startPosition);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(20.0f, 20.0f, 20.0f);
+  Vector3 relativePosition(targetPosition - startPosition);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, Actor::Property::POSITION),
+                      relativePosition,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorPositionAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Vector3 startPosition(10.0f, 10.0f, 10.0f);
+  actor.SetPosition(startPosition);
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(20.0f, 20.0f, 20.0f);
+  Vector3 relativePosition(targetPosition - startPosition);
+  float delay = 0.5f;
+  animation.AnimateBy(Property(actor, Actor::Property::POSITION),
+                      relativePosition,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  Vector3 ninetyFivePercentProgress(startPosition + relativePosition*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), startPosition, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorOrientationP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree relativeRotationDegrees(360.0f);
+  Radian relativeRotationRadians(relativeRotationDegrees);
+  animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorOrientationAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree relativeRotationDegrees(360.0f);
+  Radian relativeRotationRadians(relativeRotationDegrees);
+  animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ), AlphaFunction::EASE_IN );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.25f*0.25f*0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.5f*0.5f*0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * 0.75f*0.75f*0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorOrientationAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation( Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree relativeRotationDegrees(360.0f);
+  Radian relativeRotationRadians(relativeRotationDegrees);
+  float delay = 0.3f;
+  animation.AnimateBy( Property( actor, Actor::Property::ORIENTATION ), Quaternion( relativeRotationRadians, Vector3::YAXIS ),
+                       AlphaFunction::EASE_IN, TimePeriod( delay, durationSeconds - delay ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  float progress = max(0.0f, 0.25f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.5f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.75f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(relativeRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateByActorScaleP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetScale(2.0f, 2.0f, 2.0f);
+  Vector3 relativeScale(targetScale - Vector3::ONE);
+  animation.AnimateBy( Property( actor, Actor::Property::SCALE ), Vector3( relativeScale.x, relativeScale.y, relativeScale.z ) );
+
+  Vector3 ninetyNinePercentProgress(Vector3::ONE + relativeScale*0.99f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), ninetyNinePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetScale(Vector3::ONE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Repeat with a different (ease-in) alpha function
+  animation = Animation::New(durationSeconds);
+  animation.AnimateBy( Property( actor, Actor::Property::SCALE ), relativeScale, AlphaFunction::EASE_IN );
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The scale should have grown less, than with a linear alpha function
+  Vector3 current(actor.GetCurrentScale());
+  DALI_TEST_CHECK( current.x > 1.0f );
+  DALI_TEST_CHECK( current.y > 1.0f );
+  DALI_TEST_CHECK( current.z > 1.0f );
+  DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y );
+  DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetScale(Vector3::ONE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Repeat with a delay
+  float delay = 0.5f;
+  animation = Animation::New(durationSeconds);
+  animation.AnimateBy( Property( actor, Actor::Property::SCALE ), relativeScale, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) );
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToBooleanP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  const bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  const bool targetValue( !startValue );
+  animation.AnimateTo(Property(actor, index), targetValue);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  // Repeat with target value "false"
+  animation = Animation::New(durationSeconds);
+  const bool finalValue( !targetValue );
+  animation.AnimateTo(Property(actor, index), finalValue);
+
+  // Start the animation
+  animation.Play();
+
+  finishCheck.Reset();
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToBooleanAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  const bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  const bool targetValue( !startValue );
+  animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction::EASE_OUT);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  // Repeat with target value "false"
+  animation = Animation::New(durationSeconds);
+  const bool finalValue( !targetValue );
+  animation.AnimateTo(Property(actor, index), finalValue, AlphaFunction::EASE_OUT);
+
+  // Start the animation
+  animation.Play();
+
+  finishCheck.Reset();
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == targetValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToBooleanTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool finalValue( !startValue );
+  float animatorDurationSeconds(durationSeconds * 0.5f);
+  animation.AnimateTo( Property(actor, index),
+                       finalValue,
+                       TimePeriod( animatorDurationSeconds ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*950.0f)/* 95% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/);
+
+  // We didn't expect the animation to finish yet...
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // ...however we should have reached the final value
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToBooleanAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a boolean property
+  bool startValue(false);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool finalValue( !startValue );
+  float animatorDurationSeconds(durationSeconds * 0.5f);
+  animation.AnimateTo( Property(actor, index),
+                       finalValue,
+                       AlphaFunction::LINEAR,
+                       TimePeriod( animatorDurationSeconds ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*950.0f)/* 95% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*50.0f) + 1u/*just beyond the animator duration*/);
+
+  // We didn't expect the animation to finish yet...
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // ...however we should have reached the final value
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(animatorDurationSeconds*1000.0f)/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+
+  // Check that nothing has changed after a couple of buffer swaps
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  application.Render(0);
+  DALI_TEST_CHECK( actor.GetProperty<bool>(index) == finalValue );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToFloatP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(50.0f);
+  float relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, "test-property"), targetValue);
+
+  float ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToFloatAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(90.0f);
+  float relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT);
+
+  float ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  float current(actor.GetProperty<float>(index));
+  DALI_TEST_CHECK( current > ninetyFivePercentProgress );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToFloatTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(30.0f);
+  float relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToFloatAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetValue(30.0f);
+  float relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToIntegerP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(50);
+  int relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, "test-property"), targetValue);
+
+  int ninetyFivePercentProgress(static_cast<int>(startValue + relativeValue*0.95f + 0.5f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToIntegerAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(90);
+  int relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT);
+
+  int ninetyFivePercentProgress(static_cast<int>(startValue + relativeValue*0.95f + 0.5f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  int current(actor.GetProperty<int>(index));
+  DALI_TEST_CHECK( current > ninetyFivePercentProgress );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToIntegerTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(30);
+  int relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), static_cast<int>(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToIntegerAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register an integer property
+  int startValue(10);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  int targetValue(30);
+  int relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), static_cast<int>(startValue+(relativeValue*0.5f)+0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector2P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(-50.0f, -50.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(50.0f, 50.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue);
+
+  Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector2AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(1000.0f, 1000.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(9000.0f, 9000.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, "test-property"), targetValue, AlphaFunction::EASE_OUT);
+
+  Vector2 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector2 current(actor.GetProperty<Vector2>(index));
+  DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector2TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(-10.0f, 20.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector2AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector2 property
+  Vector2 startValue(10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector2 targetValue(30.0f, 30.0f);
+  Vector2 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector2>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector3P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(-50.0f, -50.0f, -50.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(50.0f, 50.0f, 50.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue);
+
+  Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector3AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(1000.0f, 1000.0f, 1000.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(9000.0f, 9000.0f, 9000.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT);
+
+  Vector3 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector3 current(actor.GetProperty<Vector3>(index));
+  DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector3TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(-10.0f, 20.0f, 100.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector3AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(30.0f, 30.0f, 30.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, "test-property"),
+                      targetValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector3ComponentP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector3 property
+  Vector3 startValue(10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetValue(30.0f, 30.0f, 10.0f);
+  Vector3 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, "test-property", 0),
+                      30.0f,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+  animation.AnimateTo(Property(actor, index, 1),
+                      30.0f,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector3>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector4P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(-50.0f, -40.0f, -30.0f, -20.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(50.0f, 50.0f, 50.0f, 50.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue);
+
+  Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), ninetyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector4AlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(1000.0f, 1000.0f, 1000.0f, 1000.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(9000.0f, 9000.0f, 9000.0f, 9000.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  animation.AnimateTo(Property(actor, index), targetValue, AlphaFunction::EASE_OUT);
+
+  Vector4 ninetyFivePercentProgress(startValue + relativeValue*0.95f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*950.0f)/* 95% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved more, than with a linear alpha function
+  Vector4 current(actor.GetProperty<Vector4>(index));
+  DALI_TEST_CHECK( current.x > ninetyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y > ninetyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z > ninetyFivePercentProgress.z );
+  DALI_TEST_CHECK( current.w > ninetyFivePercentProgress.w );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*50.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector4TimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, VECTOR4_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(-10.0f, 20.0f, 100.0f, 100.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, VECTOR4_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue+(relativeValue*0.5f), VECTOR4_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, VECTOR4_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToVector4AlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a Vector4 property
+  Vector4 startValue(10.0f, 10.0f, 10.0f, 10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetValue(30.0f, 30.0f, 30.0f, 30.0f);
+  Vector4 relativeValue(targetValue - startValue);
+  float delay = 0.5f;
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      AlphaFunction::LINEAR,
+                      TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<Vector4>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorParentOriginP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentParentOrigin(), ParentOrigin::TOP_LEFT, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN), targetParentOrigin );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorParentOriginXP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().x, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::PARENT_ORIGIN_X), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetX(1.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_X), targetX );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorParentOriginYP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().y, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::PARENT_ORIGIN_Y), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetY(1.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_Y), targetY );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorParentOriginZP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.5f);
+  DALI_TEST_EQUALS( actor.GetCurrentParentOrigin().z, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::PARENT_ORIGIN_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetZ(1.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::PARENT_ORIGIN_Z), targetZ );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorAnchorPointP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint(), AnchorPoint::CENTER, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetAnchorPoint(AnchorPoint::TOP_LEFT);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT), targetAnchorPoint);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorAnchorPointXP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.5f);
+  DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().x, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::ANCHOR_POINT_X), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetX(1.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_X), targetX );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorAnchorPointYP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.5f);
+  DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().y, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::ANCHOR_POINT_Y), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetY(0.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_Y), targetY );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorAnchorPointZP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.5f);
+  DALI_TEST_EQUALS( actor.GetCurrentAnchorPoint().z, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::ANCHOR_POINT_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetZ(100.0f);
+
+  try
+  {
+    animation.AnimateTo( Property(actor, Actor::Property::ANCHOR_POINT_Z), targetZ );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "IsPropertyAnimatable( index )", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorSizeP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetSize(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize );
+
+  Vector3 ninetyNinePercentProgress(targetSize * 0.99f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), ninetyNinePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetSize(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Repeat with a different (ease-in) alpha function
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize, AlphaFunction::EASE_IN);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The size should have travelled less, than with a linear alpha function
+  Vector3 current(actor.GetCurrentSize());
+  DALI_TEST_CHECK( current.x > 0.0f );
+  DALI_TEST_CHECK( current.y > 0.0f );
+  DALI_TEST_CHECK( current.z > 0.0f );
+  DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y );
+  DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetSize(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Repeat with a delay
+  float delay = 0.5f;
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE), targetSize, AlphaFunction::LINEAR, TimePeriod(delay, durationSeconds - delay));
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorSizeWidthP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentSize().width, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_WIDTH), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetWidth(10.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE_WIDTH), targetWidth );
+
+  float fiftyPercentProgress(startValue + (targetWidth - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().width, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_WIDTH), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().width, targetWidth, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_WIDTH), targetWidth, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorSizeHeightP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentSize().height, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_HEIGHT), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetHeight(-10.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE_HEIGHT), targetHeight );
+
+  float fiftyPercentProgress(startValue + (targetHeight - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().height, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_HEIGHT), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().height, targetHeight, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_HEIGHT), targetHeight, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorSizeDepthP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentSize().depth, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_DEPTH), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetDepth(-10.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SIZE_DEPTH), targetDepth );
+
+  float fiftyPercentProgress(startValue + (targetDepth - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().depth, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_DEPTH), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().depth, targetDepth, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SIZE_DEPTH), targetDepth, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorSizeWidthHeightP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetSize(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE ), targetSize );
+
+  Vector3 ninetyNinePercentProgress(targetSize * 0.99f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), ninetyNinePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), targetSize, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetSize(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Repeat with a different (ease-in) alpha function
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE_WIDTH ), targetSize.x, AlphaFunction::EASE_IN );
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE_HEIGHT ), targetSize.y, AlphaFunction::EASE_IN );
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The size should have travelled less, than with a linear alpha function
+  Vector3 current(actor.GetCurrentSize());
+  DALI_TEST_CHECK( current.x > 0.0f );
+  DALI_TEST_CHECK( current.y > 0.0f );
+  DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().x, targetSize.x, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentSize().y, targetSize.y, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetSize(Vector3::ZERO);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  // Repeat with a delay
+  float delay = 0.5f;
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE_WIDTH ), targetSize.x, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) );
+  animation.AnimateTo( Property( actor, Actor::Property::SIZE_HEIGHT ), targetSize.y, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) );
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize(), Vector3::ZERO, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentSize().x, targetSize.x, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentSize().y, targetSize.y, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(200.0f, 200.0f, 200.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition);
+
+  Vector3 seventyFivePercentProgress(targetPosition * 0.75f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*750.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionXP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetX(1.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION_X), targetX );
+
+  float fiftyPercentProgress(startValue + (targetX - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, targetX, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), targetX, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionYP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().y, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetY(10.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION_Y), targetY );
+
+  float fiftyPercentProgress(startValue + (targetY - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().y, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().y, targetY, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), targetY, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionZP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(0.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().z, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetZ(-5.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION_Z), targetZ );
+
+  float fiftyPercentProgress(startValue + (targetZ - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().z, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().z, targetZ, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::POSITION_Z), targetZ, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(200.0f, 200.0f, 200.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::EASE_IN);
+
+  Vector3 seventyFivePercentProgress(targetPosition * 0.75f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*750.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The position should have moved less, than with a linear alpha function
+  Vector3 current(actor.GetCurrentPosition());
+  DALI_TEST_CHECK( current.x > Vector3::ZERO.x );
+  DALI_TEST_CHECK( current.y > Vector3::ZERO.y );
+  DALI_TEST_CHECK( current.z > Vector3::ZERO.z );
+  DALI_TEST_CHECK( current.x < seventyFivePercentProgress.x );
+  DALI_TEST_CHECK( current.y < seventyFivePercentProgress.y );
+  DALI_TEST_CHECK( current.z < seventyFivePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(200.0f, 200.0f, 200.0f);
+  float delay = 0.5f;
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION),
+                       targetPosition,
+                       TimePeriod( delay, durationSeconds - delay ) );
+
+  Vector3 seventyFivePercentProgress(targetPosition * 0.75f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f*0.75)/* 7/8 animation progress, 3/4 animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f*0.25) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorPositionAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetPosition(200.0f, 200.0f, 200.0f);
+  float delay = 0.5f;
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION),
+                       targetPosition,
+                       AlphaFunction::LINEAR,
+                       TimePeriod( delay, durationSeconds - delay ) );
+
+  Vector3 seventyFivePercentProgress(targetPosition * 0.75f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3::ZERO, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f*0.75)/* 7/8 animation progress, 3/4 animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), seventyFivePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f*0.25) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorOrientationAngleAxisP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree targetRotationDegrees(90.0f);
+  Radian targetRotationRadians(targetRotationDegrees);
+  animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationRadians, Vector3::YAXIS) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorOrientationQuaternionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree targetRotationDegrees(90.0f);
+  Radian targetRotationRadians(targetRotationDegrees);
+  Quaternion targetRotation(targetRotationRadians, Vector3::YAXIS);
+  animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), targetRotation );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorOrientationAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(Radian(0.0f), Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree targetRotationDegrees(90.0f);
+  Radian targetRotationRadians(targetRotationDegrees);
+  animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), AlphaFunction::EASE_IN);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.25f*0.25f*0.25f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.5f*0.5f*0.5f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * 0.75f*0.75f*0.75f, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorOrientationTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree targetRotationDegrees(90.0f);
+  Radian targetRotationRadians(targetRotationDegrees);
+  float delay(0.1f);
+  animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  float progress = max(0.0f, 0.25f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.5f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.75f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorOrientationAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetOrientation(Quaternion( Dali::ANGLE_0, Vector3::YAXIS ) );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion( Dali::ANGLE_0, Vector3::YAXIS ), ROTATION_EPSILON, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Degree targetRotationDegrees(90.0f);
+  Radian targetRotationRadians(targetRotationDegrees);
+  float delay(0.1f);
+  animation.AnimateTo( Property(actor, Actor::Property::ORIENTATION), AngleAxis(targetRotationDegrees, Vector3::YAXIS), AlphaFunction::EASE_IN, TimePeriod(delay, durationSeconds - delay));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  float progress = max(0.0f, 0.25f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.5f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  progress = max(0.0f, 0.75f - delay) / (1.0f - delay);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians * progress*progress*progress, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), Quaternion(targetRotationRadians, Vector3::YAXIS), ROTATION_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorScaleP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector3 targetScale(2.0f, 2.0f, 2.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale );
+
+  Vector3 ninetyNinePercentProgress(Vector3::ONE + (targetScale - Vector3::ONE)*0.99f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), ninetyNinePercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetScale(Vector3::ONE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Repeat with a different (ease-in) alpha function
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale, AlphaFunction::EASE_IN);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*990.0f)/* 99% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The scale should have grown less, than with a linear alpha function
+  Vector3 current(actor.GetCurrentScale());
+  DALI_TEST_CHECK( current.x > 1.0f );
+  DALI_TEST_CHECK( current.y > 1.0f );
+  DALI_TEST_CHECK( current.z > 1.0f );
+  DALI_TEST_CHECK( current.x < ninetyNinePercentProgress.x );
+  DALI_TEST_CHECK( current.y < ninetyNinePercentProgress.y );
+  DALI_TEST_CHECK( current.z < ninetyNinePercentProgress.z );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetScale(Vector3::ONE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  // Repeat with a delay
+  float delay = 0.5f;
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE), targetScale, AlphaFunction::LINEAR, TimePeriod(delay, durationSeconds - delay));
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), Vector3::ONE, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale(), targetScale, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorScaleXP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentScale().x, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetX(10.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE_X), targetX );
+
+  float fiftyPercentProgress(startValue + (targetX - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().x, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().x, targetX, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), targetX, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorScaleYP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentScale().y, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetY(1000.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE_Y), targetY );
+
+  float fiftyPercentProgress(startValue + (targetY - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().y, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().y, targetY, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), targetY, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorScaleZP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentScale().z, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetZ(-1000.0f);
+  animation.AnimateTo( Property(actor, Actor::Property::SCALE_Z), targetZ );
+
+  float fiftyPercentProgress(startValue + (targetZ - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().z, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentScale().z, targetZ, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_X), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Y), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::SCALE_Z), targetZ, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorColorP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  Vector4 targetColor(Color::RED);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor );
+
+  Vector4 tenPercentProgress(Vector4(1.0f, 0.9f, 0.9f, 1.0f));
+  Vector4 twentyPercentProgress(Vector4(1.0f, 0.8f, 0.8f, 1.0f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), tenPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*900.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetColor(Color::WHITE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION );
+
+  // Repeat with a different (ease-in) alpha function
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor, AlphaFunction::EASE_IN);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  // The color should have changed less, than with a linear alpha function
+  Vector4 current(actor.GetCurrentColor());
+  DALI_TEST_CHECK( current.x == 1.0f ); // doesn't change
+  DALI_TEST_CHECK( current.y < 1.0f );
+  DALI_TEST_CHECK( current.y > tenPercentProgress.y );
+  DALI_TEST_CHECK( current.z  < 1.0f );
+  DALI_TEST_CHECK( current.z  > tenPercentProgress.z );
+  DALI_TEST_CHECK( current.w == 1.0f ); // doesn't change
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*900.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION );
+
+  // Reset everything
+  finishCheck.Reset();
+  actor.SetColor(Color::WHITE);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), Color::WHITE, TEST_LOCATION );
+
+  // Repeat with a shorter animator duration
+  float animatorDuration = 0.5f;
+  animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR), targetColor, AlphaFunction::LINEAR, TimePeriod(animatorDuration));
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% animation progress, 20% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), twentyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*400.0f)/* 50% animation progress, 100% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor(), targetColor, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorColorRedP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentColor().r, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetRed(0.5f);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR_RED), targetRed );
+
+  float fiftyPercentProgress(startValue + (targetRed - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().r, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue,           TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().r, targetRed, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   targetRed,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorColorGreenP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentColor().g, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetGreen(0.5f);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR_GREEN), targetGreen );
+
+  float fiftyPercentProgress(startValue + (targetGreen - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().g, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue,           TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().g, targetGreen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), targetGreen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue,  TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorColorBlueP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentColor().b, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetBlue(0.5f);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR_BLUE), targetBlue );
+
+  float fiftyPercentProgress(startValue + (targetBlue - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().b, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue,           TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().b, targetBlue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  targetBlue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateToActorColorAlphaP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  float startValue(1.0f);
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  float targetAlpha(0.5f);
+  animation.AnimateTo( Property(actor, Actor::Property::COLOR_ALPHA), targetAlpha );
+
+  float fiftyPercentProgress(startValue + (targetAlpha - startValue)*0.5f);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, fiftyPercentProgress, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue,           TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), fiftyPercentProgress, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, targetAlpha, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue,  TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), targetAlpha, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames01P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, 0.1f);
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::FLOAT, TEST_LOCATION);
+
+  KeyFrames keyFrames2( keyFrames);
+  DALI_TEST_CHECK( keyFrames2 );
+  DALI_TEST_EQUALS(keyFrames2.GetType(), Property::FLOAT, TEST_LOCATION);
+
+  KeyFrames keyFrames3 = KeyFrames::New();
+  keyFrames3.Add(0.6f, true);
+  DALI_TEST_CHECK( keyFrames3 );
+  DALI_TEST_EQUALS(keyFrames3.GetType(), Property::BOOLEAN, TEST_LOCATION);
+
+  keyFrames3 = keyFrames;
+  DALI_TEST_CHECK( keyFrames3 );
+  DALI_TEST_EQUALS(keyFrames3.GetType(), Property::FLOAT, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames02P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, 0.1f);
+  keyFrames.Add(0.2f, 0.5f);
+  keyFrames.Add(0.4f, 0.0f);
+  keyFrames.Add(0.6f, 1.0f);
+  keyFrames.Add(0.8f, 0.7f);
+  keyFrames.Add(1.0f, 0.9f);
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::FLOAT, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(1.9f, false);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames03P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, true);
+  keyFrames.Add(0.2f, false);
+  keyFrames.Add(0.4f, false);
+  keyFrames.Add(0.6f, true);
+  keyFrames.Add(0.8f, true);
+  keyFrames.Add(1.0f, false);
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::BOOLEAN, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(0.7f, Vector3(1.0f, 1.0f, 1.0f));
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames04P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Vector2(0.0f, 0.0f));
+  keyFrames.Add(0.2f, Vector2(1.0f, 1.0f));
+  keyFrames.Add(0.4f, Vector2(2.0f, 2.0f));
+  keyFrames.Add(0.6f, Vector2(3.0f, 5.0f));
+  keyFrames.Add(0.8f, Vector2(4.0f, 3.0f));
+  keyFrames.Add(1.0f, Vector2(6.0f, 2.0f));
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR2, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(0.7f, Vector3(1.0f, 1.0f, 1.0f));
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames05P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Vector3(0.0f, 4.0f, 0.0f));
+  keyFrames.Add(0.2f, Vector3(1.0f, 3.0f, 1.0f));
+  keyFrames.Add(0.4f, Vector3(2.0f, 2.0f, 2.0f));
+  keyFrames.Add(0.6f, Vector3(3.0f, 2.0f, 5.0f));
+  keyFrames.Add(0.8f, Vector3(4.0f, 4.0f, 3.0f));
+  keyFrames.Add(1.0f, Vector3(6.0f, 8.0f, 2.0f));
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR3, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(0.7f, 1.0f);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames06P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Vector4(0.0f, 0.0f, 0.0f, 0.0f));
+  keyFrames.Add(0.2f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+  keyFrames.Add(0.4f, Vector4(2.0f, 2.0f, 2.0f, 2.0f));
+  keyFrames.Add(0.6f, Vector4(3.0f, 5.0f, 3.0f, 5.0f));
+  keyFrames.Add(0.8f, Vector4(4.0f, 3.0f, 4.0f, 3.0f));
+  keyFrames.Add(1.0f, Vector4(6.0f, 2.0f, 6.0f, 2.0f));
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::VECTOR4, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(0.7f, Quaternion(Radian(1.717f), Vector3::XAXIS));
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationKeyFrames07P(void)
+{
+  TestApplication application;
+
+  KeyFrames keyFrames = KeyFrames::New();
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::NONE, TEST_LOCATION);
+
+  keyFrames.Add(0.0f, Quaternion(Radian(1.717f), Vector3::XAXIS));
+  keyFrames.Add(0.2f, Quaternion(Radian(2.0f), Vector3::XAXIS));
+  keyFrames.Add(0.4f, Quaternion(Radian(3.0f), Vector3::ZAXIS));
+  keyFrames.Add(0.6f, Quaternion(Radian(4.0f), Vector3(1.0f, 1.0f, 1.0f)));
+  keyFrames.Add(0.8f, AngleAxis(Degree(90), Vector3::XAXIS));
+  keyFrames.Add(1.0f, Quaternion(Radian(3.0f), Vector3::YAXIS));
+
+  DALI_TEST_EQUALS(keyFrames.GetType(), Property::ROTATION, TEST_LOCATION);
+
+  try
+  {
+    keyFrames.Add(0.7f, 1.1f);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "mType == value.GetType()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorAlphaP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, 0.1f);
+  keyFrames.Add(0.2f, 0.5f);
+  keyFrames.Add(0.4f, 0.0f);
+  keyFrames.Add(0.6f, 1.0f);
+  keyFrames.Add(0.8f, 0.7f);
+  keyFrames.Add(1.0f, 0.9f);
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR_ALPHA), keyFrames );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.1f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.3f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 30% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.25f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.25f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 40% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.0f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*400.0f)/* 80% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.7f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 90% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.8f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.9f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorAlphaCubicP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, 0.1f);
+  keyFrames.Add(0.2f, 0.5f);
+  keyFrames.Add(0.4f, 0.0f);
+  keyFrames.Add(0.6f, 1.0f);
+  keyFrames.Add(0.8f, 0.7f);
+  keyFrames.Add(1.0f, 0.9f);
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR_ALPHA), keyFrames, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.1f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 10% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.36f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.36f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*200.0f)/* 30% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.21f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.21f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 40% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.0f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*400.0f)/* 80% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.7f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)/* 90% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.76f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.76f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*100.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, 0.9f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.95f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorCubicP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.55f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.506f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.99375f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85625f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorVisibleP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, false);
+  keyFrames.Add(0.2f, true);
+  keyFrames.Add(0.4f, true);
+  keyFrames.Add(0.8f, false);
+  keyFrames.Add(1.0f, true);
+
+  animation.AnimateBetween( Property(actor, Actor::Property::VISIBLE), keyFrames );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+  application.SendNotification();
+
+  DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION);
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorVisibleCubicP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+
+  DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, false);
+  keyFrames.Add(0.2f, true);
+  keyFrames.Add(0.4f, true);
+  keyFrames.Add(0.8f, false);
+  keyFrames.Add(1.0f, true);
+
+  //Cubic interpolation for boolean values should be ignored
+  animation.AnimateBetween( Property(actor, Actor::Property::VISIBLE), keyFrames, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+  application.SendNotification();
+
+  DALI_TEST_EQUALS( actor.IsVisible(), true, TEST_LOCATION);
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorOrientation01P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  Quaternion start(Radian(aa.angle), aa.axis);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::ZAXIS));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+  application.SendNotification();
+
+  Quaternion check( Radian(Degree(60)), Vector3::ZAXIS );
+
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorOrientation02P(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  application.SendNotification();
+  application.Render(0);
+  Stage::GetCurrent().Add(actor);
+
+  Quaternion start(Radian(aa.angle), aa.axis);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::XAXIS));
+  keyFrames.Add(0.5f, AngleAxis(Degree(120), Vector3::XAXIS));
+  keyFrames.Add(1.0f, AngleAxis(Degree(120), Vector3::YAXIS));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  Quaternion check(Radian(Degree(60)), Vector3::XAXIS);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(90)), Vector3::XAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(120)), Vector3::XAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(101.5)), Vector3(0.5f, 0.5f, 0.0f) );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(120)), Vector3::YAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorOrientation01CubicP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(0);
+  Quaternion start(Radian(aa.angle), aa.axis);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::ZAXIS));
+
+  //Cubic interpolation should be ignored for quaternions
+  animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f));
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)+1);
+  application.SendNotification();
+
+  Quaternion check( Radian(Degree(60)), Vector3::ZAXIS );
+
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorOrientation02CubicP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  AngleAxis aa(Degree(90), Vector3::XAXIS);
+  actor.SetOrientation(aa.angle, aa.axis);
+  application.SendNotification();
+  application.Render(0);
+  Stage::GetCurrent().Add(actor);
+
+  Quaternion start(Radian(aa.angle), aa.axis);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), start, 0.001f, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, AngleAxis(Degree(60), Vector3::XAXIS));
+  keyFrames.Add(0.5f, AngleAxis(Degree(120), Vector3::XAXIS));
+  keyFrames.Add(1.0f, AngleAxis(Degree(120), Vector3::YAXIS));
+
+  //Cubic interpolation should be ignored for quaternions
+  animation.AnimateBetween( Property(actor, Actor::Property::ORIENTATION), keyFrames, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+
+  Quaternion check(Radian(Degree(60)), Vector3::XAXIS);
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(90)), Vector3::XAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(120)), Vector3::XAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(101.5)), Vector3(0.5f, 0.5f, 0.0f ) );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  check = Quaternion( Radian(Degree(120)), Vector3::YAXIS );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), check, 0.001f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.95f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionCubicP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.55f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.506f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.99375f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85625f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorTimePeriodP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  float delay = 0.5f;
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, TimePeriod( delay, durationSeconds - delay ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  application.Render(static_cast<unsigned int>(delay*1000.0f)/* 0% progress */);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.95f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorTimePeriodCubicP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  float delay = 0.5f;
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, TimePeriod( delay, durationSeconds - delay ), Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  application.Render(static_cast<unsigned int>(delay*1000.0f)/* 0% progress */);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.55f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.506f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.99375f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85625f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateBetweenActorColorAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  float delay = 0.5f;
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ) );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  application.Render(static_cast<unsigned int>(delay*1000.0f)/* 0% progress */);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.5f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.5f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.95f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.90f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.80f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int P(void)
+{
+  TestApplication application;
+
+  float startValue(1.0f);
+  Actor actor = Actor::New();
+  actor.SetColor(Vector4(startValue, startValue, startValue, startValue));
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS( actor.GetCurrentColor().a, startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  startValue, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  float delay = 0.5f;
+  Animation animation = Animation::New(durationSeconds);
+
+  KeyFrames keyFrames = KeyFrames::New();
+  keyFrames.Add(0.0f, Vector4(0.1f, 0.2f, 0.3f, 0.4f));
+  keyFrames.Add(0.5f, Vector4(0.9f, 0.8f, 0.7f, 0.6f));
+  keyFrames.Add(1.0f, Vector4(1.0f, 1.0f, 1.0f, 1.0f));
+
+  animation.AnimateBetween( Property(actor, Actor::Property::COLOR), keyFrames, AlphaFunction::LINEAR, TimePeriod( delay, durationSeconds - delay ), Animation::Cubic );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+
+  application.Render(static_cast<unsigned int>(delay*1000.0f)/* 0% progress */);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.1f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.2f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.3f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 25% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.55f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.525f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.506f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.4875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 50% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.9f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.8f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.7f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.6f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)/* 75% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   0.99375f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 0.925f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  0.85625f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 0.7875f, 0.01f, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>((durationSeconds - delay)*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_RED),   1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_GREEN), 1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_BLUE),  1.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProperty<float>(Actor::Property::COLOR_ALPHA), 1.0f, 0.01f, TEST_LOCATION );
+
+  // We did expect the animation to finish
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //Build the path
+  Vector3 position0( 30.0,  80.0,  0.0);
+  Vector3 position1( 70.0,  120.0, 0.0);
+  Vector3 position2( 100.0, 100.0, 0.0);
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(position0);
+  path.AddPoint(position1);
+  path.AddPoint(position2);
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0));
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0));
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New(durationSeconds);
+  animation.Animate(actor, path, Vector3::XAXIS);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  path.Sample( 0.25f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  path.Sample( 0.5f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  path.Sample( 0.75f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateAlphaFunctionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //Build the path
+  Vector3 position0( 30.0,  80.0,  0.0);
+  Vector3 position1( 70.0,  120.0, 0.0);
+  Vector3 position2( 100.0, 100.0, 0.0);
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(position0);
+  path.AddPoint(position1);
+  path.AddPoint(position2);
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0));
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0));
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New(durationSeconds);
+  animation.Animate(actor, path, Vector3::XAXIS, AlphaFunction::LINEAR);
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  path.Sample( 0.25f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  path.Sample( 0.5f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  path.Sample( 0.75f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //Build the path
+  Vector3 position0( 30.0,  80.0,  0.0);
+  Vector3 position1( 70.0,  120.0, 0.0);
+  Vector3 position2( 100.0, 100.0, 0.0);
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(position0);
+  path.AddPoint(position1);
+  path.AddPoint(position2);
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0));
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0));
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New(durationSeconds);
+  animation.Animate(actor, path, Vector3::XAXIS, TimePeriod(0.0f, 1.0f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  path.Sample( 0.25f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  path.Sample( 0.5f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  path.Sample( 0.75f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationAnimateAlphaFunctionTimePeriodP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //Build the path
+  Vector3 position0( 30.0,  80.0,  0.0);
+  Vector3 position1( 70.0,  120.0, 0.0);
+  Vector3 position2( 100.0, 100.0, 0.0);
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(position0);
+  path.AddPoint(position1);
+  path.AddPoint(position2);
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0));
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0));
+
+  // Build the animation
+  float durationSeconds( 1.0f );
+  Animation animation = Animation::New(durationSeconds);
+  animation.Animate(actor, path, Vector3::XAXIS, AlphaFunction::LINEAR, TimePeriod(0.0f, 1.0f));
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  application.SendNotification();
+  application.Render(0);
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  Vector3 position, tangent;
+  Quaternion rotation;
+  path.Sample( 0.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+  application.SendNotification();
+  path.Sample( 0.25f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  application.SendNotification();
+  path.Sample( 0.5f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  application.SendNotification();
+  path.Sample( 0.75f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)+1/* 100% progress */);
+  application.SendNotification();
+  path.Sample( 1.0f, position, tangent );
+  rotation = Quaternion( Vector3::XAXIS, tangent );
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetCurrentOrientation(), rotation, TEST_LOCATION );
+
+  finishCheck.CheckSignalReceived();
+  END_TEST;
+}
+
+int UtcDaliAnimationShowP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetVisible(false);
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( !actor.IsVisible() );
+  Stage::GetCurrent().Add(actor);
+
+  // Start the animation
+  float durationSeconds(10.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.Show(actor, durationSeconds*0.5f);
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*490.0f));
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f)/*Should be shown now*/);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.IsVisible() );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.IsVisible() );
+  END_TEST;
+}
+
+int UtcDaliAnimationHideP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( actor.IsVisible() );
+  Stage::GetCurrent().Add(actor);
+
+  // Start the animation
+  float durationSeconds(10.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.Hide(actor, durationSeconds*0.5f);
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*490.0f));
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( actor.IsVisible() );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*10.0f)/*Should be hidden now*/);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( !actor.IsVisible() );
+  END_TEST;
+}
+
+int UtcDaliAnimationShowHideAtEndP(void)
+{
+  // Test that show/hide delay can be the same as animation duration
+  // i.e. to show/hide at the end of the animation
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( actor.IsVisible() );
+  Stage::GetCurrent().Add(actor);
+
+  // Start Hide animation
+  float durationSeconds(10.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.Hide(actor, durationSeconds/*Hide at end*/);
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( !actor.IsVisible() );
+
+  // Start Show animation
+  animation = Animation::New(durationSeconds);
+  animation.Show(actor, durationSeconds/*Show at end*/);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_CHECK( actor.IsVisible() );
+  END_TEST;
+}
+
+int UtcDaliKeyFramesCreateDestroyP(void)
+{
+  tet_infoline("Testing Dali::Animation::UtcDaliKeyFramesCreateDestroy()");
+
+  KeyFrames* keyFrames = new KeyFrames;
+  delete keyFrames;
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+int UtcDaliKeyFramesDownCastP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Animation::KeyFramesDownCast()");
+
+  KeyFrames keyFrames = KeyFrames::New();
+  BaseHandle object(keyFrames);
+
+  KeyFrames keyFrames2 = KeyFrames::DownCast(object);
+  DALI_TEST_CHECK(keyFrames2);
+
+  KeyFrames keyFrames3 = DownCast< KeyFrames >(object);
+  DALI_TEST_CHECK(keyFrames3);
+
+  BaseHandle unInitializedObject;
+  KeyFrames keyFrames4 = KeyFrames::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!keyFrames4);
+
+  KeyFrames keyFrames5 = DownCast< KeyFrames >(unInitializedObject);
+  DALI_TEST_CHECK(!keyFrames5);
+  END_TEST;
+}
+
+int UtcDaliAnimationCreateDestroyP(void)
+{
+  TestApplication application;
+  Animation* animation = new Animation;
+  DALI_TEST_CHECK( animation );
+  delete animation;
+  END_TEST;
+}
+
+struct UpdateManagerTestConstraint
+{
+  UpdateManagerTestConstraint(TestApplication& application)
+  : mApplication(application)
+  {
+  }
+
+  void operator()( Vector3& current, const PropertyInputContainer& /* inputs */)
+  {
+    mApplication.SendNotification();  // Process events
+  }
+
+  TestApplication& mApplication;
+};
+
+int UtcDaliAnimationUpdateManagerP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Build the animation
+  Animation animation = Animation::New( 0.0f );
+
+  bool signalReceived = false;
+  AnimationFinishCheck finishCheck( signalReceived );
+  animation.FinishedSignal().Connect( &application, finishCheck );
+
+  Vector3 startValue(1.0f, 1.0f, 1.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Constraint constraint = Constraint::New<Vector3>( actor, index, UpdateManagerTestConstraint( application ) );
+  constraint.Apply();
+
+  // Apply animation to actor
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION), Vector3( 100.f, 90.f, 80.f ), AlphaFunction::LINEAR );
+
+  animation.Play();
+
+  application.SendNotification();
+  application.UpdateOnly( 16 );
+
+  finishCheck.CheckSignalNotReceived();
+
+  application.SendNotification();   // Process events
+
+  finishCheck.CheckSignalReceived();
+
+  END_TEST;
+}
+
+int UtcDaliAnimationSignalOrderP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Build the animations
+  Animation animation1 = Animation::New( 0.0f ); // finishes first frame
+  Animation animation2 = Animation::New( 0.02f ); // finishes in 20 ms
+
+  bool signal1Received = false;
+  animation1.FinishedSignal().Connect( &application, AnimationFinishCheck( signal1Received ) );
+
+  bool signal2Received = false;
+  animation2.FinishedSignal().Connect( &application, AnimationFinishCheck( signal2Received ) );
+
+  // Apply animations to actor
+  animation1.AnimateTo( Property(actor, Actor::Property::POSITION), Vector3( 3.0f, 2.0f, 1.0f ), AlphaFunction::LINEAR );
+  animation1.Play();
+  animation2.AnimateTo( Property(actor, Actor::Property::SIZE ), Vector3( 10.0f, 20.0f, 30.0f ), AlphaFunction::LINEAR );
+  animation2.Play();
+
+  DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+
+  application.SendNotification();
+  application.UpdateOnly( 10 ); // 10ms progress
+
+  // no notifications yet
+  DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+
+  application.SendNotification();
+
+  // first completed
+  DALI_TEST_EQUALS( signal1Received, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( signal2Received, false, TEST_LOCATION );
+  signal1Received = false;
+
+  // 1st animation is complete now, do another update with no ProcessEvents in between
+  application.UpdateOnly( 20 ); // 20ms progress
+
+  // ProcessEvents
+  application.SendNotification();
+
+  // 2nd should complete now
+  DALI_TEST_EQUALS( signal1Received, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( signal2Received, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliAnimationExtendDurationP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Register a float property
+  float startValue(10.0f);
+  Property::Index index = actor.RegisterProperty( "test-property", startValue );
+  Stage::GetCurrent().Add(actor);
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float initialDurationSeconds(1.0f);
+  float animatorDelay = 5.0f;
+  float animatorDurationSeconds(5.0f);
+  float extendedDurationSeconds(animatorDelay+animatorDurationSeconds);
+  Animation animation = Animation::New(initialDurationSeconds);
+  float targetValue(30.0f);
+  float relativeValue(targetValue - startValue);
+
+  animation.AnimateTo(Property(actor, index),
+                      targetValue,
+                      TimePeriod(animatorDelay, animatorDurationSeconds));
+
+  // The duration should have been extended
+  DALI_TEST_EQUALS( animation.GetDuration(), extendedDurationSeconds, TEST_LOCATION );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(extendedDurationSeconds*500.0f)/* 50% animation progress, 0% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(extendedDurationSeconds*250.0f)/* 75% animation progress, 50% animator progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), startValue+(relativeValue*0.5f), TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(extendedDurationSeconds*250.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<float>(index), targetValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnimationCustomIntProperty(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  int startValue(0u);
+
+  Property::Index index = actor.RegisterProperty("an-index", startValue);
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), startValue, TEST_LOCATION );
+
+  // Build the animation
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  animation.AnimateTo( Property(actor, index), 20 );
+
+  // Start the animation
+  animation.Play();
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f)/* 50% progress */);
+
+  // We didn't expect the animation to finish yet
+  application.SendNotification();
+  finishCheck.CheckSignalNotReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), 10, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*500.0f) + 1u/*just beyond the animation duration*/);
+
+  // We did expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetProperty<int>(index), 20, TEST_LOCATION );
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-Any.cpp b/automated-tests/src/dali/utc-Dali-Any.cpp
new file mode 100644 (file)
index 0000000..f516cf0
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+// Temp include
+#include <dali/public-api/object/any.h>
+
+namespace
+{
+struct MyStruct
+{
+  MyStruct()
+  : mFloatValue( 0.f ),
+    mIntValue( 0 )
+  {}
+
+  MyStruct( float fValue, int iValue )
+  : mFloatValue( fValue ),
+    mIntValue( iValue )
+  {}
+
+  MyStruct( const MyStruct& myStruct )
+  : mFloatValue( myStruct.mFloatValue ),
+    mIntValue( myStruct.mIntValue )
+  {}
+
+  MyStruct& operator=( const MyStruct& myStruct )
+  {
+    mFloatValue = myStruct.mFloatValue;
+    mIntValue = myStruct.mIntValue;
+
+    return *this;
+  }
+
+  float mFloatValue;
+  int mIntValue;
+};
+}
+
+using namespace Dali;
+
+void utc_dali_any_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_any_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliAnyConstructors(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test Any constructors.");
+
+  // Test default constructor.
+  Any value;
+
+  DALI_TEST_CHECK( typeid( void ) == value.GetType() );
+
+  // Test constructor Any( const Type& )
+  Any value1 = 4u;
+
+  // Test constructor Any( const Any& )
+  Any value2 = value1;
+
+  // Test constructor Any( const Any& ) with a non initialized Any
+  Any value3 = value;
+
+  DALI_TEST_CHECK( typeid( unsigned int ) == value1.GetType() );
+  DALI_TEST_CHECK( typeid( unsigned int ) == value2.GetType() );
+  DALI_TEST_CHECK( typeid( void ) == value3.GetType() );
+
+  unsigned int uiValue1 = 0u;
+  unsigned int uiValue2 = 0u;
+  value1.Get( uiValue1 );
+  value2.Get( uiValue2 );
+
+  DALI_TEST_EQUALS( uiValue1, uiValue2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliAnyAssignmentOperators(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test assignment operators.");
+
+  float fValue = 0.f;
+
+  Any value1;
+
+  value1 = 4.f; // Test operator=( const Type& ) when current object is not initialized.
+
+  value1.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 4.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  Any value2 = 0.f;
+
+  value2 = 9.f; // Test operator=( const Type& ).
+
+  value2.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 9.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  Any value3 = 5.f;
+
+  value1 = value3; // Test operator=( const Any& ).
+
+  value1.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  Any value4;
+
+  value4 = value3; // Test operator=( const Any& ) when current object is not initialized.
+
+  value4.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // Test assign a value to value3 doesn't modify value1.
+  value3 = 3.f;
+
+  value1.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  value3.Get( fValue );
+
+  DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // Test the branch when copying the same object.
+  Any value5 = 3.f;
+  Any& value6( value5 );
+
+  value6 = value5;
+
+  value6.Get( fValue );
+  DALI_TEST_EQUALS( fValue, 3.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  // test assignment for  non-empty Any = empty Any
+  Any value7;
+  value6 = value7;
+  DALI_TEST_CHECK( value6.Empty() );
+
+
+  END_TEST;
+}
+
+int UtcDaliAnyNegativeAssignmentOperators(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test assignment operators.");
+
+  Any value1 = 4.f;
+  Any value2 = 5u;
+
+  bool assert = false;
+
+  try
+  {
+    value1 = value2; // Test operator=( const Any& );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    assert = true;
+  }
+
+  if( assert )
+  {
+    tet_result( TET_PASS );
+  }
+  else
+  {
+    tet_result( TET_FAIL );
+  }
+  END_TEST;
+}
+
+int UtcDaliAnyGetType(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test GetType().");
+
+  Any value;
+
+  DALI_TEST_CHECK( typeid( void ) == value.GetType() );
+
+  value = 5.f;
+
+  DALI_TEST_CHECK( typeid( float ) == value.GetType() );
+  END_TEST;
+}
+
+int UtcDaliAnyGet(void)
+{
+  TestApplication application;
+
+  tet_infoline("Test Get().");
+
+  Any value1( 5.f );
+
+  float fValue = value1.Get<float>();
+
+  DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  fValue = 0.f;
+  value1.Get( fValue );
+  DALI_TEST_EQUALS( fValue, 5.f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+
+  class MyClass
+  {
+  public:
+    MyClass( float fValue, int iValue )
+    : mAny( MyStruct( fValue, iValue ) )
+    {
+    }
+
+    const MyStruct& Get() const
+    {
+      return AnyCastReference<MyStruct>( mAny );
+    }
+
+    MyStruct* GetPointer()
+    {
+      return AnyCast<MyStruct>( &mAny );
+    }
+
+    const MyStruct* GetPointer() const
+    {
+      return AnyCast<MyStruct>( &mAny );
+    }
+
+  private:
+    Dali::Any mAny;
+  };
+
+  MyClass myClass( 3.25f, 3 );
+
+  MyStruct myStruct1 = myClass.Get();
+  const MyStruct& myStruct2 = myClass.Get();
+  MyStruct* myStruct3 = myClass.GetPointer();
+  const MyStruct* myStruct4 = myClass.GetPointer();
+
+  DALI_TEST_EQUALS( myStruct1.mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct2.mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct3->mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct4->mFloatValue, 3.25f, Math::MACHINE_EPSILON_1000, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct1.mIntValue, 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct2.mIntValue, 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct3->mIntValue, 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( myStruct4->mIntValue, 3, TEST_LOCATION );
+
+  // Test on empty any object
+  Dali::Any myAny;
+  float* f = myAny.GetPointer<float>();
+  DALI_TEST_CHECK( f == NULL );
+
+  // Test on getting wrong type
+  myAny = 1.f;
+  try
+  {
+    myAny.GetPointer<int>();
+    tet_result( TET_FAIL );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliAnyNegativeGet(void)
+{
+  TestApplication application;
+  tet_infoline("Test Get().");
+
+  Any value1;
+  Any value2( 5.f );
+
+  bool assert1 = false;
+  bool assert2 = false;
+
+  unsigned int uiValue = 0u;
+
+  try
+  {
+    uiValue = value1.Get< unsigned int >();
+  }
+
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    assert1 = true;
+  }
+
+  try
+  {
+    uiValue = value2.Get< unsigned int >();
+  }
+
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    assert2 = true;
+  }
+
+  if( assert1 && assert2 )
+  {
+    tet_result( TET_PASS );
+  }
+  else
+  {
+    tet_result( TET_FAIL );
+  }
+  uiValue++;  // supresss warning from unused variable
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-BaseHandle.cpp b/automated-tests/src/dali/utc-Dali-BaseHandle.cpp
new file mode 100644 (file)
index 0000000..9e3da41
--- /dev/null
@@ -0,0 +1,535 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+
+#include "dali-test-suite-utils/dali-test-suite-utils.h"
+
+using namespace Dali;
+
+
+void utc_base_handle_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+// Called after each test
+void utc_base_handle_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+// Functor to test whether an animation finish signal is emitted
+struct AnimationFinishCheck
+{
+  AnimationFinishCheck(bool& signalReceived)
+  : mSignalReceived(signalReceived)
+  {
+  }
+
+  void operator()(Animation& animation)
+  {
+    mSignalReceived = true;
+  }
+
+  void Reset()
+  {
+    mSignalReceived = false;
+  }
+
+  void CheckSignalReceived()
+  {
+    if (!mSignalReceived)
+    {
+      tet_printf("Expected Finish signal was not received\n");
+      tet_result(TET_FAIL);
+    }
+    else
+    {
+      tet_result(TET_PASS);
+    }
+  }
+
+  bool& mSignalReceived; // owned by individual tests
+};
+
+BaseHandle ImplicitCopyConstructor(BaseHandle passedByValue)
+{
+  // object + copy + passedByValue, ref count == 3
+  DALI_TEST_CHECK(passedByValue);
+  if (passedByValue)
+  {
+    DALI_TEST_EQUALS(3, passedByValue.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  return passedByValue;
+}
+
+static bool gTouchCallBackCalled;
+
+struct TestCallback
+{
+  void operator()()
+  {
+    gTouchCallBackCalled = true;
+  }
+};
+
+// Used for testing BaseObject::GetTypeName with an object that is not registered
+class FakeObject : public BaseObject
+{
+};
+// used for testing ThisIsSaferThanReturningVoidStar
+class FakeHandle :  public BaseHandle
+{
+public:
+
+  void RunTest()
+  {
+    return ThisIsSaferThanReturningVoidStar();
+  }
+};
+} // anon namespace
+
+int UtcDaliBaseHandleConstructorVoid(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::BaseHandle()");
+
+  BaseHandle object;
+
+  DALI_TEST_CHECK(!object);
+  END_TEST;
+}
+
+
+int UtcDaliBaseHandleCopyConstructor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::BaseHandle(const BaseHandle&)");
+
+  // Initialize an object, ref count == 1
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  // Copy the object, ref count == 2
+  BaseHandle copy(object);
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  {
+    // Pass by value, and return another copy, ref count == 3
+    BaseHandle anotherCopy = ImplicitCopyConstructor(copy);
+
+    DALI_TEST_CHECK(anotherCopy);
+    if (anotherCopy)
+    {
+      DALI_TEST_EQUALS(3, anotherCopy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+    }
+  }
+
+  // anotherCopy out of scope, ref count == 2
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliBaseHandleAssignmentOperator(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::operator=");
+
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+  if (object)
+  {
+    DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  BaseHandle copy = object;
+
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliBaseHandleGetBaseObject(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetBaseObject()");
+
+  BaseHandle object = Actor::New();
+
+  BaseObject& handle = object.GetBaseObject();
+
+  DALI_TEST_EQUALS(1, handle.ReferenceCount(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliBaseHandleReset(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::Reset()");
+
+  // Initialize an object, ref count == 1
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  object.Reset();
+
+  DALI_TEST_CHECK(!object);
+  END_TEST;
+}
+
+int UtcDaliBaseHandleEqualityOperator01(void)
+{
+  TestApplication application;
+  tet_infoline("Positive Test Dali::BaseHandle::operator==");
+
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+
+  BaseHandle theSameBaseHandle = object;
+
+  DALI_TEST_CHECK(object == theSameBaseHandle);
+  END_TEST;
+}
+
+int UtcDaliBaseHandleEqualityOperator02(void)
+{
+  TestApplication application;
+  tet_infoline("Negative Test Dali::BaseHandle::operator==");
+
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+
+  BaseHandle aDifferentBaseHandle = Actor::New();
+
+  DALI_TEST_CHECK(!(object == aDifferentBaseHandle));
+  END_TEST;
+}
+
+int UtcDaliBaseHandleInequalityOperator01(void)
+{
+  TestApplication application;
+  tet_infoline("Positive Test Dali::BaseHandle::operator!=");
+
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+
+  BaseHandle aDifferentBaseHandle = Actor::New();
+
+  DALI_TEST_CHECK(object != aDifferentBaseHandle);
+  END_TEST;
+}
+
+int UtcDaliBaseHandleInequalityOperator02(void)
+{
+  TestApplication application;
+  tet_infoline("Negative Test Dali::BaseHandle::operator!=");
+
+  BaseHandle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+
+  BaseHandle theSameBaseHandle = object;
+
+  DALI_TEST_CHECK(!(object != theSameBaseHandle));
+  END_TEST;
+}
+
+int UtcDaliBaseHandleStlVector(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle compatibility with std::vector");
+
+  const int TargetVectorSize(5);
+
+  std::vector<Actor> myVector;
+
+  for (int i=0; i<TargetVectorSize; ++i)
+  {
+    Actor actor = Actor::New();
+
+    std::stringstream stream;
+    stream << "Actor " << i+1;
+    actor.SetName(stream.str());
+
+    myVector.push_back(actor);
+  }
+
+  DALI_TEST_EQUALS(TargetVectorSize, static_cast<int>(myVector.size()), TEST_LOCATION);
+
+  DALI_TEST_CHECK(myVector[0].GetName() == "Actor 1");
+  DALI_TEST_CHECK(myVector[1].GetName() == "Actor 2");
+  DALI_TEST_CHECK(myVector[2].GetName() == "Actor 3");
+  DALI_TEST_CHECK(myVector[3].GetName() == "Actor 4");
+  DALI_TEST_CHECK(myVector[4].GetName() == "Actor 5");
+  END_TEST;
+}
+
+int UtcDaliBaseHandleDoAction(void)
+{
+  TestApplication application;
+  tet_infoline("Positive Test Dali::BaseHandle::UtcDaliBaseHandleDoAction");
+
+  Actor actor = Actor::New();
+  BaseHandle actorObject = actor;
+
+  DALI_TEST_CHECK(actorObject);
+
+  // Check that an invalid command is not performed
+  Property::Map attributes;
+  DALI_TEST_CHECK(actorObject.DoAction("invalidCommand", attributes) == false);
+
+  // Check that the actor is visible
+  actor.SetVisible(true);
+  DALI_TEST_CHECK(actor.IsVisible() == true);
+
+  // Check the actor performed an action to hide itself
+  DALI_TEST_CHECK(actorObject.DoAction("hide", attributes) == true);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Check that the actor is now invisible
+  DALI_TEST_CHECK(actor.IsVisible() == false);
+
+  // Check the actor performed an action to show itself
+  DALI_TEST_CHECK(actorObject.DoAction("show", attributes) == true);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Check that the actor is now visible
+  DALI_TEST_CHECK(actor.IsVisible() == true);
+
+  Stage::GetCurrent().Add(actor);
+
+  // Build an animation with initial duration of 1 second
+  float durationSeconds(1.0f);
+  Animation animation = Animation::New(durationSeconds);
+  BaseHandle animationObject = animation;
+
+  DALI_TEST_CHECK(animationObject);
+
+  // Check the current animation duration is 1 second
+  DALI_TEST_EQUALS(animation.GetDuration(), durationSeconds, TEST_LOCATION);
+
+  Vector3 targetPosition(100.0f, 100.0f, 100.0f);
+  animation.AnimateTo(Property(actor, Actor::Property::POSITION), targetPosition, AlphaFunction::LINEAR);
+
+  // Set the new duration to be 2 seconds
+  float newDurationSeconds(2.0f);
+  Property::Value newDurationSecondsValue = Property::Value( newDurationSeconds );
+  attributes["duration"] = newDurationSecondsValue;
+
+  // Check the animation performed an action to play itself with the specified duration of 2 seconds
+  animationObject.DoAction("play", attributes);
+
+  bool signalReceived(false);
+  AnimationFinishCheck finishCheck(signalReceived);
+  animation.FinishedSignal().Connect(&application, finishCheck);
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(newDurationSeconds * 1000.0f) + 1u/*just beyond the animation duration*/);
+
+  // We expect the animation to finish
+  application.SendNotification();
+  finishCheck.CheckSignalReceived();
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), targetPosition, TEST_LOCATION );
+
+  // Check the new animation duration is 2 seconds
+  DALI_TEST_EQUALS(animation.GetDuration(), newDurationSeconds, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliBaseHandleConnectSignal(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::ConnectSignal");
+
+  gTouchCallBackCalled = false;
+
+  // get the root layer
+  Actor actor = Actor::New();
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.SetPosition( 240, 400 );
+  actor.SetSize( 100, 100 );
+
+  Stage::GetCurrent().Add( actor );
+
+  DALI_TEST_CHECK( gTouchCallBackCalled == false );
+
+  // connect to its touch signal
+  actor.ConnectSignal( &application, "touched", TestCallback() );
+
+  application.SendNotification();
+  application.Render(1000);
+  application.SendNotification();
+  application.Render(1000);
+
+  // simulate a touch event
+  Dali::TouchPoint point( 0, TouchPoint::Down, 240, 400  );
+  Dali::Integration::TouchEvent event;
+  event.AddPoint( point );
+  application.ProcessEvent( event );
+
+  application.SendNotification();
+  application.Render(1000);
+  application.SendNotification();
+  application.Render(1000);
+
+  DALI_TEST_CHECK( application.GetConnectionCount() > 0 );
+  DALI_TEST_CHECK( gTouchCallBackCalled == true );
+
+  gTouchCallBackCalled = false;
+  application.DisconnectAll();
+
+  // simulate another touch event
+  application.ProcessEvent( event );
+
+  DALI_TEST_CHECK( gTouchCallBackCalled == false );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleGetTypeNameP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetTypeName");
+
+  // get the root layer
+  Actor actor = Actor::New();
+
+  std::string typeName = actor.GetTypeName();
+
+  DALI_TEST_CHECK( typeName.size() );
+  DALI_TEST_CHECK( typeName == std::string("Actor") );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleGetTypeNameN(void)
+{
+
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseObject::GetTypeName");
+  FakeObject object;
+  std::string typeName = object.GetTypeName();
+
+  DALI_TEST_CHECK( typeName.empty() );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleGetTypeInfoP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetTypeInfo");
+
+  Dali::TypeInfo info;
+  Actor actor = Actor::New();
+
+  bool ok = actor.GetTypeInfo( info );
+  DALI_TEST_CHECK( ok );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleThisIsSaferThanReturningVoidStar(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetTypeInfo");
+  FakeHandle handle;
+  handle.RunTest();
+  tet_result(TET_PASS);
+  END_TEST;
+
+}
+
+int UtcDaliBaseHandleGetTypeInfoN(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetTypeInfo");
+
+  Dali::TypeInfo info;
+  FakeObject object;
+
+  bool ok = object.GetTypeInfo( info );
+  DALI_TEST_CHECK( !ok );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleGetObjectPtr(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::GetObjectPtr");
+
+  // get the root layer
+  Actor actor = Actor::New();
+
+  Dali::RefObject* p = actor.GetObjectPtr();
+
+  DALI_TEST_CHECK( p != NULL );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleBooleanCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BaseHandle::BooleanType");
+
+  // get the root layer
+  BaseHandle handle = Actor::New();
+
+  DALI_TEST_CHECK( static_cast<BaseHandle::BooleanType>( handle ) );
+  END_TEST;
+}
+
+int UtcDaliBaseHandleCompareOperatorN(void)
+{
+  TestApplication application;
+  BaseHandle handle1 = Actor::New();
+  BaseHandle handle2 = handle1;
+
+  DALI_TEST_CHECK( (handle1 < handle2) == false );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-BufferImage.cpp b/automated-tests/src/dali/utc-Dali-BufferImage.cpp
new file mode 100644 (file)
index 0000000..bd3a05c
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using std::max;
+using namespace Dali;
+
+void utc_dali_buffer_image_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_buffer_image_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliBufferImageNew01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageNew01 - BufferImage::New(unsigned int, unsigned int, Pixel::Format)");
+
+  // invoke default handle constructor
+  BufferImage image;
+
+  // initialise handle
+  image = BufferImage::New(16, 16);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetWidth() == 16);
+  END_TEST;
+}
+
+int UtcDaliBufferImageNew02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageNew02 - BufferImage::New(PixelBuffer*, unsigned int, unsigned int, Pixel::Format, unsigned int)");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetWidth() == 16);
+
+  delete [] buffer;
+  END_TEST;
+}
+
+int UtcDaliBufferImageNewWithPolicy01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageNewWithPolicy01 - BufferImage::New(unsigned int, unsigned int, Pixel::Format, LoadPolicy, ReleasePolicy)");
+
+  // Force texture id's
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  // invoke default handle constructor
+  BufferImage image;
+
+  // initialise handle
+  image = BufferImage::New(16, 16, Pixel::A8, Image::UNUSED);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetWidth() == 16);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  // testing ReleasePolicy::Unused
+  // fake loading image
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // discard texture when actor comes off stage
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) );
+  END_TEST;
+}
+
+int UtcDaliBufferImageNewWithPolicy02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageNewWithPolicy02 - BufferImage::New(PixelBuffer*, unsigned int, unsigned int, Pixel::Format, unsigned int, ReleasePolicy)");
+
+  // Force texture id's
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8, 16, Image::UNUSED);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetWidth() == 16);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  // testing ReleasePolicy::Unused
+  // fake loading image
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // discard texture when actor comes off stage
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) );
+  END_TEST;
+}
+
+int UtcDaliBufferImageDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BufferImage::DownCast()");
+
+  BufferImage bitmap = BufferImage::New(1, 1, Dali::Pixel::BGRA8888);
+  ImageActor imageActor = ImageActor::New(bitmap);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  Image image = imageActor.GetImage();
+  BufferImage bufferImage = BufferImage::DownCast( image );
+
+  DALI_TEST_CHECK(bufferImage);
+  END_TEST;
+}
+
+int UtcDaliBufferImageDownCast2(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::BufferImage::DownCast()");
+
+  Image image = ResourceImage::New("IncorrectImageName");
+  ImageActor imageActor = ImageActor::New(image);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  Image image1 = imageActor.GetImage();
+
+  BufferImage bufferImage = BufferImage::DownCast( image1 );
+  DALI_TEST_CHECK(!bufferImage);
+
+  Actor unInitialzedActor;
+  bufferImage = BufferImage::DownCast( unInitialzedActor );
+  DALI_TEST_CHECK(!bufferImage);
+  END_TEST;
+}
+
+int UtcDaliBufferImageWHITE(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageWHITE - BufferImage::WHITE()");
+
+  BufferImage image = BufferImage::WHITE();               // creates a 1x1 RGBA white pixel
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  PixelBuffer* buffer = image.GetBuffer();
+
+  DALI_TEST_CHECK( image.GetWidth() == 1 &&               // 1 pixel wide
+                   buffer != NULL &&                      // valid buffer
+                   *buffer == 0xff);                       // r component is 255
+  END_TEST;
+}
+
+int UtcDaliBufferImageGetBuffer(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageGetBuffer");
+
+  BufferImage image = BufferImage::WHITE();               // creates a 1x1 RGBA white pixel
+
+  PixelBuffer* buffer = image.GetBuffer();
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetWidth() == 1 &&               // 1 pixel wide
+                   buffer != NULL &&                      // valid buffer
+                   *((unsigned int*)buffer) == 0xffffffff); // all component are 255
+  END_TEST;
+}
+
+int UtcDaliBufferImageGetBufferSize(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageGetBufferSize");
+
+  BufferImage image = BufferImage::WHITE();               // creates a 1x1 RGBA white pixel
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  PixelBuffer* buffer = image.GetBuffer();
+  unsigned int bufferSize = image.GetBufferSize();
+  unsigned int pixelSize = Pixel::GetBytesPerPixel(image.GetPixelFormat());
+
+  DALI_TEST_CHECK( image.GetWidth() == 1 &&               // 1 pixel wide
+                   buffer != NULL &&                      // valid buffer
+                   bufferSize == pixelSize);              // r component is 255
+  END_TEST;
+}
+
+int UtcDaliBufferImageGetBufferStride(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageGetBufferStride");
+
+  BufferImage image = BufferImage::WHITE();               // creates a 1x1 RGBA white pixel
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  unsigned int pixelSize = Pixel::GetBytesPerPixel(image.GetPixelFormat());
+  unsigned int bufferStride = image.GetBufferStride();
+  DALI_TEST_CHECK( bufferStride == pixelSize );
+  DALI_TEST_CHECK( !image.IsDataExternal() );
+
+  PixelBuffer* buffer = new PixelBuffer[20 * 16];
+  image = BufferImage::New(buffer, 16, 16, Pixel::A8, 20);
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  bufferStride = image.GetBufferStride();
+
+  DALI_TEST_CHECK( bufferStride == 20);
+  DALI_TEST_CHECK( image.IsDataExternal() );
+
+  delete [] buffer;
+  END_TEST;
+}
+
+int UtcDaliBufferImageGetPixelFormat(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageGetPixelFormat");
+
+  // Set pixel format to a non-default
+  BufferImage image = BufferImage::New( 16, 16, Pixel::A8 );
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.GetPixelFormat() == Pixel::A8 );
+  END_TEST;
+}
+
+
+int UtcDaliBufferImageIsDataExternal(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageIsDataExternal - BufferImage::IsDataExternal()");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.IsDataExternal() );
+  END_TEST;
+}
+
+namespace
+{
+
+static bool SignalReceived;
+static void ImageUploaded(Image image)
+{
+  tet_infoline("Received image uploaded signal");
+  SignalReceived = true;
+}
+}
+
+int UtcDaliBufferImageUpdate01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageUpdate01 - single empty rect");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+  actor.SetVisible(true);
+
+  SignalReceived = false;
+  image.UploadedSignal().Connect( ImageUploaded );
+
+  std::vector<GLuint> ids;
+  ids.push_back(200);
+  ids.push_back(201);
+  ids.push_back(202);
+  application.GetGlAbstraction().SetNextTextureIds(ids);
+
+  // Allow actor to be staged and rendered
+  application.SendNotification();
+  application.Render(0);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.IsDataExternal() );
+  application.GetGlAbstraction().EnableTextureCallTrace(true);
+
+  image.Update();//(RectArea()); // notify Core that the image has been updated
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  const TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(0, "TexSubImage2D", "0, 0, 16, 16"), true, TEST_LOCATION);
+
+  DALI_TEST_CHECK( SignalReceived == true );
+  SignalReceived = false;
+  END_TEST;
+}
+
+int UtcDaliBufferImageUpdate02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageUpdate02 - Multiple rects");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+  actor.SetVisible(true);
+
+  SignalReceived = false;
+  image.UploadedSignal().Connect( ImageUploaded );
+
+  std::vector<GLuint> ids;
+  ids.push_back(200);
+  ids.push_back(201);
+  ids.push_back(202);
+  application.GetGlAbstraction().SetNextTextureIds(ids);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image.IsDataExternal() );
+  application.GetGlAbstraction().EnableTextureCallTrace(true);
+
+  image.Update(RectArea(9,9,5,5));              // notify Core that the image has been updated
+
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  const TraceCallStack& callStack = application.GetGlAbstraction().GetTextureTrace();
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(0, "TexSubImage2D", "9, 9, 5, 1"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(1, "TexSubImage2D", "9, 10, 5, 1"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(2, "TexSubImage2D", "9, 11, 5, 1"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(3, "TexSubImage2D", "9, 12, 5, 1"), true, TEST_LOCATION);
+  DALI_TEST_EQUALS( callStack.TestMethodAndParams(4, "TexSubImage2D", "9, 13, 5, 1"), true, TEST_LOCATION);
+
+  DALI_TEST_CHECK( SignalReceived == true );
+  SignalReceived = false;
+  END_TEST;
+}
+
+int UtcDaliBufferImageUploadedSignal01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageUploadedSignal - Test that Uploaded signal is sent when image is staged");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  SignalReceived = false;
+  image.UploadedSignal().Connect( ImageUploaded );
+
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  Dali::ImageActor imageActor = ImageActor::New(image);
+  Stage::GetCurrent().Add(imageActor);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( SignalReceived == true );
+  END_TEST;
+}
+
+int UtcDaliBufferImageUploadedSignal02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliBufferImageUploadedSignal - Test that Uploaded signal is sent after Update");
+
+  PixelBuffer* buffer = new PixelBuffer[16 * 16];
+  BufferImage image = BufferImage::New(buffer, 16, 16, Pixel::A8);
+  SignalReceived = false;
+  //ScopedConnection connection =
+  image.UploadedSignal().Connect( ImageUploaded );
+
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  Dali::ImageActor imageActor = ImageActor::New(image);
+  Stage::GetCurrent().Add(imageActor);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK( SignalReceived == true );
+  SignalReceived = false;
+
+  image.Update(RectArea());              // notify Core that the whole image has been updated
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK( SignalReceived == true );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-CameraActor.cpp b/automated-tests/src/dali/utc-Dali-CameraActor.cpp
new file mode 100644 (file)
index 0000000..15e86c4
--- /dev/null
@@ -0,0 +1,1552 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <cmath>
+#include <dali/public-api/dali-core.h>
+
+#include "dali-test-suite-utils/dali-test-suite-utils.h"
+
+using namespace Dali;
+
+void camera_actor_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void camera_actor_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+const float FLOAT_EPSILON = 0.001f;
+const float TEST_ASPECT_RATIO = 0.123f;
+const float TEST_FIELD_OF_VIEW = Radian(Degree(40.0f));
+const float TEST_NEAR_PLANE_DISTANCE = 0.23f;
+const float TEST_FAR_PLANE_DISTANCE = 0.973f;
+
+const std::string SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME( "uLightCameraProjectionMatrix" );
+const std::string SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME( "uLightCameraViewMatrix" );
+const char* const RENDER_SHADOW_VERTEX_SOURCE =
+  " uniform mediump mat4 uLightCameraProjectionMatrix;\n"
+  " uniform mediump mat4 uLightCameraViewMatrix;\n"
+  "\n"
+  "void main()\n"
+  "{\n"
+  "  gl_Position = uProjection * uModelView * vec4(aPosition,1.0);\n"
+  "  vec4 textureCoords = uLightCameraProjectionMatrix * uLightCameraViewMatrix * uModelMatrix  * vec4(aPosition,1.0);\n"
+  "  vTexCoord = 0.5 + 0.5 * (textureCoords.xy/textureCoords.w);\n"
+  "}\n";
+
+const char* const RENDER_SHADOW_FRAGMENT_SOURCE =
+  "uniform lowp vec4 uShadowColor;\n"
+  "void main()\n"
+  "{\n"
+  "  lowp float alpha;\n"
+  "  alpha = texture2D(sTexture, vec2(vTexCoord.x, vTexCoord.y)).a;\n"
+  "  gl_FragColor = vec4(uShadowColor.rgb, uShadowColor.a * alpha);\n"
+  "}\n";
+
+} // Anonymous namespace
+
+
+int UtcDaliCameraActorConstructorP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::CameraActor()" );
+
+  CameraActor actor;
+
+  DALI_TEST_CHECK( !actor );
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliCameraActorConstructor.
+
+int UtcDaliCameraActorDestructorP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::~CameraActor (P)" );
+  CameraActor* actor = new CameraActor();
+  delete actor;
+  actor = NULL;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliCameraActorDestructor.
+
+int UtcDaliCameraActorCopyConstructorP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Copy Constructor (P)" );
+  CameraActor actor = CameraActor::New();
+
+  CameraActor copyActor( actor );
+
+  DALI_TEST_CHECK( copyActor );
+  DALI_TEST_CHECK( copyActor == actor );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorCopyConstructorN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Copy Constructor (N)" );
+  CameraActor actor;
+
+  CameraActor copyActor( actor );
+
+  DALI_TEST_CHECK( !copyActor );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorAssignmentOperatorP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Assignment Operator (P)" );
+  const CameraActor actor = CameraActor::New();
+
+  CameraActor copyActor = actor;
+
+  DALI_TEST_CHECK( copyActor );
+  DALI_TEST_CHECK( copyActor == actor );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorAssignmentOperatorN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor = (N)" );
+  CameraActor actor;
+
+  CameraActor copyActor = actor;
+
+  DALI_TEST_CHECK( !copyActor );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorNewP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::New (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  DALI_TEST_CHECK( actor );
+
+  actor.Reset();
+
+  DALI_TEST_CHECK( !actor );
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliCameraActorNew.
+
+int UtcDaliCameraActorDownCastP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::DownCast (P)" );
+
+  CameraActor camera = CameraActor::New();
+  Actor anActor = Actor::New();
+  anActor.Add( camera );
+
+  Actor child = anActor.GetChildAt( 0 );
+  CameraActor cameraActor = CameraActor::DownCast( child );
+  DALI_TEST_CHECK( cameraActor );
+
+  cameraActor.Reset();
+  DALI_TEST_CHECK( !cameraActor );
+
+  cameraActor = DownCast< CameraActor >( child );
+  DALI_TEST_CHECK( cameraActor );
+  END_TEST;
+}
+
+int UtcDaliCameraActorDownCastN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::DownCast (N)" );
+
+  Actor actor1 = Actor::New();
+  Actor anActor = Actor::New();
+  anActor.Add( actor1 );
+
+  Actor child = anActor.GetChildAt( 0 );
+  CameraActor cameraActor = CameraActor::DownCast( child );
+  DALI_TEST_CHECK( !cameraActor );
+
+  Actor unInitialzedActor;
+  cameraActor = CameraActor::DownCast( unInitialzedActor );
+  DALI_TEST_CHECK( !cameraActor );
+
+  cameraActor = DownCast< CameraActor >( unInitialzedActor );
+  DALI_TEST_CHECK( !cameraActor );
+  END_TEST;
+}
+
+// Note: SetType and GetType are tested within the same test cases.
+
+int UtcDaliCameraActorSetGetTypeP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor GetType (P)" );
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetType(), Dali::Camera::FREE_LOOK, TEST_LOCATION );
+
+  actor.SetType( Dali::Camera::LOOK_AT_TARGET );
+  DALI_TEST_EQUALS( actor.GetType(), Dali::Camera::LOOK_AT_TARGET, TEST_LOCATION );
+
+  std::string sValue;
+  actor.GetProperty( CameraActor::Property::TYPE ).Get( sValue );
+  std::string result( "LOOK_AT_TARGET");
+  DALI_TEST_EQUALS( result, sValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetGetTypeN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor GetType (N)" );
+
+  CameraActor actor;
+
+  Dali::Camera::Type cameraType = Dali::Camera::FREE_LOOK;
+  try
+  {
+    cameraType = actor.GetType();
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera", TEST_LOCATION );
+  }
+
+  const CameraActor aConstActor;
+
+  try
+  {
+    cameraType = aConstActor.GetType();
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera", TEST_LOCATION );
+  }
+
+  DALI_TEST_EQUALS( (int)cameraType, (int)Dali::Camera::FREE_LOOK, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetFieldOfViewP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Field of view (P)" );
+
+  CameraActor defaultCamera = CameraActor::New( Size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT ) );
+  const float defaultFieldOfView = defaultCamera.GetFieldOfView();
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetFieldOfView(), defaultFieldOfView, TEST_LOCATION );
+
+  float fieldOfView = Math::PI / 3.0f;
+  actor.SetFieldOfView( fieldOfView );
+  DALI_TEST_EQUALS( actor.GetFieldOfView(), fieldOfView, TEST_LOCATION );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( fieldOfView, value, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetFieldOfViewN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Field of view (N)" );
+
+  CameraActor defaultCamera = CameraActor::New( Size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT ) );
+  const float defaultFieldOfView = defaultCamera.GetFieldOfView();
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetFieldOfView(), defaultFieldOfView, TEST_LOCATION );
+
+  float fieldOfView = Math::PI / 3.0f;
+  actor.SetFieldOfView( fieldOfView );
+  DALI_TEST_EQUALS( actor.GetFieldOfView(), fieldOfView, TEST_LOCATION );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( fieldOfView, value, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetFieldOfViewP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Field of view (P)" );
+  const Vector2 size( TestApplication::DEFAULT_SURFACE_WIDTH, TestApplication::DEFAULT_SURFACE_HEIGHT );
+
+  CameraActor defaultCamera = CameraActor::New( size );
+
+  const float cameraZ = 2.0f * std::max( size.width, size.height );
+  const float expectedFieldOfView = 2.0f * std::atan( size.height * 0.5f / cameraZ );
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetFieldOfView(), expectedFieldOfView, TEST_LOCATION );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( expectedFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetFieldOfViewN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Field of view (N)" );
+
+  CameraActor defaultCamera = CameraActor::New();
+
+  bool asserted = true;
+  try
+  {
+    defaultCamera.GetFieldOfView();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+//todor
+int UtcDaliCameraActorSetAspectRatioP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Aspect Ratio (P)" );
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), static_cast<float>( TestApplication::DEFAULT_SURFACE_WIDTH ) / static_cast<float>( TestApplication::DEFAULT_SURFACE_HEIGHT ), TEST_LOCATION );
+
+  // Set an initial value to confirm a further set changes it.
+  float aspect = 4.0f / 3.0f;
+  actor.SetAspectRatio( aspect );
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), aspect, TEST_LOCATION );
+
+  aspect = 16.0f / 9.0f;
+  actor.SetAspectRatio( aspect );
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), aspect, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetAspectRatioN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Aspect Ratio (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetAspectRatio( 16.0f / 9.0f );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetAspectRatioP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CameraActor Get Aspect Ratio");
+
+  CameraActor actor = CameraActor::New();
+  float defaultAspect = static_cast<float>( TestApplication::DEFAULT_SURFACE_WIDTH ) / static_cast<float>( TestApplication::DEFAULT_SURFACE_HEIGHT );
+
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), defaultAspect, TEST_LOCATION );
+
+  float value = 0.0f;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( defaultAspect, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetAspectRatioN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Aspect Ratio (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.GetAspectRatio();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetNearClippingPlaneP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Near clipping plane (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  // Set a value so we are not relying on a particular default for this test case.
+  actor.SetNearClippingPlane( 200.0f );
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, TEST_LOCATION );
+
+  actor.SetNearClippingPlane( 400.0f );
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 400.0f, TEST_LOCATION );
+
+  // Check setting the property.
+  actor.SetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE, Property::Value( 300.0f ) );
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 300.0f, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetNearClippingPlaneN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Near clipping plane (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetNearClippingPlane( 200.0f );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetNearClippingPlaneP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Near clipping plane (P)" );
+
+  // Check the default value.
+  CameraActor actor = CameraActor::New();
+  float defaultValue = 800.0f;
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), defaultValue, TEST_LOCATION );
+
+  // Check getting the property.
+  float value;
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetNearClippingPlaneN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Near clipping plane (N)" );
+
+  CameraActor actor;
+  bool asserted = true;
+  try
+  {
+    actor.GetNearClippingPlane();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetFarClippingPlaneP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Far clipping plane (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  // Set a value so we are not relying on a particular default for this test case.
+  actor.SetFarClippingPlane( 2000.0f );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 2000.0f, TEST_LOCATION );
+
+  actor.SetFarClippingPlane( 4000.0f );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 4000.0f, TEST_LOCATION );
+
+  // Check setting the property.
+  actor.SetProperty( CameraActor::Property::FAR_PLANE_DISTANCE, 2000.0f );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 2000.0f, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetFarClippingPlaneN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Far clipping plane (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetFarClippingPlane( 2000.0f );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetFarClippingPlaneP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Far clipping plane (P)" );
+
+  CameraActor actor = CameraActor::New();
+  float defaultValue = 800.0f + ( 0xFFFF >> 4 );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), defaultValue, TEST_LOCATION );
+
+  // Check getting the property.
+  float value;
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetFarClippingPlaneN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Far clipping plane (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.GetFarClippingPlane();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetTargetPositionP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Target Position (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  Vector3 target1( 10.0f, 20.0f, 30.0f );
+  Vector3 target2( 15.0f, 25.0f, 35.0f );
+
+  // Set a value so we are not relying on a particular default for this test case.
+  actor.SetTargetPosition( target1 );
+  DALI_TEST_EQUALS( actor.GetTargetPosition(), target1, TEST_LOCATION );
+
+  actor.SetTargetPosition( target2 );
+  DALI_TEST_EQUALS( actor.GetTargetPosition(), target2, TEST_LOCATION );
+
+  // Check setting the property.
+  actor.SetProperty( CameraActor::Property::TARGET_POSITION, target1 );
+  DALI_TEST_EQUALS( actor.GetTargetPosition(), target1, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetTargetPositionN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set Target Position (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetTargetPosition( Vector3( 10.0f, 20.0f, 30.0f ) );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetTargetPositionP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Target Position (P)" );
+
+  CameraActor actor = CameraActor::New();
+  Vector3 defaultValue( Vector3::ZERO );
+  DALI_TEST_EQUALS( actor.GetTargetPosition(), defaultValue, TEST_LOCATION );
+
+  // Check getting the property.
+  Vector3 value;
+  actor.GetProperty( CameraActor::Property::TARGET_POSITION ).Get( value );
+  DALI_TEST_EQUALS( defaultValue, value, FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetTargetPositionN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get Target Position (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.GetTargetPosition();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetInvertYAxisP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set InvertYAxis (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  // Set a value so we are not relying on a particular default for this test case.
+  actor.SetInvertYAxis( false );
+  DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION );
+
+  actor.SetInvertYAxis( true );
+  DALI_TEST_EQUALS( actor.GetInvertYAxis(), true, TEST_LOCATION );
+
+  actor.SetProperty( CameraActor::Property::INVERT_Y_AXIS, false );
+  DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetInvertYAxisN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Set InvertYAxis (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetInvertYAxis( false );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetInvertYAxisP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get InvertYAxis (P)" );
+
+  // Check the default value.
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_EQUALS( actor.GetInvertYAxis(), false, TEST_LOCATION );
+
+  // Check getting the property.
+  bool bValue;
+  actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue );
+  DALI_TEST_EQUALS( false, bValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetInvertYAxisN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Get InvertYAxis (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.GetInvertYAxis();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetPerspectiveProjectionP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetPerspectiveProjection (P)" );
+
+  CameraActor actor = CameraActor::New();
+  actor.SetPerspectiveProjection( Size( 100.f, 150.f ) );
+
+  DALI_TEST_CHECK( actor );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( 0.666666f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( 0.489957f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 150.f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 4245.f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetPerspectiveProjectionN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetPerspectiveProjection (N)" );
+
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  CameraActor actor = CameraActor::New();
+
+  // Check that setting perspective projection without a size (using zero size) uses the stages size.
+  actor.SetPerspectiveProjection( Size::ZERO );
+
+  float nearClippingPlane = std::max( stageSize.width, stageSize.height );
+  float farClippingPlane = nearClippingPlane + static_cast<float>( 0xFFFF >> 4 );
+
+  DALI_TEST_EQUALS( nearClippingPlane, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( farClippingPlane, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetOrthographicProjectionP1(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,1)" );
+
+  CameraActor actor = CameraActor::New( Size( 1080.0f, 1920.0f ) );
+  DALI_TEST_CHECK( actor );
+
+  Stage::GetCurrent().Add( actor );
+
+  actor.SetOrthographicProjection( Size( 1080.0f, 1920.0f ) );
+  application.SendNotification();
+  application.Render( 0 );
+  application.Render();
+  application.SendNotification();
+
+  float defaultAspectRatio;
+  float defaultFieldOfView;
+  float defaultNearPlaneDistance;
+  float defaultFarPlaneDistance;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance );
+  Vector3 defaultPos = actor.GetCurrentPosition();
+
+  actor.SetOrthographicProjection( Size( 1080.0f, 1920.0f ) );
+
+  application.SendNotification();
+  application.Render( 0 );
+  application.Render();
+  application.SendNotification();
+
+  float value;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( defaultNearPlaneDistance, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( defaultFarPlaneDistance, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -540.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 540.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 960.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -960.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  Vector3 pos = actor.GetCurrentPosition();
+  DALI_TEST_EQUALS( defaultPos.z, pos.z, 0.001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetOrthographicProjectionN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (N)" );
+
+  CameraActor actor;
+  bool asserted = true;
+  try
+  {
+    actor.GetProjectionMode();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetOrthographicProjectionP2(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,2)" );
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_CHECK( actor );
+
+  float defaultAspectRatio;
+  float defaultFieldOfView;
+  float defaultNearPlaneDistance;
+  float defaultFarPlaneDistance;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance );
+
+  // Check setting with specific near and far plane distances.
+  actor.SetOrthographicProjection( -100.0f, 200.0f, -300.0f, 500.0f, 400.0f, 4000.0f );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 400.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 4000.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -100.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 200.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -300.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 500.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetOrthographicProjectionP3(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetOrthographicProjection (P,3)" );
+
+  CameraActor actor = CameraActor::New();
+  DALI_TEST_CHECK( actor );
+
+  float defaultAspectRatio;
+  float defaultFieldOfView;
+  float defaultNearPlaneDistance;
+  float defaultFarPlaneDistance;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( defaultAspectRatio );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( defaultFieldOfView );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( defaultNearPlaneDistance );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( defaultFarPlaneDistance );
+
+  actor.SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION );
+
+  actor.SetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE, -100.0f );
+  actor.SetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE, 200.0f );
+  actor.SetProperty( CameraActor::Property::TOP_PLANE_DISTANCE, -300.0f );
+  actor.SetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE, 500.0f );
+  actor.SetNearClippingPlane( 400.0f );
+  actor.SetFarClippingPlane( 4000.0f );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( defaultAspectRatio, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( defaultFieldOfView, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 400.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 4000.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  actor.GetProperty( CameraActor::Property::LEFT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -100.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::RIGHT_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 200.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::TOP_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( -300.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::BOTTOM_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( 500.0f, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION );
+  std::string stringValue;
+  actor.GetProperty( CameraActor::Property::PROJECTION_MODE ).Get( stringValue );
+  DALI_TEST_EQUALS( stringValue, "ORTHOGRAPHIC_PROJECTION", TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetProjectionModeP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetProjectionModeP (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  // Check that changing the projection mode alone does not alter other presets.
+  actor.SetNearClippingPlane( 200.0f );
+  actor.SetFarClippingPlane( 400.0f );
+
+  actor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 400.0f, FLOAT_EPSILON, TEST_LOCATION );
+
+  actor.SetProjectionMode( Dali::Camera::ORTHOGRAPHIC_PROJECTION );
+
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetNearClippingPlane(), 200.0f, FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor.GetFarClippingPlane(), 400.0f, FLOAT_EPSILON, TEST_LOCATION );
+
+  // Check setting the property.
+  Property::Value setValue = "PERSPECTIVE_PROJECTION";
+  actor.SetProperty( CameraActor::Property::PROJECTION_MODE, setValue );
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetProjectionModeN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetProjectionModeP (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.SetProjectionMode( Dali::Camera::PERSPECTIVE_PROJECTION );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetProjectionModeP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::GetPerspectiveProjection (P)" );
+
+  CameraActor actor = CameraActor::New();
+
+  actor.SetOrthographicProjection( Size::ONE );
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::ORTHOGRAPHIC_PROJECTION, TEST_LOCATION );
+
+  actor.SetPerspectiveProjection( Size( 100.f, 150.f ) );
+  DALI_TEST_EQUALS( (int)actor.GetProjectionMode(), (int)Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+
+  // Check getting the property.
+  std::string stringValue;
+  actor.GetProperty( CameraActor::Property::PROJECTION_MODE ).Get( stringValue );
+  DALI_TEST_EQUALS( stringValue, "PERSPECTIVE_PROJECTION", TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetProjectionModeN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::GetProjectionMode (N)" );
+
+  CameraActor actor;
+
+  bool asserted = true;
+  try
+  {
+    actor.GetProjectionMode();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "camera && \"Camera handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetCameraOffStage(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetCamera()" );
+
+  CameraActor actor = CameraActor::New();
+
+  actor.SetType( Camera::FREE_LOOK );
+  actor.SetFieldOfView( TEST_FIELD_OF_VIEW );
+  actor.SetAspectRatio( TEST_ASPECT_RATIO );
+  actor.SetNearClippingPlane( TEST_NEAR_PLANE_DISTANCE );
+  actor.SetFarClippingPlane( TEST_FAR_PLANE_DISTANCE );
+  actor.SetProjectionMode( Camera::PERSPECTIVE_PROJECTION );
+
+  actor.SetInvertYAxis( false );
+
+  DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION );//change to machine epsilon
+  DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( Camera::PERSPECTIVE_PROJECTION, actor.GetProjectionMode(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION );
+
+  float value;
+  std::string sValue;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO).Get( value );
+  DALI_TEST_EQUALS( TEST_ASPECT_RATIO, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW).Get( value );
+  DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE).Get( value );
+  DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE).Get( value );
+  DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::PROJECTION_MODE).Get( sValue );
+  DALI_TEST_EQUALS( "PERSPECTIVE_PROJECTION", sValue, TEST_LOCATION );
+  bool bValue;
+  actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS).Get( bValue );
+  DALI_TEST_EQUALS( false, bValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorSetCameraOnStage(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::SetCamera()" );
+
+  CameraActor actor = CameraActor::New();
+  Stage::GetCurrent().Add( actor );
+  application.Render( 0 );
+  application.SendNotification();
+
+  actor.SetType( Camera::LOOK_AT_TARGET );
+  actor.SetFieldOfView( TEST_FIELD_OF_VIEW );
+  actor.SetAspectRatio( TEST_ASPECT_RATIO );
+  actor.SetNearClippingPlane( TEST_NEAR_PLANE_DISTANCE );
+  actor.SetFarClippingPlane( TEST_FAR_PLANE_DISTANCE );
+  actor.SetInvertYAxis( false );
+
+  DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION );
+
+  // Will need 2 frames to ensure both buffers are set to same values:
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, actor.GetInvertYAxis(), TEST_LOCATION );
+
+  std::string sValue;
+  actor.GetProperty( CameraActor::Property::TYPE ).Get( sValue );
+  DALI_TEST_EQUALS( sValue, "LOOK_AT_TARGET", TEST_LOCATION );
+
+  float value;
+  actor.GetProperty( CameraActor::Property::ASPECT_RATIO ).Get( value );
+  DALI_TEST_EQUALS( TEST_ASPECT_RATIO, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FIELD_OF_VIEW ).Get( value );
+  DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE ).Get( value );
+  DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION );
+  actor.GetProperty( CameraActor::Property::FAR_PLANE_DISTANCE ).Get( value);
+  DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, value, FLOAT_EPSILON, TEST_LOCATION );
+
+  bool bValue;
+  actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue );
+  DALI_TEST_EQUALS( false, bValue, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorGetCamera(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::GetCamera()" );
+
+  CameraActor actor = CameraActor::New();
+
+  actor.SetAspectRatio( TEST_ASPECT_RATIO );
+
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), TEST_ASPECT_RATIO, FLOAT_EPSILON, TEST_LOCATION );
+
+  actor.SetProperty( CameraActor::Property::TYPE, "FREE_LOOK" );
+  actor.SetProperty( CameraActor::Property::ASPECT_RATIO, TEST_ASPECT_RATIO );
+  actor.SetProperty( CameraActor::Property::FIELD_OF_VIEW, TEST_FIELD_OF_VIEW );
+  actor.SetProperty( CameraActor::Property::NEAR_PLANE_DISTANCE, TEST_NEAR_PLANE_DISTANCE );
+  actor.SetProperty( CameraActor::Property::FAR_PLANE_DISTANCE, TEST_FAR_PLANE_DISTANCE );
+
+  DALI_TEST_EQUALS( Camera::FREE_LOOK, actor.GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_ASPECT_RATIO, actor.GetAspectRatio(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_FIELD_OF_VIEW, actor.GetFieldOfView(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_NEAR_PLANE_DISTANCE, actor.GetNearClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  DALI_TEST_EQUALS( TEST_FAR_PLANE_DISTANCE, actor.GetFarClippingPlane(), FLOAT_EPSILON, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorDefaultProperties(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor DefaultProperties" );
+
+  CameraActor actor = CameraActor::New();
+
+  actor.SetAspectRatio( TEST_ASPECT_RATIO );
+  Stage::GetCurrent().Add( actor );
+  application.Render( 0 );
+  application.SendNotification();
+  bool bValue;
+  actor.GetProperty( CameraActor::Property::INVERT_Y_AXIS ).Get( bValue );
+  DALI_TEST_EQUALS( false, bValue, TEST_LOCATION );
+
+  std::vector<Property::Index> indices ;
+  indices.push_back( CameraActor::Property::TYPE );
+  indices.push_back( CameraActor::Property::PROJECTION_MODE );
+  indices.push_back( CameraActor::Property::FIELD_OF_VIEW );
+  indices.push_back( CameraActor::Property::ASPECT_RATIO );
+  indices.push_back( CameraActor::Property::NEAR_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::FAR_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::LEFT_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::RIGHT_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::TOP_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::BOTTOM_PLANE_DISTANCE );
+  indices.push_back( CameraActor::Property::TARGET_POSITION );
+  indices.push_back( CameraActor::Property::PROJECTION_MATRIX );
+  indices.push_back( CameraActor::Property::VIEW_MATRIX );
+  indices.push_back( CameraActor::Property::INVERT_Y_AXIS );
+
+  DALI_TEST_CHECK( actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) );
+
+  for( std::vector<Property::Index>::iterator iter = indices.begin(); iter != indices.end(); ++iter )
+  {
+    DALI_TEST_EQUALS( *iter, actor.GetPropertyIndex( actor.GetPropertyName( *iter ) ), TEST_LOCATION);
+    DALI_TEST_CHECK( !actor.IsPropertyAnimatable( *iter ) );
+
+    if ( ( *iter == CameraActor::Property::PROJECTION_MATRIX ) ||
+         ( *iter == CameraActor::Property::VIEW_MATRIX ) )
+    {
+      DALI_TEST_CHECK( !actor.IsPropertyWritable( *iter ) );
+    }
+    else
+    {
+      DALI_TEST_CHECK( actor.IsPropertyWritable( *iter ) );
+    }
+
+    DALI_TEST_CHECK( actor.GetPropertyType( *iter ) == actor.GetPropertyType( *iter ) ); // just checking call succeeds
+  }
+
+  // Set/Get one of them.
+  const float newAspect = TEST_ASPECT_RATIO * 2.0f;
+
+  actor.SetProperty( CameraActor::Property::ASPECT_RATIO, Property::Value( newAspect ) );
+  application.Render();
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS( actor.GetAspectRatio(), newAspect, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorModelView(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor Test view application" );
+
+  BufferImage image = CreateBufferImage();
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetPosition( 20.0f, 30.0f, 40.0f );
+  actor.SetParentOrigin( ParentOrigin::CENTER );
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render( 0 );
+  application.Render();
+  application.SendNotification();
+
+  Matrix resultMatrix( true );
+  resultMatrix.SetTransformComponents( Vector3::ONE, Quaternion::IDENTITY, actor.GetCurrentPosition() );
+
+  RenderTask task = Stage::GetCurrent().GetRenderTaskList().GetTask( 0 );
+  CameraActor cameraActor = task.GetCameraActor();
+
+  Matrix viewMatrix( false );
+  cameraActor.GetProperty( CameraActor::Property::VIEW_MATRIX ).Get( viewMatrix );
+  Matrix::Multiply( resultMatrix, resultMatrix, viewMatrix );
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uModelView", resultMatrix ) );
+  END_TEST;
+}
+
+int UtcDaliCameraActorReadProjectionMatrix(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::CameraActor::ReadProjectionMatrix()" );
+
+  CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor();
+  application.SendNotification();
+  application.Render( 0 );
+  application.Render();
+  application.SendNotification();
+  Image image = CreateBufferImage();
+  ImageActor imageActor = ImageActor::New( image );
+  imageActor.SetSize( 100.0f, 100.0f );
+  Stage::GetCurrent().Add( imageActor );
+
+  Matrix projectionMatrix;
+  Matrix viewMatrix;
+
+  camera.GetProperty( CameraActor::CameraActor::Property::PROJECTION_MATRIX ).Get( projectionMatrix );
+  camera.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( viewMatrix );
+
+  ShaderEffect shaderEffect = ShaderEffect::New( RENDER_SHADOW_VERTEX_SOURCE, RENDER_SHADOW_FRAGMENT_SOURCE );
+  imageActor.SetShaderEffect( shaderEffect );
+
+  shaderEffect.SetUniform( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME, Matrix::IDENTITY );
+  shaderEffect.SetUniform( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME, Matrix::IDENTITY );
+
+  Property::Index projectionMatrixPropertyIndex = shaderEffect.GetPropertyIndex( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME );
+  Property::Index viewMatrixPropertyIndex = shaderEffect.GetPropertyIndex( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME );
+
+  Constraint projectionMatrixConstraint = Constraint::New<Dali::Matrix>( shaderEffect, projectionMatrixPropertyIndex, EqualToConstraint() );
+  projectionMatrixConstraint.AddSource( Source( camera, CameraActor::Property::PROJECTION_MATRIX ) );
+  Constraint viewMatrixConstraint = Constraint::New<Dali::Matrix>( shaderEffect, viewMatrixPropertyIndex, EqualToConstraint() );
+  viewMatrixConstraint.AddSource( Source( camera, CameraActor::Property::VIEW_MATRIX ) );
+
+  projectionMatrixConstraint.Apply();
+  viewMatrixConstraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( SHADER_LIGHT_CAMERA_PROJECTION_MATRIX_PROPERTY_NAME.c_str(), projectionMatrix) );
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( SHADER_LIGHT_CAMERA_VIEW_MATRIX_PROPERTY_NAME.c_str(), viewMatrix ) );
+  END_TEST;
+}
+
+int UtcDaliCameraActorAnimatedProperties(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::Internal::CameraActor::GetSceneObjectAnimatableProperty()" );
+
+  CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor();
+  Actor actor = Actor::New();
+  actor.SetSize( 100.0f, 100.0f );
+  Stage::GetCurrent().Add( actor );
+
+  Constraint constraint = Constraint::New<Dali::Vector3>( actor, Actor::Property::POSITION, EqualToConstraint() );
+  constraint.AddSource( Source( camera, Actor::Property::POSITION ) );
+  constraint.Apply();
+
+  camera.SetPosition( 100.0f, 200.0f, 300.0f );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), Vector3( 100.0f, 200.0f, 300.0f ), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliCameraActorPropertyIndices(void)
+{
+  TestApplication application;
+  CameraActor camera = Stage::GetCurrent().GetRenderTaskList().GetTask( 0u ).GetCameraActor();
+
+  Actor basicActor = Actor::New();
+  Property::IndexContainer indices;
+  camera.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() );
+  DALI_TEST_EQUALS( indices.Size(), camera.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCameraActorCheckLookAtAndFreeLookViews01(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  CameraActor freeLookCameraActor = CameraActor::New( stageSize );
+  freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+  freeLookCameraActor.SetType( Camera::FREE_LOOK );
+
+  Vector3 targetPosition( 30.0f, 240.0f, -256.0f );
+  Actor target = Actor::New();
+  target.SetParentOrigin( ParentOrigin::CENTER );
+  target.SetPosition( targetPosition );
+
+  Constraint cameraOrientationConstraint = Constraint::New<Quaternion> ( freeLookCameraActor, Actor::Property::ORIENTATION, &LookAt );
+  cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_POSITION ) );
+  cameraOrientationConstraint.AddSource( Source( freeLookCameraActor,  Actor::Property::WORLD_POSITION ) );
+  cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_ORIENTATION ) );
+  cameraOrientationConstraint.Apply();
+
+  CameraActor lookAtCameraActor = CameraActor::New( stageSize );
+  lookAtCameraActor.SetType( Camera::LOOK_AT_TARGET );
+  lookAtCameraActor.SetTargetPosition( targetPosition );
+  lookAtCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+
+  stage.Add( target );
+  stage.Add( freeLookCameraActor );
+  stage.Add( lookAtCameraActor );
+
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 position( x, y, z );
+        position.Normalize();
+        position *= 200.0f;
+
+        freeLookCameraActor.SetPosition( position );
+        lookAtCameraActor.SetPosition( position );
+
+        application.SendNotification();
+        application.Render();
+        application.SendNotification();
+        application.Render();
+        Matrix freeLookViewMatrix;
+        Matrix lookAtViewMatrix;
+        freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix );
+        lookAtCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( lookAtViewMatrix );
+
+        DALI_TEST_EQUALS( freeLookViewMatrix, lookAtViewMatrix, 0.01, TEST_LOCATION );
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliCameraActorCheckLookAtAndFreeLookViews02(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  CameraActor freeLookCameraActor = CameraActor::New( stageSize );
+  freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+  freeLookCameraActor.SetType( Camera::FREE_LOOK );
+
+  Vector3 targetPosition( 30.0f, 240.0f, -256.0f );
+  Actor target = Actor::New();
+  target.SetParentOrigin( ParentOrigin::CENTER );
+  target.SetPosition( targetPosition );
+
+  Constraint cameraOrientationConstraint = Constraint::New<Quaternion> ( freeLookCameraActor, Actor::Property::ORIENTATION, &LookAt );
+  cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_POSITION ) );
+  cameraOrientationConstraint.AddSource( Source( freeLookCameraActor,  Actor::Property::WORLD_POSITION ) );
+  cameraOrientationConstraint.AddSource( Source( target, Actor::Property::WORLD_ORIENTATION ) );
+  cameraOrientationConstraint.Apply();
+
+  CameraActor lookAtCameraActor = CameraActor::New( stageSize );
+  lookAtCameraActor.SetType( Camera::LOOK_AT_TARGET );
+  lookAtCameraActor.SetTargetPosition( targetPosition );
+  lookAtCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+
+  stage.Add( target );
+  stage.Add( freeLookCameraActor );
+  stage.Add( lookAtCameraActor );
+
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 position( x, y, z );
+        position.Normalize();
+        position *= 200.0f;
+
+        freeLookCameraActor.SetPosition( position );
+        lookAtCameraActor.SetPosition( position );
+
+        application.SendNotification();
+        application.Render();
+        application.SendNotification();
+        application.Render();
+        Matrix freeLookViewMatrix;
+        Matrix lookAtViewMatrix;
+        freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix );
+        lookAtCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( lookAtViewMatrix );
+
+        Matrix freeLookWorld = freeLookCameraActor.GetCurrentWorldMatrix();
+
+        Matrix freeLookTest( false );
+        Matrix::Multiply( freeLookTest, freeLookViewMatrix, freeLookWorld );
+        DALI_TEST_EQUALS( freeLookTest, Matrix::IDENTITY, 0.01f, TEST_LOCATION );
+
+        DALI_TEST_EQUALS( freeLookViewMatrix, lookAtViewMatrix, 0.01, TEST_LOCATION );
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliCameraActorCheckLookAtAndFreeLookViews03(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  Vector3 targetPosition( Vector3::ZERO );
+  Vector3 cameraOffset( 0.0f, 0.0f, 100.0f );
+
+  CameraActor freeLookCameraActor = CameraActor::New( stageSize );
+  freeLookCameraActor.SetType( Camera::FREE_LOOK );
+  freeLookCameraActor.SetParentOrigin( ParentOrigin::CENTER );
+
+  Quaternion cameraOrientation( Radian( Degree( 180.0f ) ), Vector3::YAXIS );
+  freeLookCameraActor.SetPosition( cameraOffset );
+  freeLookCameraActor.SetOrientation( cameraOrientation );
+
+  Actor cameraAnchor = Actor::New();
+  cameraAnchor.Add( freeLookCameraActor );
+  stage.Add( cameraAnchor );
+
+  for( float angle = 1.0f; angle <= 180.0f; angle += 1.0f )
+  {
+    Quaternion rotation( Radian( Degree( angle ) ), Vector3::YAXIS );
+
+    freeLookCameraActor.SetPosition( rotation.Rotate( cameraOffset ) );
+    cameraAnchor.SetOrientation( rotation );
+
+    application.SendNotification();
+    application.Render();
+    application.SendNotification();
+    application.Render();
+
+    Matrix freeLookViewMatrix;
+    freeLookCameraActor.GetProperty( CameraActor::CameraActor::Property::VIEW_MATRIX ).Get( freeLookViewMatrix );
+
+    Matrix freeLookWorld = freeLookCameraActor.GetCurrentWorldMatrix();
+
+    Matrix freeLookTest( false );
+    Matrix::Multiply( freeLookTest,  freeLookViewMatrix,  freeLookWorld );
+    DALI_TEST_EQUALS( freeLookTest, Matrix::IDENTITY, 0.01f, TEST_LOCATION );
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp b/automated-tests/src/dali/utc-Dali-ConnectionTracker.cpp
new file mode 100644 (file)
index 0000000..a246746
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iostream>
+#include <stdlib.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <signal-helper.h>
+
+
+using namespace Dali;
+
+void utc_dali_conenction_tracker_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_conenction_tracker_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace {
+
+
+} // anon namespace
+
+
+/*******************************************
+ *
+ * Start of Utc test cases.
+ * Test cases performed in order of API listed in dali-signal.h
+ * UtcDaliSignal + FunctionName + P=positive test, N = Negative test
+ *
+ */
+
+int UtcConnectionTrackerConstructorP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  ConnectionTracker tracker;
+
+  DALI_TEST_CHECK( tracker.GetConnectionCount() == 0 );
+
+  END_TEST;
+}
+
+int UtcConnectionTrackerDestructorP(void)
+{
+  TestApplication app; // Create core for debug logging
+  // make sure the ConnectionTracker disconnects form a signal when it
+  // gets deleted.
+  TestButton* button = new TestButton(1);
+  {
+    TestApp testApp;
+    button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+    DALI_TEST_CHECK( testApp.GetConnectionCount() == 1 );
+    DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( )== 1 );
+  }
+  // testApp out of scope it should have been disconnected
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+
+  END_TEST;
+}
+
+int UtcConnectionTrackerDisconnectAllP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp testApp;
+  button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 );
+
+  testApp.DisconnectAll();
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+
+  END_TEST;
+}
+
+int UtcConnectionTrackerDisconnectAllN(void)
+{
+  TestApplication app; // Create core for debug logging
+  TestApp testApp;
+  TestButton* button = new TestButton(1);
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+  testApp.DisconnectAll();
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+
+  END_TEST;
+}
+
+int UtcConnectionTrackerSignalConnectedP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp testApp;
+  button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 );
+
+  END_TEST;
+
+}
+int UtcConnectionTrackerSignalConnectedN(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp* testApp( NULL );
+
+  try
+  {
+    // connect to a null connection tracker
+    button->DownSignal().Connect( testApp, &TestApp::OnButtonPress);
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_PASS);
+  }
+
+  END_TEST;
+}
+
+
+int UtcConnectionTrackerSignalDisconnectP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp testApp;
+  button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 );
+
+  button->DownSignal().Disconnect(&testApp,&TestApp::OnButtonPress);
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+
+  END_TEST;
+
+}
+
+
+int UtcConnectionTrackerSignalDisconnectN(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp testApp;
+  button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 );
+
+  try
+  {
+    app.SignalDisconnected( NULL, NULL );
+    tet_result( TET_FAIL );
+  }
+  catch (Dali::DaliException& e)
+  {
+    tet_result( TET_PASS );
+  }
+
+  END_TEST;
+
+}
+
+
+int UtcConnectionTrackerGetConnectionCountP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  TestApp testApp;
+  button->DownSignal().Connect(&testApp,&TestApp::OnButtonPress);
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 1 );
+  END_TEST;
+}
+
+int UtcConnectionTrackerGetConnectionCountN(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestButton* button = new TestButton(1);
+  DALI_TEST_CHECK( button->DownSignal().GetConnectionCount( ) == 0 );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Constrainer.cpp b/automated-tests/src/dali/utc-Dali-Constrainer.cpp
new file mode 100644 (file)
index 0000000..3398341
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/animation/path-constrainer.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Internal;
+
+namespace
+{
+static void SetupLinearConstrainerUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.Resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+}
+
+static void SetupLinearConstrainerNonUniformProgress( Dali::LinearConstrainer& linearConstrainer)
+{
+  Dali::Property::Array points;
+  points.Resize(3);
+  points[0] = 0.0f;
+  points[1] = 1.0f;
+  points[2] = 0.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::VALUE, points );
+
+  points[0] = 0.0f;
+  points[1] = 0.25f;
+  points[2] = 1.0f;
+  linearConstrainer.SetProperty( Dali::LinearConstrainer::Property::PROGRESS, points );
+}
+
+} // anonymous namespace
+
+int UtcLinearConstrainerApply(void)
+{
+  TestApplication application;
+
+  Dali::Actor actor = Dali::Actor::New();
+
+  // Register a float property
+  Property::Index index = actor.RegisterProperty( "t", 0.0f );
+
+  Dali::Stage::GetCurrent().Add(actor);
+
+
+  //Create a LinearConstrainer without specifying progress for values
+  Dali::LinearConstrainer linearConstrainer = Dali::LinearConstrainer::New();
+  SetupLinearConstrainerUniformProgress( linearConstrainer );
+
+  //Apply the linear constraint to the actor's position. The source property for the constraint will be the custom property "t"
+  Vector2 range( 0.0f, 1.0f );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  //Create an animation to animate the custom property
+  float durationSeconds(1.0f);
+  Dali::Animation animation = Dali::Animation::New(durationSeconds);
+  animation.AnimateTo(Dali::Property(actor,index),1.0f);
+  animation.Play();
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.5f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  //Setup a LinearConstrainer specifying the progress for each value
+  linearConstrainer.Remove(actor);
+  SetupLinearConstrainerNonUniformProgress( linearConstrainer );
+  linearConstrainer.Apply( Property(actor,Dali::Actor::Property::POSITION_X), Property(actor,index), range );
+
+  actor.SetProperty(index,0.0f);
+  animation.Play();
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 25% progress */);
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 50% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 2.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 75% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 1.0f/3.0f, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* 100% progress */);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  application.SendNotification();
+  application.Render(static_cast<unsigned int>(durationSeconds*250.0f)/* beyond the animation duration*/);
+  DALI_TEST_EQUALS( actor.GetCurrentPosition().x, 0.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-Constraint.cpp b/automated-tests/src/dali/utc-Dali-Constraint.cpp
new file mode 100644 (file)
index 0000000..84af54d
--- /dev/null
@@ -0,0 +1,1206 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+///////////////////////////////////////////////////////////////////////////////
+void utc_dali_constraint_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_constraint_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+/**
+ * A function to use for a constraint, no data collected.
+ */
+template< typename T >
+void BasicFunction( T& /* current */, const PropertyInputContainer& /* inputs */ )
+{
+}
+
+/**
+ * A functor which sets a given boolean when the functor is called.
+ */
+template< typename T >
+struct BasicCalledFunctor
+{
+  BasicCalledFunctor( bool& functorCalled ) : mCalled( functorCalled ) { }
+
+  void operator()( T& /* current */, const PropertyInputContainer& /* inputs */ )
+  {
+    mCalled = true;
+  }
+
+  bool& mCalled;
+};
+
+/**
+ * A functor which increments a given integer when the functor is called.
+ */
+template< typename T >
+struct CalledCountFunctor
+{
+  CalledCountFunctor( int& callCount ) : mCallCount( callCount ) { }
+
+  void operator()( T& /* current */, const PropertyInputContainer& /* inputs */ )
+  {
+    ++mCallCount;
+  }
+
+  int& mCallCount;
+};
+
+/**
+ * A functor which sets the given value as the value required when the functor is called.
+ */
+template< typename T >
+struct SetValueFunctor
+{
+  SetValueFunctor( const T& value ) : mValue( value ) { }
+
+  void operator()( T& current, const PropertyInputContainer& /* inputs */ )
+  {
+    current = mValue;
+  }
+
+  T mValue;
+};
+
+} // unnamed namespace
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::New(
+//   Handle,
+//   Property::Index,
+//   void( *function )( T&, const PropertyInputContainer& ) )
+///////////////////////////////////////////////////////////////////////////////
+namespace UtcDaliConstraintNewFunction
+{
+bool gConstraintFunctionCalled = false;
+void ConstraintFunction( Vector3& /* current */, const PropertyInputContainer& /* inputs */ )
+{
+  gConstraintFunctionCalled = true;
+}
+} // namespace UtcDaliConstraintNewFunction
+
+int UtcDaliConstraintNewFunctionP(void)
+{
+  // Ensure that we can create a constraint using a C function and that it is called.
+
+  TestApplication application;
+  UtcDaliConstraintNewFunction::gConstraintFunctionCalled = false;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( UtcDaliConstraintNewFunction::gConstraintFunctionCalled, false, TEST_LOCATION );
+
+  // Add a constraint
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintNewFunction::ConstraintFunction );
+  DALI_TEST_CHECK( constraint );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( UtcDaliConstraintNewFunction::gConstraintFunctionCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintNewFunctionN(void)
+{
+  // Create a constraint with an uninitialised handle
+
+  TestApplication application;
+
+  // Add a constraint with an uninitialised handle
+  try
+  {
+    Constraint constraint = Constraint::New< Vector3 >( Actor(), Actor::Property::POSITION, &UtcDaliConstraintNewFunction::ConstraintFunction );
+    DALI_TEST_CHECK( false ); // Should not reach here
+  }
+  catch ( ... )
+  {
+    DALI_TEST_CHECK( true ); // Should assert!
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::New(
+//   Handle,
+//   Property::Index,
+//   const T& object )
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintNewFunctorP(void)
+{
+  // Ensure that we can create a constraint using a functor and that it is called.
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Add a constraint
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+  DALI_TEST_CHECK( constraint );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintNewFunctorN(void)
+{
+  // Create a constraint with an uninitialised handle
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  // Add a constraint with an uninitialised handle
+  try
+  {
+    Constraint constraint = Constraint::New< Vector3 >( Actor(), Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+    DALI_TEST_CHECK( false ); // Should not reach here
+  }
+  catch ( ... )
+  {
+    DALI_TEST_CHECK( true ); // Should assert!
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::New(
+//   Handle,
+//   Property::Index,
+//   const T& object,
+//   void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) )
+///////////////////////////////////////////////////////////////////////////////
+namespace UtcDaliConstraintNewFunctorMember
+{
+struct Functor
+{
+  Functor( bool& positionCalled, bool& scaleCalled )
+  : mPositionCalled( positionCalled ),
+    mScaleCalled( scaleCalled )
+  {
+  }
+
+  void Position( Vector3& /* current */, const PropertyInputContainer& /* inputs */ )
+  {
+    mPositionCalled = true;
+  }
+
+  void Scale( Vector3& /* current */, const PropertyInputContainer& /* inputs */ )
+  {
+    mScaleCalled = true;
+  }
+
+  bool& mPositionCalled;
+  bool& mScaleCalled;
+};
+} // namespace UtcDaliConstraintNewFunctorMember
+
+int UtcDaliConstraintNewFunctorMemberP(void)
+{
+  // Ensure that we can create a constraint using a functor and that it is called.
+
+  TestApplication application;
+  bool positionFunctorCalled = false;
+  bool sizeFunctorCalled = false;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( positionFunctorCalled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( sizeFunctorCalled, false, TEST_LOCATION );
+
+  // Add a constraint that calls Functor::Position
+  Constraint constraint = Constraint::New< Vector3 >(
+      actor,
+      Actor::Property::POSITION,
+      UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ),
+      &UtcDaliConstraintNewFunctorMember::Functor::Position );
+  DALI_TEST_CHECK( constraint );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( positionFunctorCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( sizeFunctorCalled, false, TEST_LOCATION );
+
+  // Add another constraint that calls Functor::Size
+  Constraint constraint2 = Constraint::New< Vector3 >(
+      actor,
+      Actor::Property::SCALE,
+      UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ),
+      &UtcDaliConstraintNewFunctorMember::Functor::Scale );
+  DALI_TEST_CHECK( constraint2 );
+  constraint2.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( positionFunctorCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( sizeFunctorCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintNewFunctorMemberN(void)
+{
+  // Create a constraint with an uninitialised handle
+
+  TestApplication application;
+  bool positionFunctorCalled = false;
+  bool sizeFunctorCalled = false;
+
+  // Add a constraint with an uninitialised handle
+  try
+  {
+    Constraint constraint = Constraint::New< Vector3 >(
+        Actor(),
+        Actor::Property::POSITION,
+        UtcDaliConstraintNewFunctorMember::Functor( positionFunctorCalled, sizeFunctorCalled ),
+        &UtcDaliConstraintNewFunctorMember::Functor::Position );
+    DALI_TEST_CHECK( false ); // Should not reach here
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_CHECK( true ); // Should assert!
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Clone
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintCloneP(void)
+{
+  // Ensure we can clone for another actor and it's called appropriately
+
+  TestApplication application;
+  int calledCount = 0;
+
+  Actor actor = Actor::New();
+  Actor clone = Actor::New();
+
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+  stage.Add( clone );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( calledCount, 0, TEST_LOCATION );
+
+  // Add a constraint to actor
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, CalledCountFunctor< Vector3 >( calledCount ) );
+  DALI_TEST_CHECK( constraint );
+  constraint.Apply();
+
+  // Create a clone but don't apply
+  Constraint constraintClone = constraint.Clone( clone );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( calledCount, 1, TEST_LOCATION );
+
+  // Reset
+  calledCount = 0;
+
+  // Ensure constraint isn't called again if scene doesn't change
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( calledCount, 0, TEST_LOCATION );
+
+  // Apply the clone constraint
+  constraintClone.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Should only be called once for the new constraint clone ONLY
+  DALI_TEST_EQUALS( calledCount, 1, TEST_LOCATION );
+
+  // Reset
+  calledCount = 0;
+
+  // Change the position of both actors
+  actor.SetPosition( 100.0f, 100.0f );
+  clone.SetPosition( 100.0f, 100.0f );
+
+  application.SendNotification();
+  application.Render();
+
+  // Functor should have been called twice
+  DALI_TEST_EQUALS( calledCount, 2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintCloneN(void)
+{
+  // Attempt to clone an uninitialised constraint should cause an assert
+
+  TestApplication application;
+
+  Constraint constraint;
+
+  try
+  {
+    Actor actor = Actor::New();
+    Constraint clone = constraint.Clone( actor );
+    DALI_TEST_CHECK( false );
+  }
+  catch ( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+namespace UtcDaliConstraintClone
+{
+void Function( Vector3& /* current */, const PropertyInputContainer& inputs )
+{
+  DALI_TEST_EQUALS( inputs[0]->GetType(), Property::VECTOR3, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[1]->GetType(), Property::ROTATION, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[2]->GetType(), Property::VECTOR4, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[3]->GetType(), Property::BOOLEAN, TEST_LOCATION );
+}
+} // namespace UtcDaliConstraintClone
+
+int UtcDaliConstraintCloneCheckSourcesAndSetters(void)
+{
+  // Ensure all sources, the tag and remove-action are cloned appropriately
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Actor clone = Actor::New();
+
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+  stage.Add( clone );
+
+  application.SendNotification();
+  application.Render();
+
+  // Create a constraint, DON'T Apply it though
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintClone::Function );
+  constraint.AddSource( LocalSource( Actor::Property::SIZE ) );
+  constraint.AddSource( LocalSource( Actor::Property::ORIENTATION ) );
+  constraint.AddSource( LocalSource( Actor::Property::COLOR ) );
+  constraint.AddSource( LocalSource( Actor::Property::VISIBLE ) );
+  constraint.SetRemoveAction( Constraint::Discard );
+  constraint.SetTag( 123 );
+
+  // Clone the constraint & apply the clone
+  Constraint constraintClone = constraint.Clone( clone );
+  constraintClone.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( constraint.GetRemoveAction(), constraintClone.GetRemoveAction(), TEST_LOCATION );
+  DALI_TEST_EQUALS( constraint.GetTag(),          constraintClone.GetTag(),          TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Constraint( const Constraint& )
+// Constraint::operator=
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintCopyAndAssignment(void)
+{
+  // Ensure copy constructor & assignment operators work
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+  Constraint copied( constraint );
+  Constraint assigned;
+  DALI_TEST_CHECK( constraint == copied );
+  DALI_TEST_CHECK( copied != assigned );
+
+  assigned = constraint;
+  DALI_TEST_CHECK( constraint == assigned );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::DownCast
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintDownCast(void)
+{
+  // Ensure DownCast works as expected
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+
+  // Another BaseHandle type
+  Constraint downCast = Constraint::DownCast( actor );
+  DALI_TEST_CHECK( ! downCast );
+
+  // A constraint
+  downCast = Constraint::DownCast( constraint );
+  DALI_TEST_CHECK( downCast );
+
+  // An empty constraint
+  downCast = Constraint::DownCast( Constraint() );
+  DALI_TEST_CHECK( ! downCast );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::GetTargetObject
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintGetTargetObjectP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+  DALI_TEST_CHECK( constraint.GetTargetObject() == actor );
+
+  Actor actor2 = Actor::New();
+  DALI_TEST_CHECK( constraint.GetTargetObject() != actor2 );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintGetTargetObjectN(void)
+{
+  // Attempt to retrieve from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    Handle handle = constraint.GetTargetObject();
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::GetTargetProperty
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintGetTargetPropertyP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+  DALI_TEST_EQUALS( constraint.GetTargetProperty(), Actor::Property::POSITION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintGetTargetPropertyN(void)
+{
+  // Attempt to retrieve from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    Property::Index propertyIndex = constraint.GetTargetProperty();
+    ( void )propertyIndex;
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::SetTag
+// Constraint::GetTag
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintTagP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+  DALI_TEST_EQUALS( constraint.GetTag(), 0u, TEST_LOCATION );
+
+  const unsigned int tag = 123;
+  constraint.SetTag( tag );
+  DALI_TEST_EQUALS( constraint.GetTag(), tag, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintSetTagN(void)
+{
+  // Attempt to set from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    constraint.SetTag( 123 );
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliConstraintGetTagN(void)
+{
+  // Attempt to retrieve from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    int tag = constraint.GetTag();
+    ( void )tag;
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::SetRemoveAction
+// Constraint::GetRemoveAction
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintRemoveActionP(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &BasicFunction< Vector3 > );
+  DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::DEFAULT_REMOVE_ACTION, TEST_LOCATION );
+
+  constraint.SetRemoveAction( Constraint::Discard );
+  DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::Discard, TEST_LOCATION );
+
+  constraint.SetRemoveAction( Constraint::Bake );
+  DALI_TEST_EQUALS( constraint.GetRemoveAction(), Constraint::Bake, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintSetRemoveActionN(void)
+{
+  // Attempt to set from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    constraint.SetRemoveAction( Constraint::Discard );
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliConstraintGetRemoveActionN(void)
+{
+  // Attempt to retrieve from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    Constraint::RemoveAction removeAction = constraint.GetRemoveAction();
+    ( void )removeAction;
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliConstraintBakeRemoveAction(void)
+{
+  // Ensure value is baked when constraint is removed
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Should not equal position by default
+  Vector3 position( 10.0f, 20.0f, 30.0f );
+  DALI_TEST_CHECK( actor.GetCurrentPosition() != position );
+
+  // Create a constraint that constrains to position
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, SetValueFunctor< Vector3 >( position ) );
+  constraint.SetRemoveAction( Constraint::Bake );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  // Remove the constraint, it should still be at position
+  constraint.Remove();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintDiscardRemoveAction(void)
+{
+  // Ensure value is baked when constraint is removed
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Get and store current position
+  Vector3 originalPosition = actor.GetCurrentPosition();
+
+  // Should not equal position by default
+  Vector3 position( 10.0f, 20.0f, 30.0f );
+  DALI_TEST_CHECK( actor.GetCurrentPosition() != position );
+
+  // Create a constraint that constrains to position
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, SetValueFunctor< Vector3 >( position ) );
+  constraint.SetRemoveAction( Constraint::Discard );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), position, TEST_LOCATION );
+
+  // Remove the constraint, it should still be at position
+  constraint.Remove();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( actor.GetCurrentPosition(), originalPosition, TEST_LOCATION );
+  DALI_TEST_CHECK( actor.GetCurrentPosition() != position );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Apply
+// Constraint::Remove
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintApplyRemove(void)
+{
+  // Ensure constraint functors are called appropriately
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Create a constraint and apply, functor should be called
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  // Reset
+  functorCalled = false;
+
+  // Remove the constraint, functor should not be called
+  constraint.Remove();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Re-apply the constraint, functor should be called again
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintApplyBeforeAddedToStage(void)
+{
+  // Constraint gets applied to an off-stage actor.
+  // Constraint should be automatically applied when the actor is added to the stage and not before
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  // Create an actor and a constraint and apply, DON'T add to stage just yet
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Should NOT be called
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Add actor to stage
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Should now be called
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintApplyAndRemoveBeforeAddedToStage(void)
+{
+  // Constraint gets applied to an off-stage actor, then gets removed before it's added to the stage
+  // Constraint should NOT be called at all
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  // Create an actor and a constraint and apply, DON'T add to stage just yet
+  Actor actor = Actor::New();
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Should NOT be called
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Remove the constraint
+  constraint.Remove();
+
+  // Add actor to stage
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Still should NOT be called
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintApplyActorStagedUnstaged(void)
+{
+  // Apply a constraint to an actor which is staged and unstaged.
+  // Functor should only be called while the actor is staged.
+
+  TestApplication application;
+  bool functorCalled = false;
+
+  // Create an actor and add to stage
+  Actor actor = Actor::New();
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+
+  // Create a constraint and apply
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, BasicCalledFunctor< Vector3 >( functorCalled ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Constraint should be called
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  // Reset
+  functorCalled = false;
+
+  // Remove actor from stage
+  stage.Remove( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Constraint should NOT be called
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Re-add to stage
+  stage.Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  // Constraint should be called
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintApplySeveralTimes(void)
+{
+  // Apply the same constraint several times.
+  // Should not cause any problems (subsequent attempts should be no-ops)
+
+  TestApplication application;
+  int count = 0;
+
+  // Create an actor and add to stage
+  Actor actor = Actor::New();
+  Stage stage = Stage::GetCurrent();
+  stage.Add( actor );
+
+  // Create a constraint and apply
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, CalledCountFunctor< Vector3 >( count ) );
+  constraint.Apply();
+
+  // Apply again
+  constraint.Apply(); // no-op
+
+  application.SendNotification();
+  application.Render();
+
+  // Should only have been called once
+  DALI_TEST_EQUALS( count, 1, TEST_LOCATION );
+
+  // Reset
+  count = 0;
+
+  // Apply again
+  constraint.Apply(); // no-op
+
+  application.SendNotification();
+  application.Render();
+
+  // Constraint should not have been called as the input-properties (none) have not changed for the constraint
+  DALI_TEST_EQUALS( count, 0, TEST_LOCATION );
+
+  // Reset
+  count = 0;
+
+  // Change the position property, apply again
+  actor.SetPosition( 10.0f, 10.0f );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Constraint should have been called once
+  DALI_TEST_EQUALS( count, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::AddSource
+///////////////////////////////////////////////////////////////////////////////
+namespace UtcDaliConstraintAddSource
+{
+void Function( Vector3& /* current */, const PropertyInputContainer& inputs )
+{
+  DALI_TEST_EQUALS( inputs.Size(), 4u, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[0]->GetType(), Property::VECTOR3, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[1]->GetType(), Property::ROTATION, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[2]->GetType(), Property::VECTOR4, TEST_LOCATION );
+  DALI_TEST_EQUALS( inputs[3]->GetType(), Property::BOOLEAN, TEST_LOCATION );
+}
+} // namespace UtcDaliConstraintAddSource
+
+int UtcDaliConstraintAddSourceP(void)
+{
+  // Ensure all sources are in the correct order in the functor
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  // Create a constraint, add sources
+  Constraint constraint = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &UtcDaliConstraintAddSource::Function );
+  constraint.AddSource( LocalSource( Actor::Property::SIZE ) );
+  constraint.AddSource( LocalSource( Actor::Property::ORIENTATION ) );
+  constraint.AddSource( LocalSource( Actor::Property::COLOR ) );
+  constraint.AddSource( LocalSource( Actor::Property::VISIBLE ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+
+int UtcDaliConstraintAddSourceN(void)
+{
+  // Attempt to set from uninitialised constraint
+
+  TestApplication application;
+
+  Constraint constraint;
+  try
+  {
+    constraint.AddSource( LocalSource( Actor::Property::POSITION ) );
+    DALI_TEST_CHECK( false ); // Should not reach here!
+  }
+  catch( ... )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace TestChaining
+{
+
+const Vector3 gFunction1Output( Vector3::ONE );
+void Function1( Vector3& current, const PropertyInputContainer& /* inputs */ )
+{
+  // current is original position
+  DALI_TEST_EQUALS( current, Vector3::ZERO, TEST_LOCATION );
+  current = gFunction1Output;
+}
+
+const Vector3 gFunction2Output( 10.0f, 20.0f, 30.0f );
+void Function2( Vector3& current, const PropertyInputContainer& /* inputs */ )
+{
+  // current is output from Function1
+  DALI_TEST_EQUALS( current, gFunction1Output, TEST_LOCATION );
+
+  current = gFunction2Output;
+}
+
+const Vector3 gFunction3Output( 10.0f, 20.0f, 30.0f );
+void Function3( Vector3& current, const PropertyInputContainer& /* inputs */ )
+{
+  // current is output from Function2
+  DALI_TEST_EQUALS( current, gFunction2Output, TEST_LOCATION );
+
+  current = gFunction3Output;
+}
+
+const Vector3 gFunction4Output( 10.0f, 20.0f, 30.0f );
+void Function4( Vector3& current, const PropertyInputContainer& /* inputs */ )
+{
+  // current is output from Function3
+  DALI_TEST_EQUALS( current, gFunction3Output, TEST_LOCATION );
+
+  current = gFunction4Output;
+}
+
+void Function5( Vector3& current, const PropertyInputContainer& /* inputs */ )
+{
+  // current is output from Function4
+  DALI_TEST_EQUALS( current, gFunction4Output, TEST_LOCATION );
+
+  current = Vector3::ZERO;
+}
+
+} // namespace TestChaining
+
+int UtcDaliConstraintChaining(void)
+{
+  // Apply several constraints to the same property and ensure the functors are called in the correct order.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add( actor );
+
+  Constraint constraint1 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function1 );
+  Constraint constraint2 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function2 );
+  Constraint constraint3 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function3 );
+  Constraint constraint4 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function4 );
+  Constraint constraint5 = Constraint::New< Vector3 >( actor, Actor::Property::POSITION, &TestChaining::Function5 );
+
+  constraint1.Apply();
+  constraint2.Apply();
+  constraint3.Apply();
+  constraint4.Apply();
+  constraint5.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace TestPropertyTypes
+{
+template< typename T >
+void Execute( T value )
+{
+  TestApplication application;
+  bool functorCalled = false;
+
+  Actor actor = Actor::New();
+  Property::Index index = actor.RegisterProperty( "TEMP_PROPERTY_NAME", value );
+
+  Stage::GetCurrent().Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, false, TEST_LOCATION );
+
+  // Add a constraint
+  Constraint constraint = Constraint::New< T >( actor, index, BasicCalledFunctor< T >( functorCalled ) );
+  DALI_TEST_CHECK( constraint );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( functorCalled, true, TEST_LOCATION );
+}
+} // namespace UtcDaliConstraintNewFunctor
+
+int UtcDaliConstraintTestPropertyTypesP(void)
+{
+  // Ensure we can use a constraint functor with all supported property types
+
+  TestPropertyTypes::Execute< bool >( false );
+  TestPropertyTypes::Execute< int >( 0 );
+  TestPropertyTypes::Execute< float >( 0.0f );
+  TestPropertyTypes::Execute< Vector2 >( Vector2::ZERO );
+  TestPropertyTypes::Execute< Vector3 >( Vector3::ZERO );
+  TestPropertyTypes::Execute< Vector4 >( Vector4::ZERO );
+  TestPropertyTypes::Execute< Quaternion >( Quaternion::IDENTITY );
+  TestPropertyTypes::Execute< Matrix >( Matrix::IDENTITY );
+  TestPropertyTypes::Execute< Matrix3 >( Matrix3::IDENTITY );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
diff --git a/automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp b/automated-tests/src/dali/utc-Dali-ConstraintFunction.cpp
new file mode 100644 (file)
index 0000000..d7ad79b
--- /dev/null
@@ -0,0 +1,347 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+///////////////////////////////////////////////////////////////////////////////
+void utc_dali_constraint_function_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_constraint_function_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+bool gFunctionCalled = false;
+
+template< typename T >
+void TestCallbackFunction( T& /* current*/ , const PropertyInputContainer& /* inputs */ )
+{
+  gFunctionCalled = true;
+}
+
+template< typename T >
+struct TestCallbackFunctor
+{
+  TestCallbackFunctor( bool& functorCalled ) : mFunctorCalled( functorCalled ) { }
+
+  void operator()( T& /* current*/ , const PropertyInputContainer& /* inputs */ )
+  {
+    mFunctorCalled = true;
+  }
+
+  bool& mFunctorCalled;
+};
+
+template< typename T >
+struct TestFunctorMethod
+{
+  TestFunctorMethod( bool& functorCalled ) : mFunctorCalled( functorCalled ) { }
+
+  void Method( T& /* current*/ , const PropertyInputContainer& /* inputs */ )
+  {
+    mFunctorCalled = true;
+  }
+
+  bool& mFunctorCalled;
+};
+
+} // unnamed namespace
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Function::Function( void( *function )( P&, const PropertyInputContainer& ) )
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+template< typename T >
+void TestFunctionConstructor()
+{
+  gFunctionCalled = false;
+  Constraint::Function< T > function( &TestCallbackFunction< T > );
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( gFunctionCalled, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( function, current, inputs );
+  DALI_TEST_EQUALS( gFunctionCalled, true, TEST_LOCATION );
+}
+} // unnamed namespace
+
+int UtcDaliConstraintFunctionWithFunction(void)
+{
+  TestFunctionConstructor< bool >();
+  TestFunctionConstructor< int >();
+  TestFunctionConstructor< unsigned int >();
+  TestFunctionConstructor< float >();
+  TestFunctionConstructor< Vector2 >();
+  TestFunctionConstructor< Vector3 >();
+  TestFunctionConstructor< Vector4 >();
+  TestFunctionConstructor< Quaternion >();
+  TestFunctionConstructor< Matrix >();
+  TestFunctionConstructor< Matrix3 >();
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Function::Function( const T& object )
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+template< typename T >
+void TestFunctorConstructor()
+{
+  bool called = false;
+  TestCallbackFunctor< T > functor( called );
+  Constraint::Function< T > callback( functor );
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( called, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( callback, current, inputs );
+  DALI_TEST_EQUALS( called, true, TEST_LOCATION );
+}
+} // unnamed namespace
+
+int UtcDaliConstraintFunctionWithFunctor(void)
+{
+  TestFunctorConstructor< bool >();
+  TestFunctorConstructor< int >();
+  TestFunctorConstructor< unsigned int >();
+  TestFunctorConstructor< float >();
+  TestFunctorConstructor< Vector2 >();
+  TestFunctorConstructor< Vector3 >();
+  TestFunctorConstructor< Vector4 >();
+  TestFunctorConstructor< Quaternion >();
+  TestFunctorConstructor< Matrix >();
+  TestFunctorConstructor< Matrix3 >();
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Function::Function( const T& object, void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) )
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+template< typename T >
+void TestFunctorMethodConstructor()
+{
+  bool called = false;
+  TestFunctorMethod< T > functor( called );
+  Constraint::Function< T > callback( functor, &TestFunctorMethod< T >::Method );
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( called, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( callback, current, inputs );
+  DALI_TEST_EQUALS( called, true, TEST_LOCATION );
+}
+} // unnamed namespace
+
+int UtcDaliConstraintFunctionWithMethodFunctor(void)
+{
+  TestFunctorMethodConstructor< bool >();
+  TestFunctorMethodConstructor< int >();
+  TestFunctorMethodConstructor< unsigned int >();
+  TestFunctorMethodConstructor< float >();
+  TestFunctorMethodConstructor< Vector2 >();
+  TestFunctorMethodConstructor< Vector3 >();
+  TestFunctorMethodConstructor< Vector4 >();
+  TestFunctorMethodConstructor< Quaternion >();
+  TestFunctorMethodConstructor< Matrix >();
+  TestFunctorMethodConstructor< Matrix3 >();
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Constraint::Function::Clone
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+template< typename T >
+void TestFunctionClone()
+{
+  gFunctionCalled = false;
+  Constraint::Function< T > callback( &TestCallbackFunction< T > );
+  CallbackBase* clone = callback.Clone();
+
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( gFunctionCalled, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs );
+  DALI_TEST_EQUALS( gFunctionCalled, true, TEST_LOCATION );
+  delete clone;
+}
+
+template< typename T >
+void TestFunctorClone()
+{
+  bool called = false;
+  TestCallbackFunctor< T > functor( called );
+  Constraint::Function< T > callback( functor );
+  CallbackBase* clone = callback.Clone();
+
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( called, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs );
+  DALI_TEST_EQUALS( called, true, TEST_LOCATION );
+  delete clone;
+}
+
+template< typename T >
+void TestMethodFunctorClone()
+{
+  bool called = false;
+  TestFunctorMethod< T > functor( called );
+  Constraint::Function< T > callback( functor, &TestFunctorMethod< T >::Method );
+  CallbackBase* clone = callback.Clone();
+
+  T current;
+  PropertyInputContainer inputs;
+
+  DALI_TEST_EQUALS( called, false, TEST_LOCATION );
+  CallbackBase::Execute< T&, const PropertyInputContainer& >( *clone, current, inputs );
+  DALI_TEST_EQUALS( called, true, TEST_LOCATION );
+  delete clone;
+}
+
+} // unnamed namespace
+
+int UtcDaliConstraintFunctionFunctionClone(void)
+{
+  TestFunctionClone< bool >();
+  TestFunctionClone< int >();
+  TestFunctionClone< unsigned int >();
+  TestFunctionClone< float >();
+  TestFunctionClone< Vector2 >();
+  TestFunctionClone< Vector3 >();
+  TestFunctionClone< Vector4 >();
+  TestFunctionClone< Quaternion >();
+  TestFunctionClone< Matrix >();
+  TestFunctionClone< Matrix3 >();
+  END_TEST;
+}
+
+int UtcDaliConstraintFunctionFunctorClone(void)
+{
+  TestFunctorClone< bool >();
+  TestFunctorClone< int >();
+  TestFunctorClone< unsigned int >();
+  TestFunctorClone< float >();
+  TestFunctorClone< Vector2 >();
+  TestFunctorClone< Vector3 >();
+  TestFunctorClone< Vector4 >();
+  TestFunctorClone< Quaternion >();
+  TestFunctorClone< Matrix >();
+  TestFunctorClone< Matrix3 >();
+  END_TEST;
+}
+
+int UtcDaliConstraintFunctionMethodFunctorClone(void)
+{
+  TestMethodFunctorClone< bool >();
+  TestMethodFunctorClone< int >();
+  TestMethodFunctorClone< unsigned int >();
+  TestMethodFunctorClone< float >();
+  TestMethodFunctorClone< Vector2 >();
+  TestMethodFunctorClone< Vector3 >();
+  TestMethodFunctorClone< Vector4 >();
+  TestMethodFunctorClone< Quaternion >();
+  TestMethodFunctorClone< Matrix >();
+  TestMethodFunctorClone< Matrix3 >();
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+struct CountFunctor
+{
+  CountFunctor( int& count )
+  : mCount( count )
+  {
+    ++mCount;
+  }
+
+  CountFunctor( const CountFunctor& other )
+  : mCount( other.mCount )
+  {
+    ++mCount;
+  }
+
+  CountFunctor& operator=( const CountFunctor& other )
+  {
+    return *this;
+  }
+
+  ~CountFunctor()
+  {
+    --mCount;
+  }
+
+  void operator()( bool& /* current*/ , const PropertyInputContainer& /* inputs */ )
+  {
+  }
+
+  int& mCount;
+};
+} // unnamed namespace
+
+int UtcDaliConstraintFunctionEnsureMemoryCleanup(void)
+{
+  // Functors are new'd in Constraint::Function, so check that all memory is released at the end
+
+  int count = 0;
+
+  {
+    CountFunctor functor( count );
+    Constraint::Function< bool > callback1( functor );
+    Constraint::Function< bool > callback2( functor );
+    Constraint::Function< bool > callback3( functor );
+    Constraint::Function< bool > callback4( functor );
+    Constraint::Function< bool > callback5( functor );
+    Constraint::Function< bool > callback6( functor );
+    Constraint::Function< bool > callback7( functor );
+    Constraint::Function< bool > callback8( functor );
+    Constraint::Function< bool > callback9( functor );
+    DALI_TEST_EQUALS( count, 10, TEST_LOCATION );
+  }
+
+  DALI_TEST_EQUALS( count, 0, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
diff --git a/automated-tests/src/dali/utc-Dali-ConstraintSource.cpp b/automated-tests/src/dali/utc-Dali-ConstraintSource.cpp
new file mode 100644 (file)
index 0000000..7c69e21
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+///////////////////////////////////////////////////////////////////////////////
+void utc_dali_constraint_source_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_constraint_source_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// LocalSource
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliLocalSource(void)
+{
+  LocalSource source( Actor::Property::POSITION );
+
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::POSITION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// ParentSource
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliParentSource(void)
+{
+  ParentSource source( Actor::Property::POSITION );
+
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::POSITION, TEST_LOCATION );
+
+  END_TEST;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// Source
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliSource1(void)
+{
+  Actor actor;
+  Source source( actor, Actor::Property::SIZE );
+
+  DALI_TEST_CHECK( ! source.object );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::SIZE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSource2(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Source source( actor, Actor::Property::SIZE );
+  DALI_TEST_EQUALS( source.object, actor, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::SIZE, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// ConstraintSource
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintSourceWithSource1(void)
+{
+  Actor actor;
+
+  ConstraintSource source( Source( actor, Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( ! source.object );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.sourceType, OBJECT_PROPERTY, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintSourceWithSource2(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  ConstraintSource source( Source( actor, Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_EQUALS( source.object, actor, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.sourceType, OBJECT_PROPERTY, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintSourceWithLocalSource(void)
+{
+  Actor actor;
+
+  ConstraintSource source( LocalSource( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( ! source.object );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.sourceType, LOCAL_PROPERTY, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintSourceWithParentSource(void)
+{
+  Actor actor;
+
+  ConstraintSource source( ParentSource( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( ! source.object );
+  DALI_TEST_EQUALS( source.propertyIndex, Actor::Property::PARENT_ORIGIN, TEST_LOCATION );
+  DALI_TEST_EQUALS( source.sourceType, PARENT_PROPERTY, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
diff --git a/automated-tests/src/dali/utc-Dali-Constraints.cpp b/automated-tests/src/dali/utc-Dali-Constraints.cpp
new file mode 100644 (file)
index 0000000..06c8a2e
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+///////////////////////////////////////////////////////////////////////////////
+void utc_dali_constraints_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_constraints_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+struct PropertyInputImpl : public PropertyInput
+{
+public:
+
+  // Constants
+  static const bool BOOLEAN_VALUE;
+  static const float FLOAT_VALUE;
+  static const int INTEGER_VALUE;
+  static const Vector2 VECTOR2_VALUE;
+  static const Vector3 VECTOR3_VALUE;
+  static const Vector4 VECTOR4_VALUE;
+  static const Matrix3 MATRIX3_VALUE;
+  static const Matrix MATRIX_VALUE;
+  static const Quaternion QUATERNION_VALUE;
+
+  // Construction & Destruction
+  PropertyInputImpl( Property::Type type ) : mType( type ) { }
+  virtual ~PropertyInputImpl() { }
+
+  // Methods
+  Property::Type GetType() const { return mType; }
+
+  // Virtual Methods
+  virtual const bool& GetBoolean() const                 { return BOOLEAN_VALUE;          }
+  virtual const float& GetFloat() const                  { return FLOAT_VALUE;            }
+  virtual const int& GetInteger() const                  { return INTEGER_VALUE;          }
+  virtual const Vector2& GetVector2() const              { return VECTOR2_VALUE;          }
+  virtual const Vector3& GetVector3() const              { return VECTOR3_VALUE;          }
+  virtual const Vector4& GetVector4() const              { return VECTOR4_VALUE;          }
+  virtual const Matrix3& GetMatrix3() const              { return MATRIX3_VALUE;          }
+  virtual const Matrix& GetMatrix() const                { return MATRIX_VALUE;           }
+  virtual const Quaternion& GetQuaternion() const        { return QUATERNION_VALUE;       }
+
+  // Data
+  Property::Type mType;
+};
+
+const bool PropertyInputImpl::BOOLEAN_VALUE                  = true;
+const float PropertyInputImpl::FLOAT_VALUE                   = 123.0f;
+const int PropertyInputImpl::INTEGER_VALUE                   = 456;
+const Vector2 PropertyInputImpl::VECTOR2_VALUE               = Vector2( 10.0f, 20.0f );
+const Vector3 PropertyInputImpl::VECTOR3_VALUE               = Vector3( 30.0f, 40.0f, 50.0f );
+const Vector4 PropertyInputImpl::VECTOR4_VALUE               = Vector4( 60.0f, 70.0f, 80.0f, 90.0f );
+const Matrix3 PropertyInputImpl::MATRIX3_VALUE               ( 1.0f, 2.0f, 3.0f,
+                                                               4.0f, 5.0f, 6.0f,
+                                                               7.0f, 8.0f, 9.0f );
+const Matrix PropertyInputImpl::MATRIX_VALUE                 = Matrix::IDENTITY;
+const Quaternion PropertyInputImpl::QUATERNION_VALUE         ( 1.0f, 2.0f, 3.0f, 4.0f );
+
+struct Vector3PropertyInput : public PropertyInputImpl
+{
+public:
+
+  // Construction & Destruction
+  Vector3PropertyInput( Vector3& value )
+  : PropertyInputImpl( Property::VECTOR3 ),
+    mValue( value )
+  {
+  }
+
+  ~Vector3PropertyInput()
+  {
+  }
+
+  const Vector3& GetVector3() const
+  {
+    return mValue;
+  }
+
+  // Data
+  Vector3& mValue;
+};
+
+struct QuaternionPropertyInput : public PropertyInputImpl
+{
+public:
+
+  // Construction & Destruction
+  QuaternionPropertyInput( Quaternion& value )
+  : PropertyInputImpl( Property::ROTATION ),
+    mValue( value )
+  {
+  }
+
+  ~QuaternionPropertyInput()
+  {
+  }
+
+  const Quaternion& GetQuaternion() const
+  {
+    return mValue;
+  }
+
+  // Data
+  Quaternion& mValue;
+};
+
+} // unnamed namespace
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// EqualToConstraint
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintsEqualToConstraintFloat(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::FLOAT );
+  inputs.PushBack( &input );
+
+  float value = 0.0f;
+  DALI_TEST_CHECK( value != PropertyInputImpl::FLOAT_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::FLOAT_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintVector2(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR2 );
+  inputs.PushBack( &input );
+
+  Vector2 value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR2_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR2_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintVector3(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR3 );
+  inputs.PushBack( &input );
+
+  Vector3 value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR3_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintVector4(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR4 );
+  inputs.PushBack( &input );
+
+  Vector4 value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::VECTOR4_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR4_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintQuaternion(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::ROTATION );
+  inputs.PushBack( &input );
+
+  Quaternion value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::QUATERNION_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::QUATERNION_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintMatrix3(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::MATRIX3 );
+  inputs.PushBack( &input );
+
+  Matrix3 value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::MATRIX3_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::MATRIX3_VALUE, 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsEqualToConstraintMatrix(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::MATRIX );
+  inputs.PushBack( &input );
+
+  Matrix value;
+  DALI_TEST_CHECK( value != PropertyInputImpl::MATRIX_VALUE );
+
+  EqualToConstraint constraint;
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::MATRIX_VALUE, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// RelativeToConstraint
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintsRelativeToConstraintUsingFloat(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR3 );
+  inputs.PushBack( &input );
+
+  Vector3 value;
+  DALI_TEST_EQUALS( value, Vector3::ZERO, TEST_LOCATION );
+
+  const float scale( 4.0f );
+  RelativeToConstraint constraint( scale );
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE * scale, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliConstraintsRelativeToConstraintUsingVector3(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR3 );
+  inputs.PushBack( &input );
+
+  Vector3 value;
+  DALI_TEST_EQUALS( value, Vector3::ZERO, TEST_LOCATION );
+
+  const Vector3 scale( 4.0f, 5.0f, 6.0f );
+  RelativeToConstraint constraint( scale );
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::VECTOR3_VALUE * scale, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// RelativeToConstraintFloat
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintsRelativeToConstraintFloat(void)
+{
+  PropertyInputContainer inputs;
+  PropertyInputImpl input( Property::VECTOR3 );
+  inputs.PushBack( &input );
+
+  const float scale( 4.0f );
+
+  float value = 0.0f;
+  DALI_TEST_CHECK( value != PropertyInputImpl::FLOAT_VALUE * scale );
+
+  RelativeToConstraintFloat constraint( scale );
+  constraint( value, inputs );
+
+  DALI_TEST_EQUALS( value, PropertyInputImpl::FLOAT_VALUE * scale, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+///////////////////////////////////////////////////////////////////////////////
+// LookAt
+///////////////////////////////////////////////////////////////////////////////
+int UtcDaliConstraintsLookAt(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_EQUALS( actor.GetCurrentWorldOrientation(), Quaternion::IDENTITY, TEST_LOCATION );
+
+  Vector3 targetPosition;
+  Vector3 cameraPosition;
+  Quaternion targetOrientation;
+
+  Vector3PropertyInput targetPositionProperty( targetPosition );
+  Vector3PropertyInput cameraPositionProperty( cameraPosition );
+  QuaternionPropertyInput targetOrientationProperty( targetOrientation );
+
+  PropertyInputContainer inputs;
+  inputs.PushBack( &targetPositionProperty );
+  inputs.PushBack( &cameraPositionProperty );
+  inputs.PushBack( &targetOrientationProperty );
+
+  Quaternion current;
+
+  // 180 degrees round y
+  targetPosition = Vector3::ZERO;
+  cameraPosition = Vector3( 0.0f, 0.0f, 1.0f );
+  targetOrientation = Quaternion::IDENTITY;
+  Quaternion lookAtOrientation( Quaternion( Radian( Math::PI ), Vector3::YAXIS ) );
+  LookAt( current, inputs );
+  DALI_TEST_EQUALS( current, lookAtOrientation, TEST_LOCATION );
+
+  // 180 degrees round y * -45 degrees round x
+  targetPosition = Vector3::ZERO;
+  cameraPosition = Vector3( 0.0f, -1.0f, 1.0f );
+  targetOrientation = Quaternion::IDENTITY;
+  lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS );
+  LookAt( current, inputs );
+  DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION );
+
+  // 180 degrees round y * -45 degrees round x at different points
+  targetPosition = Vector3( 0.0f, 1.0f, -1.0f );
+  cameraPosition = Vector3::ZERO;
+  targetOrientation = Quaternion::IDENTITY;
+  lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS );
+  LookAt( current, inputs );
+  DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION );
+
+  // 225 degrees round y
+  targetPosition = Vector3( -1.0f, 0.0f, 0.0f );
+  cameraPosition = Vector3( 0.0f, 0.0f, 1.0f );
+  targetOrientation = Quaternion::IDENTITY;
+  lookAtOrientation = Quaternion( Radian( Math::PI * 1.25), Vector3::YAXIS );
+  LookAt( current, inputs );
+  DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION );
+
+  // 180 degrees round y * -45 degrees round x, Up Vector: 180 degrees
+  targetPosition = Vector3::ZERO;
+  cameraPosition = Vector3( 0.0f, -1.0f, 1.0f );
+  targetOrientation = Quaternion( Radian( Math::PI ), Vector3::ZAXIS );
+  lookAtOrientation = Quaternion( Radian( Math::PI ), Vector3::YAXIS ) * Quaternion( Radian( Math::PI * 0.25f ), -Vector3::XAXIS ) * Quaternion( Radian( Math::PI ), -Vector3::ZAXIS );
+  LookAt( current, inputs );
+  DALI_TEST_EQUALS( current, lookAtOrientation, Math::MACHINE_EPSILON_10, TEST_LOCATION );
+
+  END_TEST;
+}
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliPropertyInputGetExtension(void)
+{
+  PropertyInputImpl input( Property::BOOLEAN );
+  DALI_TEST_CHECK( input.GetExtension() == NULL );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-CustomActor.cpp b/automated-tests/src/dali/utc-Dali-CustomActor.cpp
new file mode 100644 (file)
index 0000000..aca2c62
--- /dev/null
@@ -0,0 +1,2011 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+#include <dali/integration-api/events/key-event-integ.h>
+
+#include "dali-test-suite-utils/dali-test-suite-utils.h"
+
+using namespace Dali;
+
+
+void custom_actor_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void custom_actor_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+std::vector< std::string > MasterCallStack;
+bool gOnRelayout = false;
+
+} // anon namespace
+
+// TypeRegistry needs custom actor Implementations to have the same name (namespaces are ignored so we use one here)
+namespace Impl
+{
+
+struct TestCustomActor : public CustomActorImpl
+{
+  /**
+   * Constructor
+   */
+  TestCustomActor()
+  : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS | REQUIRES_WHEEL_EVENTS | REQUIRES_HOVER_EVENTS | DISABLE_SIZE_NEGOTIATION ) ),
+    mDaliProperty( Property::INVALID_INDEX ),
+    mSizeSet( Vector3::ZERO ),
+    mTargetSize( Vector3::ZERO ),
+    mNego( false ),
+    mDepth(0u)
+  {
+  }
+
+  TestCustomActor(bool nego)
+  : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS | REQUIRES_WHEEL_EVENTS | REQUIRES_HOVER_EVENTS ) ),
+    mDaliProperty( Property::INVALID_INDEX ),
+    mSizeSet( Vector3::ZERO ),
+    mTargetSize( Vector3::ZERO ),
+    mNego( nego )
+  {
+  }
+  /**
+   * Destructor
+   */
+  virtual ~TestCustomActor()
+  {
+  }
+
+  void Initialize( const char* name = NULL )
+  {
+    mDaliProperty = Self().RegisterProperty( "Dali", std::string("no"), Property::READ_WRITE);
+
+    OnInitialize( name );
+  }
+
+  virtual void OnInitialize( const char* name ) {}
+
+  /**
+   * Resets the call stack
+   */
+  void ResetCallStack()
+  {
+    mSizeSet = Vector3();
+    mTargetSize = Vector3();
+    mMethodsCalled.clear();
+  }
+
+  void AddToCallStacks( const char* method )
+  {
+    mMethodsCalled.push_back( method );
+
+    // Combine Actor name with method string
+    std::string nameAndMethod( Self().GetName() );
+    if ( 0 == nameAndMethod.size() )
+    {
+      nameAndMethod = "Unknown: ";
+    }
+    else
+    {
+      nameAndMethod += ": ";
+    }
+    nameAndMethod += method;
+
+    MasterCallStack.push_back( nameAndMethod );
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+    AddToCallStacks("OnStageConnection");
+    mDepth = depth;
+  }
+  virtual void OnStageDisconnection()
+  {
+    AddToCallStacks("OnStageDisconnection");
+  }
+  virtual void OnChildAdd(Actor& child)
+  {
+    AddToCallStacks("OnChildAdd");
+  }
+  virtual void OnChildRemove(Actor& child)
+  {
+    AddToCallStacks("OnChildRemove");
+  }
+  virtual void OnPropertySet( Property::Index index, Property::Value propertyValue )
+  {
+    AddToCallStacks("OnPropertySet");
+  }
+  virtual void OnSizeSet(const Vector3& targetSize)
+  {
+    mSizeSet = targetSize;
+    AddToCallStacks("OnSizeSet");
+  }
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+  {
+    mTargetSize = targetSize;
+    AddToCallStacks("OnSizeAnimation");
+  }
+  virtual bool OnTouchEvent(const TouchEvent& event)
+  {
+    AddToCallStacks("OnTouchEvent");
+    return true;
+  }
+  virtual bool OnHoverEvent(const HoverEvent& event)
+  {
+    AddToCallStacks("OnHoverEvent");
+    return true;
+  }
+  virtual bool OnWheelEvent(const WheelEvent& event)
+  {
+    AddToCallStacks("OnWheelEvent");
+    return true;
+  }
+  virtual bool OnKeyEvent(const KeyEvent& event)
+  {
+    AddToCallStacks("OnKeyEvent");
+    return true;
+  }
+  virtual void OnKeyInputFocusGained()
+  {
+    AddToCallStacks("OnKeyInputFocusGained");
+  }
+  virtual void OnKeyInputFocusLost()
+  {
+    AddToCallStacks("OnKeyInputFocusLost");
+  }
+  virtual Vector3 GetNaturalSize()
+  {
+    return Vector3( 0.0f, 0.0f, 0.0f );
+  }
+
+  virtual float GetHeightForWidth( float width )
+  {
+    return 0.0f;
+  }
+
+  virtual float GetWidthForHeight( float height )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+    gOnRelayout = true;
+  }
+
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+  {
+  }
+
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+  }
+
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+  }
+
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS )
+  {
+    return false;
+  }
+
+  void SetDaliProperty(std::string s)
+  {
+    Self().SetProperty(mDaliProperty, s);
+  }
+  void TestRelayoutRequest()
+  {
+    RelayoutRequest();
+  }
+
+  float TestGetHeightForWidthBase( float width )
+  {
+    return GetHeightForWidthBase( width );
+  }
+
+  float TestGetWidthForHeightBase( float height )
+  {
+    return GetWidthForHeightBase( height );
+  }
+
+  float TestCalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return CalculateChildSizeBase( child, dimension );
+  }
+
+  bool TestRelayoutDependentOnChildrenBase( Dimension::Type dimension )
+  {
+    return RelayoutDependentOnChildrenBase( dimension );
+  }
+
+  Property::Index mDaliProperty;
+  std::vector< std::string > mMethodsCalled;
+  Vector3 mSizeSet;
+  Vector3 mTargetSize;
+  bool mNego;
+  unsigned int mDepth;
+};
+
+/**
+ * Variant which adds a new child during OnStageConnection
+ */
+struct TestCustomActorVariant1 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant1( Actor childToAdd )
+  : mChildToAdd( childToAdd )
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+    // Chain up first
+    TestCustomActor::OnStageConnection( depth );
+
+    // Add the child
+    Self().Add( mChildToAdd );
+  }
+
+  Actor mChildToAdd;
+};
+
+/**
+ * Variant which removes children during OnStageConnection
+ */
+struct TestCustomActorVariant2 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant2()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+    // Chain up first
+    TestCustomActor::OnStageConnection( depth );
+
+    // Remove all the children
+    for( unsigned int i=0, num=Self().GetChildCount(); i<num; ++i )
+    {
+      Self().Remove( Self().GetChildAt(0) );
+    }
+  }
+};
+
+/**
+ * Variant which adds a new child during OnStageDisconnection
+ */
+struct TestCustomActorVariant3 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant3( Actor childToAdd )
+  : mChildToAdd( childToAdd )
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageDisconnection()
+  {
+    // Chain up first
+    TestCustomActor::OnStageDisconnection();
+
+    // Add the child
+    Self().Add( mChildToAdd );
+  }
+
+  Actor mChildToAdd;
+};
+
+/**
+ * Variant which removes children during OnStageDisconnection
+ */
+struct TestCustomActorVariant4 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant4()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageDisconnection()
+  {
+    // Chain up first
+    TestCustomActor::OnStageDisconnection();
+
+    // Remove all the children
+    for( unsigned int i=0, num=Self().GetChildCount(); i<num; ++i )
+    {
+      Self().Remove( Self().GetChildAt(0) );
+    }
+  }
+};
+
+/**
+ * Variant which removes its parent from Stage during OnStageConnection
+ */
+struct TestCustomActorVariant5 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant5()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+    // Chain up first
+    TestCustomActor::OnStageConnection( depth );
+
+    // Take parent off-stage
+    Actor parent = Self().GetParent();
+    if ( parent )
+    {
+      Stage::GetCurrent().Remove( parent );
+    }
+  }
+};
+
+/**
+ * Variant which adds its parent to Stage during OnStageDisconnection
+ */
+struct TestCustomActorVariant6 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant6()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageDisconnection()
+  {
+    // Chain up first
+    TestCustomActor::OnStageDisconnection();
+
+    // Put parent on-stage
+    Actor parent = Self().GetParent();
+    if ( parent )
+    {
+      Stage::GetCurrent().Add( parent );
+    }
+  }
+};
+
+/**
+ * Variant which reparents its children into a separate container
+ */
+struct TestCustomActorVariant7 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant7()
+  {
+  }
+
+  virtual void OnInitialize( const char* name )
+  {
+    // We need to do this early, before the OnChildAdd is recorded
+    Self().SetName( name );
+
+    mContainer = Actor::New();
+    mContainer.SetName( "Container" );
+    Self().Add( mContainer );
+  }
+
+  // From CustomActorImpl
+  virtual void OnChildAdd(Actor& child)
+  {
+    // Chain up first
+    TestCustomActor::OnChildAdd(child);
+
+    // Reparent child
+    if ( child != mContainer )
+    {
+      mContainer.Add( child );
+    }
+  }
+
+  Actor mContainer;
+};
+
+/**
+ * Variant which attempts to interfere with the reparenting of a child to another container
+ */
+struct TestCustomActorVariant8 : public TestCustomActor
+{
+  /**
+   * Constructor
+   */
+  TestCustomActorVariant8( Actor rival )
+  : mRivalContainer( rival )
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnChildRemove(Actor& child)
+  {
+    // Chain up first
+    TestCustomActor::OnChildRemove(child);
+
+    mRivalContainer.Remove( child ); // attempt to block reparenting to rival (should be a NOOP)
+  }
+
+  Actor mRivalContainer;
+};
+
+// Need a class that doesn't override virtual methods
+class SimpleTestCustomActor : public CustomActorImpl
+{
+public:
+
+  /**
+   * Constructor
+   */
+  SimpleTestCustomActor()
+  : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS | DISABLE_SIZE_NEGOTIATION ) )
+  {
+  }
+
+  /**
+   * Destructor
+   */
+  virtual ~SimpleTestCustomActor()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+  }
+  virtual void OnStageDisconnection()
+  {
+  }
+  virtual void OnChildAdd(Actor& child)
+  {
+  }
+  virtual void OnChildRemove(Actor& child)
+  {
+  }
+  virtual void OnSizeSet(const Vector3& targetSize)
+  {
+  }
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+  {
+  }
+  virtual bool OnTouchEvent(const TouchEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnHoverEvent(const HoverEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnWheelEvent(const WheelEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnKeyEvent(const KeyEvent& event)
+  {
+    return true;
+  }
+  virtual void OnKeyInputFocusGained()
+  {
+  }
+  virtual void OnKeyInputFocusLost()
+  {
+  }
+
+  virtual Vector3 GetNaturalSize()
+  {
+    return Vector3( 0.0f, 0.0f, 0.0f );
+  }
+
+  virtual float GetHeightForWidth( float width )
+  {
+    return 0.0f;
+  }
+
+  virtual float GetWidthForHeight( float height )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+  }
+
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+  {
+  }
+
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+  }
+
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+  }
+
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS )
+  {
+    return false;
+  }
+};
+
+} ; // namespace Impl
+
+
+namespace
+{
+
+/**
+ * Test custom actor handle
+ */
+class TestCustomActor : public CustomActor
+{
+public:
+
+  static TestCustomActor New()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActor;
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewNegoSize()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActor( true );
+    TestCustomActor custom( *impl ); // takes ownership
+    custom.SetName( "SizeNegotiationActor" );
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant1( Actor childToAdd )
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant1( childToAdd );
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant2()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant2();
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant3( Actor childToAdd )
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant3( childToAdd );
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant4()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant4();
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant5()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant5();
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant6()
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant6();
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant7( const char* name )
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant7();
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize( name );
+
+    return custom;
+  }
+
+  static TestCustomActor NewVariant8( Actor rival )
+  {
+    Impl::TestCustomActor* impl = new Impl::TestCustomActorVariant8( rival );
+    TestCustomActor custom( *impl ); // takes ownership
+
+    impl->Initialize();
+
+    return custom;
+  }
+
+  virtual ~TestCustomActor()
+  {
+  }
+
+  Impl::TestCustomActor& GetImpl()
+  {
+    return static_cast<Impl::TestCustomActor&>(GetImplementation());
+  }
+
+  std::vector< std::string >& GetMethodsCalled()
+  {
+    return GetImpl().mMethodsCalled;
+  }
+
+  void ResetCallStack()
+  {
+    GetImpl().ResetCallStack();
+  }
+
+  void SetDaliProperty(std::string s)
+  {
+    GetImpl().SetDaliProperty(s);
+  }
+
+  Vector3 GetSize()
+  {
+    return GetImpl().mSizeSet;
+  }
+
+  Vector3 GetTargetSize()
+  {
+    return GetImpl().mTargetSize;
+  }
+
+  virtual Vector3 GetNaturalSize()
+  {
+    return Vector3( 0.0f, 0.0f, 0.0f );
+  }
+
+  virtual float GetHeightForWidth( float width )
+  {
+    return 0.0f;
+  }
+
+  virtual float GetWidthForHeight( float height )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+  }
+
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+  }
+
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+  }
+
+  void TestRelayoutRequest()
+  {
+    GetImpl().TestRelayoutRequest();
+  }
+
+  float TestGetHeightForWidthBase( float width )
+  {
+    return GetImpl().TestGetHeightForWidthBase( width );
+  }
+
+  float TestGetWidthForHeightBase( float height )
+  {
+    return GetImpl().TestGetWidthForHeightBase( height );
+  }
+
+  float TestCalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return GetImpl().TestCalculateChildSizeBase( child, dimension );
+  }
+
+  bool TestRelayoutDependentOnChildrenBase( Dimension::Type dimension )
+  {
+    return GetImpl().TestRelayoutDependentOnChildrenBase( dimension );
+  }
+
+  unsigned int GetDepth()
+  {
+    return GetImpl().mDepth;
+  }
+private:
+
+  TestCustomActor( Impl::TestCustomActor& impl ) : CustomActor( impl )
+  {
+  }
+};
+
+
+
+using namespace Dali;
+
+BaseHandle CreateActor()
+{
+  return TestCustomActor::New();
+}
+
+Dali::TypeRegistration mType( typeid(TestCustomActor), typeid(Dali::CustomActor), CreateActor );
+
+} // anon namespace
+
+
+int UtcDaliCustomActorDestructor(void)
+{
+  TestApplication application;
+
+  CustomActor* actor = new CustomActor();
+  delete actor;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplDestructor(void)
+{
+  TestApplication application;
+  CustomActorImpl* actor = new Impl::TestCustomActor();
+  delete actor;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliCustomActorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::DownCast()");
+
+  TestCustomActor custom = TestCustomActor::New();
+
+  Actor anActor = Actor::New();
+  anActor.Add( custom );
+
+  Actor child = anActor.GetChildAt(0);
+  CustomActor customActor = CustomActor::DownCast( child );
+  DALI_TEST_CHECK( customActor );
+
+  customActor = NULL;
+  DALI_TEST_CHECK( !customActor );
+
+  customActor = DownCast< CustomActor >( child );
+  DALI_TEST_CHECK( customActor );
+  END_TEST;
+}
+
+// Negative test case for a method
+int UtcDaliCustomActorDownCastNegative(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::DownCast()");
+
+  Actor actor1 = Actor::New();
+  Actor anActor = Actor::New();
+  anActor.Add(actor1);
+
+  Actor child = anActor.GetChildAt(0);
+  CustomActor customActor = CustomActor::DownCast( child );
+  DALI_TEST_CHECK( !customActor );
+
+  Actor unInitialzedActor;
+  customActor = CustomActor::DownCast( unInitialzedActor );
+  DALI_TEST_CHECK( !customActor );
+
+  customActor = DownCast< CustomActor >( unInitialzedActor );
+  DALI_TEST_CHECK( !customActor );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnStageConnectionDisconnection(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnStageConnection() & OnStageDisconnection");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  // add the custom actor to stage
+  Stage::GetCurrent().Add( custom );
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  Stage::GetCurrent().Remove( custom );
+
+  DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnStageConnectionOrder(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnStageConnection() order");
+
+  MasterCallStack.clear();
+
+  /* Build tree of actors:
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   *
+   * OnStageConnection should be received for A, B, D, E, C, and finally F
+   */
+
+  TestCustomActor actorA = TestCustomActor::New();
+  actorA.SetName( "ActorA" );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  TestCustomActor actorC = TestCustomActor::New();
+  actorC.SetName( "ActorC" );
+  actorA.Add( actorC );
+
+  TestCustomActor actorD = TestCustomActor::New();
+  actorD.SetName( "ActorD" );
+  actorB.Add( actorD );
+
+  TestCustomActor actorE = TestCustomActor::New();
+  actorE.SetName( "ActorE" );
+  actorB.Add( actorE );
+
+  TestCustomActor actorF = TestCustomActor::New();
+  actorF.SetName( "ActorF" );
+  actorC.Add( actorF );
+
+  // add the custom actor to stage
+  Stage::GetCurrent().Add( actorA );
+
+  DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 3, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 2 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 2, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorC.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorC.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorD.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorD.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorE.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorE.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorF.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorF.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  // Check sequence is correct in MasterCallStack
+
+  DALI_TEST_EQUALS( 3+3+2+1+1+1, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd", MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnChildAdd", MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnChildAdd", MasterCallStack[ 3 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorC: OnChildAdd", MasterCallStack[ 4 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 5 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 6 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorD: OnStageConnection", MasterCallStack[ 7 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorE: OnStageConnection", MasterCallStack[ 8 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorC: OnStageConnection", MasterCallStack[ 9 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorF: OnStageConnection", MasterCallStack[ 10 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnStageDisconnectionOrder(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnStageDisconnection() order");
+
+  Stage stage = Stage::GetCurrent();
+
+  /* Build tree of actors:
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   *
+   * OnStageDisconnection should be received for D, E, B, F, C, and finally A.
+   */
+
+  TestCustomActor actorA = TestCustomActor::New();
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  TestCustomActor actorC = TestCustomActor::New();
+  actorC.SetName( "ActorC" );
+  actorA.Add( actorC );
+
+  TestCustomActor actorD = TestCustomActor::New();
+  actorD.SetName( "ActorD" );
+  actorB.Add( actorD );
+
+  TestCustomActor actorE = TestCustomActor::New();
+  actorE.SetName( "ActorE" );
+  actorB.Add( actorE );
+
+  TestCustomActor actorF = TestCustomActor::New();
+  actorF.SetName( "ActorF" );
+  actorC.Add( actorF );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // Clear call stacks before disconnection
+  actorA.ResetCallStack();
+  actorB.ResetCallStack();
+  actorC.ResetCallStack();
+  actorD.ResetCallStack();
+  actorE.ResetCallStack();
+  actorF.ResetCallStack();
+  MasterCallStack.clear();
+
+  stage.Remove( actorA );
+
+  DALI_TEST_EQUALS( 1, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorC.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorD.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorD.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorE.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorE.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorF.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorF.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  // Check sequence is correct in MasterCallStack
+
+  DALI_TEST_EQUALS( 6, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorD: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorE: OnStageDisconnection", MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorF: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorC: OnStageDisconnection", MasterCallStack[ 4 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 5 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorAddDuringOnStageConnection(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor::Add behaviour during Dali::CustomActor::OnStageConnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The actorA is a special variant which adds a child to itself during OnStageConnection()
+   * The actorB is provided as the child
+   */
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+
+  TestCustomActor actorA = TestCustomActor::NewVariant1( actorB );
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION ); // Called from within OnStageConnection()
+
+  DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 3, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection", MasterCallStack[ 1 ], TEST_LOCATION ); // Occurs during Actor::Add from within from within OnStageConnection()
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",        MasterCallStack[ 2 ], TEST_LOCATION ); // Occurs after Actor::Add from within from within OnStageConnection()
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // Check everything is ok after Actors are removed
+
+  stage.Remove( actorA );
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorRemoveDuringOnStageConnection(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor::Remove behaviour during Dali::CustomActor::OnStageConnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The actorA is a special variant which removes its children during OnStageConnection()
+   * Actors B & C are provided as the children
+   */
+
+  TestCustomActor actorA = TestCustomActor::NewVariant2();
+  actorA.SetName( "ActorA" );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  TestCustomActor actorC = TestCustomActor::New();
+  actorC.SetName( "ActorC" );
+  actorA.Add( actorC );
+
+  stage.Add( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 5, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",        actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildRemove",     actorA.GetMethodsCalled()[ 3 ], TEST_LOCATION ); // Called from within OnStageConnection()
+  DALI_TEST_EQUALS( "OnChildRemove",     actorA.GetMethodsCalled()[ 4 ], TEST_LOCATION ); // Called from within OnStageConnection()
+
+  DALI_TEST_EQUALS( 5, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",        MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",        MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection", MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildRemove",     MasterCallStack[ 3 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildRemove",     MasterCallStack[ 4 ], TEST_LOCATION );
+
+  /* Actors B & C should be removed before the point where they could receive an OnStageConnection callback
+   * Therefore they shouldn't receive either OnStageConnection or OnStageDisconnection
+   */
+  DALI_TEST_EQUALS( 0, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0, (int)(actorC.GetMethodsCalled().size()), TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // Check everything is ok after last actor is removed
+
+  stage.Remove( actorA );
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorAddDuringOnStageDisconnection(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor::Add behaviour during Dali::CustomActor::OnStageDisonnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  /* The actorA is a special variant which adds a child to itself during OnStageDisconnection()
+   * The actorB is provided as the child
+   */
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+
+  TestCustomActor actorA = TestCustomActor::NewVariant3( actorB );
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // Clear call stacks before disconnection
+  actorA.ResetCallStack();
+  actorB.ResetCallStack();
+  MasterCallStack.clear();
+
+  stage.Remove( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  // Child was added after parent disconnection, so should not receive OnStageConnection()
+  DALI_TEST_EQUALS( 0, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 2, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 1 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorRemoveDuringOnStageDisconnection(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor::Remove behaviour during Dali::CustomActor::OnStageDisconnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  /* The actorA is a special variant which removes its children during OnStageDisconnection()
+   * The actorB is provided as the child
+   */
+
+  TestCustomActor actorA = TestCustomActor::NewVariant4();
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  // Clear call stacks before disconnection
+  actorA.ResetCallStack();
+  actorB.ResetCallStack();
+  MasterCallStack.clear();
+
+  stage.Remove( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildRemove",        actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 3, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildRemove",        MasterCallStack[ 2 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorRemoveParentDuringOnStageConnection(void)
+{
+  TestApplication application;
+  tet_infoline("Weird test where child removes its own parent from Stage during Dali::CustomActor::OnStageConnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The actorA is the parent of actorB
+   * The actorB is a special variant which removes its own parent during OnStageConnection()
+   * The child actor is interrupting the parent's connection to stage, therefore the parent should not get an OnStageDisconnection()
+   */
+
+  TestCustomActor actorA = TestCustomActor::New();
+  actorA.SetName( "ActorA" );
+
+  TestCustomActor actorB = TestCustomActor::NewVariant5();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  stage.Add( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 1, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection", actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 4, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection",    MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection",    MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorAddParentDuringOnStageDisconnection(void)
+{
+  TestApplication application;
+  tet_infoline("Weird test where child adds its own parent to Stage during Dali::CustomActor::OnStageDisconnection() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The actorA is the parent of actorB
+   * The actorB is a special variant which (weirdly) adds its own parent during OnStageDisconnection()
+   * The child actor is interrupting the disconnection, such that parent should not get a OnStageDisconnection()
+   */
+
+  TestCustomActor actorA = TestCustomActor::New();
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  TestCustomActor actorB = TestCustomActor::NewVariant6();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  stage.Remove( actorA );
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 2, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 2, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  // Disconnect was interrupted, so we should only get one OnStageConnection() for actorB
+
+  DALI_TEST_EQUALS( 4, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection",    MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection",    MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 3 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnChildAddRemove(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnChildAdd() & OnChildRemove()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  Actor aChild = Actor::New();
+  custom.Add( aChild );
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+
+  custom.Remove( aChild );
+
+  DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildRemove", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorReparentDuringOnChildAdd(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor:Add (reparenting) behaviour during Dali::CustomActor::OnChildAdd() callback");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The actorA is a special variant which reparents children added into a separate container child
+   * The actorB is the child of actorA
+   */
+
+  TestCustomActor actorA = TestCustomActor::NewVariant7( "ActorA" );
+  stage.Add( actorA );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  actorA.Add( actorB );
+
+  // Check hierarchy is as follows:
+  //  A
+  //  |
+  //  Container
+  //  |
+  //  B
+
+  DALI_TEST_EQUALS( 1, (int)(actorA.GetChildCount()), TEST_LOCATION );
+
+  Actor container = actorA.GetChildAt(0);
+  Actor containerChild;
+
+  DALI_TEST_CHECK( container );
+  if ( container )
+  {
+    DALI_TEST_EQUALS( "Container", container.GetName(), TEST_LOCATION );
+    DALI_TEST_EQUALS( 1, (int)(container.GetChildCount()), TEST_LOCATION );
+    containerChild = container.GetChildAt(0);
+  }
+
+  DALI_TEST_CHECK( containerChild );
+  if ( containerChild )
+  {
+    DALI_TEST_EQUALS( "ActorB", containerChild.GetName(), TEST_LOCATION );
+    DALI_TEST_EQUALS( 0, (int)(containerChild.GetChildCount()), TEST_LOCATION );
+  }
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 4, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); // The mContainer added to actorA
+  DALI_TEST_EQUALS( "OnStageConnection",    actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); // The actorB added to actorA
+  DALI_TEST_EQUALS( "OnChildRemove",        actorA.GetMethodsCalled()[ 3 ], TEST_LOCATION );
+  // mContainer will then receive OnChildAdd
+
+  DALI_TEST_EQUALS( 3, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageDisconnection", actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorB.GetMethodsCalled()[ 2 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 7, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection",    MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection",    MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 3 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageDisconnection", MasterCallStack[ 4 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildRemove",        MasterCallStack[ 5 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection",    MasterCallStack[ 6 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+/**
+ * Test that Remove can be called (a NOOP) during the OnChildRemove
+ * triggered when reparenting an actor
+ */
+int UtcDaliCustomActorRemoveDuringOnChildRemove(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Actor:Remove behaviour during OnChildRemove() callback triggered when reparenting");
+
+  Stage stage = Stage::GetCurrent();
+
+  MasterCallStack.clear();
+
+  /* The childActor will be reparented from actorA to actorB
+   * The actorA is a special variant which attempts to remove a child from actorB, during the OnChildRemove callback()
+   * This should be a NOOP since the reparenting has not occured yet
+   */
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorB.SetName( "ActorB" );
+  stage.Add( actorB );
+
+  TestCustomActor actorA = TestCustomActor::NewVariant8( actorB );
+  actorA.SetName( "ActorA" );
+  stage.Add( actorA );
+
+  Actor childActor = Actor::New();
+  childActor.SetName( "Child" );
+  // Reparent from actorA to actorB
+  actorA.Add( childActor );
+  actorB.Add( childActor );
+
+  // Check hierarchy is as follows:
+  //  A    B
+  //       |
+  //       Child
+
+  DALI_TEST_EQUALS( 0, (int)(actorA.GetChildCount()), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1, (int)(actorB.GetChildCount()), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0, (int)(childActor.GetChildCount()), TEST_LOCATION );
+
+  Actor child = actorB.GetChildAt(0);
+
+  DALI_TEST_CHECK( child );
+  if ( child )
+  {
+    DALI_TEST_EQUALS( "Child", child.GetName(), TEST_LOCATION );
+  }
+
+  // Check callback sequence
+
+  DALI_TEST_EQUALS( 3, (int)(actorA.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorA.GetMethodsCalled()[ 0 ], TEST_LOCATION ); // The mContainer added to actorA
+  DALI_TEST_EQUALS( "OnChildAdd",           actorA.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildRemove",        actorA.GetMethodsCalled()[ 2 ], TEST_LOCATION ); // The actorB added to actorA
+  // mContainer will then receive OnChildAdd
+
+  DALI_TEST_EQUALS( 2, (int)(actorB.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnStageConnection",    actorB.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnChildAdd",           actorB.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 5, (int)(MasterCallStack.size()), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( "ActorB: OnStageConnection",    MasterCallStack[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnStageConnection",    MasterCallStack[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildAdd",           MasterCallStack[ 2 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorA: OnChildRemove",        MasterCallStack[ 3 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( "ActorB: OnChildAdd",           MasterCallStack[ 4 ], TEST_LOCATION );
+
+  // Excercise the message passing to Update thread
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnPropertySet(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnPropertySet()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  custom.SetDaliProperty("yes");
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnPropertySet", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnSizeSet(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnSizeSet()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  custom.SetSize( Vector2( 9.0f, 10.0f ) );
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnSizeSet", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 9.0f, custom.GetSize().width, TEST_LOCATION );
+  DALI_TEST_EQUALS( 10.0f, custom.GetSize().height, TEST_LOCATION );
+
+  custom.SetSize( Vector3( 4.0f, 5.0f, 6.0f ) );
+  DALI_TEST_EQUALS( 2, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnSizeSet", custom.GetMethodsCalled()[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 4.0f, custom.GetSize().width, TEST_LOCATION );
+  DALI_TEST_EQUALS( 5.0f, custom.GetSize().height, TEST_LOCATION );
+  DALI_TEST_EQUALS( 6.0f, custom.GetSize().depth, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnSizeAnimation(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnSizeAnimation()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  Animation anim = Animation::New( 1.0f );
+  anim.AnimateTo( Property( custom, Actor::Property::SIZE ), Vector3( 8.0f, 9.0f, 10.0f ) );
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnSizeAnimation", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 8.0f, custom.GetTargetSize().width, TEST_LOCATION );
+  DALI_TEST_EQUALS( 9.0f, custom.GetTargetSize().height, TEST_LOCATION );
+  DALI_TEST_EQUALS( 10.0f, custom.GetTargetSize().depth, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnTouchEvent(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnTouchEvent()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  // set size for custom actor
+  custom.SetSize( 100, 100 );
+  // add the custom actor to stage
+  Stage::GetCurrent().Add( custom );
+  custom.ResetCallStack();
+
+  // Render and notify a couple of times
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // simulate a touch event
+  Dali::TouchPoint point( 0, TouchPoint::Down, 1, 1 );
+  Dali::Integration::TouchEvent event;
+  event.AddPoint( point );
+  application.ProcessEvent( event );
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnTouchEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnHoverEvent(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnHoverEvent()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  // set size for custom actor
+  custom.SetSize( 100, 100 );
+  // add the custom actor to stage
+  Stage::GetCurrent().Add( custom );
+  custom.ResetCallStack();
+
+  // Render and notify a couple of times
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // simulate a hover event
+  Dali::TouchPoint point( 0, TouchPoint::Motion, 1, 1 );
+  Dali::Integration::HoverEvent event;
+  event.AddPoint( point );
+  application.ProcessEvent( event );
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnHoverEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnWheelEvent(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnWheelEvent()");
+
+  TestCustomActor custom = TestCustomActor::New();
+  DALI_TEST_EQUALS( 0, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+
+  // set size for custom actor
+  custom.SetSize( 100, 100 );
+  // add the custom actor to stage
+  Stage::GetCurrent().Add( custom );
+  custom.ResetCallStack();
+
+  // Render and notify a couple of times
+  application.SendNotification();
+  application.Render();
+  application.SendNotification();
+  application.Render();
+
+  // simulate a wheel event
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Integration::WheelEvent event( Integration::WheelEvent::MOUSE_WHEEL, 0, 0u, screenCoordinates, 1, 1000u );
+  application.ProcessEvent( event );
+
+  DALI_TEST_EQUALS( 1, (int)(custom.GetMethodsCalled().size()), TEST_LOCATION );
+  DALI_TEST_EQUALS( "OnWheelEvent", custom.GetMethodsCalled()[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplOnPropertySet(void)
+{
+  TestApplication application;
+  CustomActorImpl* impl = new Impl::SimpleTestCustomActor();
+
+  impl->OnPropertySet( 0, 0 );
+
+  DALI_TEST_CHECK( true );
+
+  delete impl;
+  END_TEST;
+}
+
+int UtcDaliCustomActorGetImplementation(void)
+{
+  TestApplication application;
+
+  TestCustomActor custom = TestCustomActor::New();
+  CustomActorImpl& impl = custom.GetImplementation();
+  impl.GetOwner();  // Test
+
+  const TestCustomActor constCustom = TestCustomActor::New();
+  const CustomActorImpl& constImpl = constCustom.GetImplementation();
+  constImpl.GetOwner();  // Test
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+int UtcDaliCustomActorDoAction(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::DoAction()");
+
+  TestCustomActor custom = TestCustomActor::New();
+
+  BaseHandle customActorObject = custom;
+
+  DALI_TEST_CHECK(customActorObject);
+
+  Property::Map attributes;
+
+  // Check that an invalid command is not performed
+  DALI_TEST_CHECK(customActorObject.DoAction("invalidCommand", attributes) == false);
+
+  // Check that the custom actor is visible
+  custom.SetVisible(true);
+  DALI_TEST_CHECK(custom.IsVisible() == true);
+
+  // Check the custom actor performed an action to hide itself
+  DALI_TEST_CHECK(customActorObject.DoAction("hide", attributes) == true);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Check that the custom actor is now invisible
+  DALI_TEST_CHECK(custom.IsVisible() == false);
+
+  // Check the custom actor performed an action to show itself
+  DALI_TEST_CHECK(customActorObject.DoAction("show", attributes) == true);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // Check that the custom actor is now visible
+  DALI_TEST_CHECK(custom.IsVisible() == true);
+  END_TEST;
+}
+
+int UtcDaliCustomActorCustomActor(void)
+{
+  Dali::CustomActor customA;
+  Dali::CustomActor customB( customA );
+
+  DALI_TEST_CHECK( customA == customB );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplRelayoutRequest(void)
+{
+  TestApplication application;
+
+  DALI_TEST_CHECK( gOnRelayout == false );
+
+  TestCustomActor custom = TestCustomActor::NewNegoSize();
+  Stage::GetCurrent().Add(custom);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( gOnRelayout == true );
+  gOnRelayout = false;
+
+  custom.TestRelayoutRequest();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( gOnRelayout == true );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplGetHeightForWidthBase(void)
+{
+  TestApplication application;
+  TestCustomActor custom = TestCustomActor::NewNegoSize();
+
+  float width = 300.0f;
+  float v = 0.0f;
+
+  application.SendNotification();
+  application.Render();
+
+  v = custom.TestGetHeightForWidthBase( width );
+
+  DALI_TEST_CHECK( v == width );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplGetWidthForHeightBase(void)
+{
+  TestApplication application;
+  TestCustomActor custom = TestCustomActor::NewNegoSize();
+
+  float height = 300.0f;
+  float v = 0.0f;
+
+  application.SendNotification();
+  application.Render();
+
+  v = custom.TestGetWidthForHeightBase( height );
+
+  DALI_TEST_CHECK( v == height );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplCalculateChildSizeBase(void)
+{
+  TestApplication application;
+  TestCustomActor custom = TestCustomActor::NewNegoSize();
+
+  Actor child = Actor::New();
+  child.SetResizePolicy(Dali::ResizePolicy::FIXED, Dali::Dimension::ALL_DIMENSIONS);
+  child.SetSize(150, 150);
+
+  application.SendNotification();
+  application.Render();
+
+  float v = 9.99f;
+  v = custom.TestCalculateChildSizeBase( child, Dali::Dimension::ALL_DIMENSIONS );
+  DALI_TEST_CHECK( v == 0.0f );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorImplRelayoutDependentOnChildrenBase(void)
+{
+  TestApplication application;
+  TestCustomActor custom = TestCustomActor::NewNegoSize();
+  custom.SetResizePolicy(Dali::ResizePolicy::FIT_TO_CHILDREN, Dali::Dimension::ALL_DIMENSIONS);
+
+  bool v = false;
+
+  v = custom.TestRelayoutDependentOnChildrenBase( Dali::Dimension::ALL_DIMENSIONS );
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( v == true );
+
+  custom.SetResizePolicy(Dali::ResizePolicy::FIXED, Dali::Dimension::ALL_DIMENSIONS);
+  v = custom.TestRelayoutDependentOnChildrenBase( Dali::Dimension::WIDTH );
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( v == false );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorTypeRegistry(void)
+{
+  TestApplication application;
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "CustomActor" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+
+  std::string name;
+  std::string exception;
+
+  try
+  {
+    name = handle.GetTypeName();
+    tet_result(TET_FAIL);
+  }
+  catch( DaliException& e )
+  {
+    exception = e.condition;
+    DALI_TEST_EQUALS( exception, "handle && \"BaseObject handle is empty\"", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliCustomActorGetExtensionP(void)
+{
+  TestApplication application;
+
+  TestCustomActor custom = TestCustomActor::NewVariant5();
+
+  DALI_TEST_CHECK( NULL == custom.GetImplementation().GetExtension() );
+
+  END_TEST;
+}
+
+int UtcDaliCustomActorOnConnectionDepth(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::CustomActor::OnStageConnection() hierarchy depth");
+
+  Stage stage = Stage::GetCurrent();
+
+  /* Build tree of actors:
+   *
+   *                      Depth
+   *
+   *       A (parent)       1
+   *      / \
+   *     B   C              2
+   *    / \   \
+   *   D   E   F            3
+   *
+   * OnStageConnection should return 1 for A, 2 for B and C, and 3 for D, E and F.
+   */
+
+  TestCustomActor actorA = TestCustomActor::New();
+  stage.Add( actorA );
+
+  TestCustomActor actorB = TestCustomActor::New();
+  actorA.Add( actorB );
+
+  TestCustomActor actorC = TestCustomActor::New();
+  actorA.Add( actorC );
+
+  TestCustomActor actorD = TestCustomActor::New();
+  actorB.Add( actorD );
+
+  TestCustomActor actorE = TestCustomActor::New();
+  actorB.Add( actorE );
+
+  TestCustomActor actorF = TestCustomActor::New();
+  actorC.Add( actorF );
+
+  // Excercise the message passing to Update thread
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  DALI_TEST_EQUALS( 1u, actorA.GetDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, actorB.GetDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, actorC.GetDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, actorD.GetDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, actorE.GetDepth(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, actorF.GetDepth(), TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Degree.cpp b/automated-tests/src/dali/utc-Dali-Degree.cpp
new file mode 100644 (file)
index 0000000..5bf1f1e
--- /dev/null
@@ -0,0 +1,99 @@
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_degree_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_degree_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+// Positive test case for constructors
+int UtcDaliDegreeConstructors01(void)
+{
+  TestApplication application;
+
+  // Default constructor, does not initialise the value
+  Degree degree0( 0.0f );
+
+  // Test assignment operator
+  degree0 = Degree(180.0f);
+  DALI_TEST_EQUALS( degree0.degree, 180.0f, 0.001f, TEST_LOCATION );
+
+  // Constructor from float value
+  Degree degree1( 180.0f );
+  DALI_TEST_EQUALS( degree1.degree, 180.0f, 0.001f, TEST_LOCATION );
+
+  // Constructor from a Radian
+  Degree degree2( Radian( Math::PI ) );
+  DALI_TEST_EQUALS( degree2.degree, 180.0f, 0.001f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+// Positive test case for comparison
+int UtcDaliDegreeComparison01(void)
+{
+  TestApplication application;
+
+  // Comparison between degrees
+  Degree degree0( 90.0f );
+  Degree degree1( 90.0f );
+  Degree degree2( 180.0f );
+
+  DALI_TEST_CHECK( degree0 == degree1 );
+  DALI_TEST_CHECK( degree0 != degree2 );
+
+  // Comparison between radian to degree
+  Degree degree3( 180.0f );
+  Degree degree4( 90.0f );
+  Radian radian0( Math::PI );
+
+  DALI_TEST_CHECK( degree3 == Degree(radian0) );
+  DALI_TEST_CHECK( degree4 != Degree(radian0) );
+
+  // Comparison with float
+  Degree degree5( 90.0f );
+
+  DALI_TEST_CHECK( degree5.degree == 90.0f );
+  DALI_TEST_CHECK( degree5.degree != 180.0f );
+
+  END_TEST;
+}
+
+int UtcDaliDegreeOperatorEquals(void)
+{
+  TestApplication application;
+
+  Degree a(90.0f);
+  Degree b(90.0f);
+  Degree c(180.0f);
+
+  DALI_TEST_EQUALS(a == a, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(a == b, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(a == c, false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliDegreeOperatorNotEquals(void)
+{
+  TestApplication application;
+
+  Degree a(90.0f);
+  Degree b(90.0f);
+  Degree c(180.0f);
+
+  DALI_TEST_EQUALS(a != a, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(a != b, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(a != c, true, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp b/automated-tests/src/dali/utc-Dali-EncodedBufferImage.cpp
new file mode 100644 (file)
index 0000000..70e6c50
--- /dev/null
@@ -0,0 +1,882 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+
+namespace
+{
+/** PNG image file converted to an array using standard linux commandline tool:
+ *  xxd -i  fractal.001.32x32.png  | gvim -
+ *  This is 720 wide x 1280 high.
+ */
+const unsigned char sEncodedBufferImageDataPNG[] = {
+  0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
+  0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x02, 0xd0, 0x00, 0x00, 0x05, 0x00,
+  0x08, 0x02, 0x00, 0x00, 0x00, 0xe1, 0xac, 0xf2, 0x6a, 0x00, 0x00, 0x00,
+  0x01, 0x73, 0x52, 0x47, 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00,
+  0x20, 0x00, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0xd8, 0x5d, 0x8f,
+  0x5c, 0x87, 0x7d, 0xdf, 0xf1, 0x39, 0x7b, 0xce, 0xec, 0xcc, 0xce, 0x72,
+  0xc9, 0x5d, 0x92, 0x22, 0x45, 0x8a, 0x22, 0x45, 0x51, 0x22, 0x25, 0x45,
+  0x96, 0x6d, 0x45, 0xb6, 0x23, 0x25, 0xb5, 0x93, 0x18, 0x49, 0x6c, 0x35,
+  0x48, 0xe0, 0x38, 0x76, 0xdd, 0x34, 0x35, 0x82, 0x5e, 0x04, 0x01, 0xda,
+  0xdb, 0x02, 0xed, 0x55, 0x8b, 0x02, 0x05, 0x7a, 0xd1, 0x14, 0xc8, 0x65,
+  0x0b, 0x17, 0x45, 0x9a, 0x06, 0x70, 0x9b, 0xd6, 0x76, 0x6c, 0x07, 0xb6,
+  0x13, 0xa7, 0x89, 0x6d, 0xd5, 0x71, 0x2c, 0x89, 0xb6, 0xf5, 0x4c, 0x49,
+  0x94, 0xf8, 0x24, 0x3e, 0x53, 0xe4, 0xee, 0x92, 0x3b, 0x3b, 0x0f, 0xe7,
+  0x9c, 0xbe, 0x01, 0xf7, 0x22, 0xc0, 0xfc, 0xd0, 0x4e, 0xfa, 0xf9, 0xbc,
+  0x80, 0x1f, 0x0f, 0xfe, 0x9c, 0x87, 0xef, 0x4e, 0xf1, 0x9d, 0xf7, 0xfd,
+  0x4e, 0x27, 0x66, 0x38, 0x2d, 0x3b, 0x49, 0xc3, 0x49, 0x70, 0xff, 0xb5,
+  0xe9, 0xce, 0xdc, 0xf8, 0x1f, 0xef, 0x39, 0x14, 0xbd, 0xcc, 0x87, 0x2f,
+  0x5e, 0xc9, 0x8d, 0x1f, 0x5d, 0xbc, 0x93, 0x1b, 0xdf, 0xdf, 0x1d, 0xe5,
+  0xc6, 0x0f, 0xae, 0x6c, 0x45, 0xcf, 0x5e, 0x14, 0xc1, 0xf1, 0x41, 0x7f,
+  0x9a, 0x1b, 0xef, 0x96, 0x4d, 0xf4, 0x32, 0xbd, 0x5e, 0x9d, 0x1b, 0xaf,
+  0xaa, 0xe0, 0x78, 0xdb, 0x16, 0xd1, 0xcb, 0x74, 0xa3, 0x97, 0xe9, 0xce,
+  0xeb, 0x65, 0x16, 0xca, 0x36, 0xfc, 0x56, 0x0d, 0xee, 0xd7, 0xd3, 0x85,
+  0x39, 0x7d, 0xf2, 0x4e, 0xa7, 0xd3, 0xd4, 0xc1, 0x87, 0x5f, 0xe8, 0x00,
+  0x00, 0x84, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a,
+  0xb5, 0xb4, 0x38, 0xcd, 0xad, 0xb7, 0xe1, 0xa7, 0xdf, 0x9a, 0x54, 0xb9,
+  0xf1, 0x72, 0x1a, 0x7c, 0xfc, 0x37, 0x7e, 0xe6, 0x9e, 0xe8, 0x65, 0x8a,
+  0x1f, 0x05, 0x53, 0xf2, 0x03, 0xe7, 0x5e, 0x09, 0x3e, 0x79, 0x11, 0x3c,
+  0xfb, 0x30, 0xf9, 0x82, 0xe9, 0x74, 0x3a, 0xcb, 0xbd, 0x49, 0xf0, 0xd5,
+  0xbe, 0x1d, 0x7c, 0xf8, 0x5d, 0xcb, 0xe3, 0xe8, 0x65, 0xb6, 0xb7, 0xcb,
+  0xe4, 0x6b, 0x26, 0xf8, 0x6a, 0xef, 0x76, 0x9b, 0xe8, 0x65, 0x9a, 0xa6,
+  0x08, 0x8e, 0x4f, 0x83, 0x97, 0xa9, 0x16, 0xeb, 0xdc, 0x78, 0x9d, 0x3c,
+  0x4b, 0x5a, 0xf4, 0xff, 0xb4, 0x9e, 0x66, 0x7f, 0x26, 0x68, 0xea, 0xe0,
+  0xc3, 0xfb, 0x85, 0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x98, 0x95, 0xaa, 0x6d, 0x8b, 0xdc, 0x7a, 0xaf, 0x6a, 0xa2,
+  0x4f, 0x3f, 0x9c, 0x06, 0x83, 0xe9, 0xed, 0x87, 0x0f, 0xe5, 0xc6, 0xef,
+  0x3d, 0x79, 0x25, 0x7a, 0x99, 0xa7, 0xdf, 0x3c, 0x9f, 0x1b, 0x6f, 0x06,
+  0xc5, 0x9c, 0xbe, 0xdc, 0x9b, 0x36, 0xbb, 0x3f, 0xa9, 0x83, 0x2f, 0xc8,
+  0x6e, 0x19, 0x7c, 0x37, 0x4d, 0xa6, 0xd9, 0xbf, 0x3d, 0xba, 0x55, 0x9d,
+  0x9c, 0x0f, 0xbe, 0x20, 0xc7, 0xe3, 0x32, 0xfb, 0x9a, 0x6c, 0x82, 0x0f,
+  0xbf, 0xbd, 0x1d, 0x7c, 0xf8, 0xa2, 0x17, 0x3c, 0xcb, 0xea, 0x60, 0x34,
+  0xc7, 0x2f, 0xc8, 0xe4, 0x07, 0x64, 0xf4, 0x2b, 0xbb, 0xd3, 0xe9, 0x14,
+  0xc9, 0x79, 0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x00, 0xb3, 0x52, 0x15, 0x45, 0x70, 0xbd, 0x68, 0xdb, 0xe8,
+  0xd3, 0xdf, 0xea, 0xf5, 0x72, 0xe3, 0x4b, 0x2f, 0x5e, 0xc9, 0x8d, 0xdf,
+  0xfe, 0xc5, 0xf7, 0x64, 0xff, 0x63, 0xdf, 0x3a, 0x9b, 0xdb, 0x5e, 0x9f,
+  0x56, 0xb9, 0xf1, 0xbd, 0xdd, 0x26, 0x37, 0x3e, 0x6d, 0xb2, 0x85, 0x3d,
+  0x1c, 0x07, 0xdf, 0x4e, 0x75, 0x59, 0xe7, 0xc6, 0x9b, 0xb6, 0x88, 0x5e,
+  0x66, 0x39, 0xfa, 0x67, 0xd3, 0x42, 0xf0, 0x73, 0xa6, 0xae, 0xb3, 0x97,
+  0xd9, 0xdc, 0xee, 0xe6, 0xc6, 0xff, 0x60, 0xfb, 0x68, 0x6e, 0xfc, 0x93,
+  0xe3, 0xf3, 0xb9, 0xf1, 0x7e, 0x39, 0x8d, 0x9e, 0x7d, 0x34, 0x2a, 0x83,
+  0x5f, 0xab, 0x55, 0x33, 0xa7, 0xaf, 0xf6, 0x4e, 0xa7, 0x53, 0x55, 0xc1,
+  0x7d, 0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x00, 0xb3, 0x52, 0x45, 0xd7, 0xdb, 0x4e, 0x11, 0xdd, 0xbf, 0xb7,
+  0xdd, 0xca, 0x8d, 0xf7, 0x7a, 0xd3, 0xdc, 0xf8, 0x9f, 0x9e, 0xb9, 0x15,
+  0xbd, 0xcc, 0x46, 0x5d, 0xe6, 0xc6, 0x57, 0x16, 0x82, 0x2f, 0x9b, 0xcd,
+  0xba, 0xc9, 0x8d, 0xd7, 0xe1, 0x17, 0xe4, 0x9e, 0xde, 0x28, 0x37, 0x3e,
+  0x69, 0x82, 0x7f, 0x1e, 0x4c, 0x46, 0xd9, 0xbf, 0x3d, 0xd6, 0x87, 0x8b,
+  0xb9, 0xf1, 0x22, 0xf9, 0xbf, 0x5a, 0x15, 0x4d, 0xf4, 0x32, 0x6d, 0x72,
+  0xfc, 0x91, 0x8d, 0xe0, 0xe7, 0xcc, 0x1b, 0xfb, 0xd7, 0x72, 0xe3, 0x6b,
+  0xc3, 0x71, 0xf4, 0xec, 0x3b, 0x06, 0xc1, 0xfd, 0xba, 0x5e, 0x48, 0x8e,
+  0x47, 0x5f, 0x32, 0x9d, 0xf1, 0x38, 0xf8, 0x76, 0xf2, 0x0b, 0x07, 0x00,
+  0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0x55,
+  0xa7, 0xd3, 0xe6, 0xd6, 0x27, 0x75, 0x36, 0x68, 0xba, 0x0b, 0x4d, 0x6e,
+  0x7c, 0x47, 0x55, 0xe7, 0xc6, 0x3f, 0x7e, 0xee, 0x9d, 0xe8, 0x65, 0xbe,
+  0xfb, 0xf0, 0xa1, 0xdc, 0x78, 0x3d, 0x0d, 0x5e, 0xe6, 0xd7, 0xde, 0x3a,
+  0x9b, 0x3c, 0x4c, 0x1b, 0x3d, 0xfb, 0xb0, 0x2e, 0x73, 0xe3, 0x2b, 0xd5,
+  0x34, 0x37, 0x3e, 0x6d, 0x8a, 0xe8, 0x65, 0x5e, 0x9a, 0xee, 0xcc, 0x8d,
+  0xef, 0x5b, 0x18, 0xe7, 0xc6, 0xf7, 0x2e, 0x8c, 0xa2, 0x97, 0xb9, 0x5c,
+  0xf7, 0x73, 0xe3, 0x27, 0x97, 0x57, 0x73, 0xe3, 0xb7, 0x46, 0x8b, 0xc1,
+  0x57, 0x7b, 0x67, 0x3b, 0x7a, 0xf6, 0x47, 0xcb, 0x9b, 0xb9, 0xf1, 0xc5,
+  0x2a, 0xf8, 0xc5, 0xd4, 0x29, 0xb2, 0x6f, 0xd5, 0xf1, 0x34, 0xf8, 0xad,
+  0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x60, 0x56, 0xaa, 0xb6, 0x2d, 0x72, 0xeb, 0xa3, 0x69, 0x19, 0x7e,
+  0xfe, 0x36, 0x37, 0x5d, 0x26, 0xc7, 0xef, 0x6b, 0xef, 0x44, 0xef, 0xb2,
+  0xf4, 0xfa, 0xf9, 0xdc, 0xf8, 0x37, 0x0e, 0x1f, 0xca, 0x8d, 0x7f, 0xf1,
+  0xc0, 0xbd, 0xb9, 0xf1, 0x5b, 0x1f, 0xd8, 0x1f, 0x3d, 0xfb, 0x3f, 0xfa,
+  0xca, 0x73, 0xb9, 0xf1, 0xa6, 0x4d, 0x3e, 0x7a, 0x91, 0x7d, 0xa3, 0x16,
+  0x4d, 0x70, 0xfc, 0xf7, 0x1f, 0x3d, 0x9e, 0x1b, 0xff, 0xcc, 0x0b, 0x6f,
+  0x46, 0x2f, 0x73, 0xb2, 0x5d, 0xc9, 0x8d, 0x7f, 0xfd, 0x9f, 0x7d, 0x24,
+  0x37, 0xfe, 0x2f, 0xfe, 0xcd, 0x97, 0x72, 0xe3, 0x77, 0x2d, 0x6d, 0x47,
+  0xcf, 0x7e, 0x6b, 0x6b, 0x31, 0x37, 0x3e, 0x58, 0x9c, 0xce, 0xef, 0x7b,
+  0xb5, 0x28, 0x82, 0x1f, 0x34, 0x7e, 0xe1, 0x00, 0x00, 0xe2, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x66, 0xa5, 0xda, 0x1a, 0x57, 0xc1,
+  0x9c, 0x29, 0xda, 0xe8, 0xd3, 0xb7, 0x6d, 0x30, 0x98, 0xb6, 0x9b, 0x32,
+  0x37, 0xde, 0x2f, 0xea, 0xe8, 0x65, 0x16, 0x17, 0x9a, 0xdc, 0xf8, 0x63,
+  0x17, 0xae, 0xe5, 0xc6, 0xbf, 0xf6, 0xe4, 0xb1, 0xdc, 0xf8, 0x87, 0x5e,
+  0xbe, 0x11, 0x3d, 0xfb, 0x46, 0xd1, 0x0d, 0xbe, 0x57, 0x9b, 0xe0, 0xbb,
+  0x69, 0xda, 0x16, 0xd1, 0xcb, 0x4c, 0x3a, 0xc1, 0xfd, 0xeb, 0x47, 0xf7,
+  0xe7, 0xc6, 0x7f, 0xf8, 0xca, 0xf5, 0xe8, 0x65, 0x5e, 0xfe, 0xc8, 0x7d,
+  0xb9, 0xf1, 0xf7, 0xfc, 0xde, 0xf7, 0x72, 0xe3, 0xa7, 0x06, 0x6b, 0xb9,
+  0xf1, 0x87, 0xda, 0x8d, 0xe8, 0xd9, 0x9b, 0xe4, 0x0b, 0xfe, 0xf6, 0x68,
+  0x31, 0xf8, 0xd9, 0x5e, 0x65, 0xbf, 0x3b, 0xaa, 0x85, 0xe0, 0xe7, 0x8c,
+  0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x80, 0x59, 0xa9, 0xea, 0xa6, 0xc8, 0xad, 0xb7, 0xe1, 0xa7, 0xbf, 0x53,
+  0x57, 0xb9, 0xf1, 0x69, 0x1b, 0xbc, 0x4c, 0x11, 0xbe, 0x4c, 0x13, 0xfd,
+  0x17, 0x92, 0xdb, 0xbd, 0x83, 0xcb, 0xb9, 0xf1, 0xcd, 0x93, 0x97, 0xa2,
+  0x67, 0x3f, 0x53, 0x0d, 0x72, 0xe3, 0xdf, 0x1b, 0xec, 0xcd, 0x8d, 0x1f,
+  0xb9, 0x7d, 0x3b, 0x7a, 0x99, 0x36, 0xf9, 0xa2, 0x19, 0x9c, 0xbd, 0x99,
+  0x1b, 0xff, 0xe2, 0xa7, 0x1e, 0x8d, 0x5e, 0x66, 0x6d, 0x58, 0xe7, 0xc6,
+  0x3f, 0xb6, 0x71, 0x2b, 0x37, 0x7e, 0xb8, 0x1a, 0xe6, 0xc6, 0x37, 0xba,
+  0xdd, 0xe8, 0xd9, 0x77, 0x74, 0xa7, 0x73, 0xfa, 0x9d, 0x3d, 0x1e, 0x65,
+  0x2f, 0x33, 0x4e, 0x26, 0x81, 0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0xce, 0xdf, 0x19, 0xe4,
+  0xd6, 0x6f, 0x15, 0xdd, 0xe8, 0xd3, 0xef, 0xe8, 0x4c, 0xe7, 0xb4, 0xc5,
+  0x86, 0x4d, 0x36, 0xf5, 0x7e, 0xb4, 0x77, 0x6f, 0x6e, 0x7c, 0xf3, 0x76,
+  0x93, 0x1b, 0x1f, 0x7c, 0xfb, 0x42, 0x6e, 0xfc, 0xf9, 0x7f, 0xf9, 0x54,
+  0xf4, 0xec, 0x4b, 0x7f, 0xf8, 0x7a, 0xf0, 0x35, 0xf3, 0xeb, 0x47, 0x73,
+  0xe3, 0xed, 0xbf, 0x7d, 0x3e, 0x7a, 0x99, 0x3b, 0x55, 0x99, 0x1b, 0xbf,
+  0xb1, 0x63, 0x31, 0x37, 0xfe, 0xd4, 0xff, 0x38, 0x15, 0xbd, 0xcc, 0xe1,
+  0xd1, 0x30, 0x37, 0xde, 0x2f, 0x82, 0x6f, 0xd5, 0xb2, 0x68, 0x83, 0x1f,
+  0x32, 0x75, 0x15, 0x3d, 0x7b, 0x9b, 0x1c, 0x8f, 0x5e, 0xa6, 0x08, 0x37,
+  0xc1, 0xe6, 0x34, 0xf8, 0xad, 0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xff, 0x78, 0xff,
+  0xf1, 0xdc, 0xfa, 0xee, 0x8d, 0xed, 0xe8, 0xd3, 0x3f, 0x75, 0xf5, 0xca,
+  0x9c, 0xde, 0x7d, 0xa3, 0xed, 0x46, 0xf7, 0x9b, 0xdb, 0xd3, 0xdc, 0xf8,
+  0x5f, 0x7d, 0xfa, 0x27, 0x72, 0xe3, 0xe5, 0xe9, 0xf5, 0xdc, 0xf8, 0xd3,
+  0xbf, 0xf2, 0x70, 0xf4, 0xec, 0x5f, 0xea, 0x17, 0xc1, 0xff, 0xd3, 0x2f,
+  0x9c, 0xcd, 0x8d, 0x5f, 0x38, 0xba, 0x16, 0xbd, 0xcc, 0xad, 0xaa, 0xcc,
+  0x8d, 0xef, 0x39, 0xb3, 0x91, 0x1b, 0x5f, 0xee, 0x34, 0xd1, 0xcb, 0x2c,
+  0x15, 0x75, 0x6e, 0xbc, 0x6d, 0x93, 0x1f, 0x32, 0xc9, 0xf1, 0x4e, 0x11,
+  0xbd, 0x7a, 0x67, 0x73, 0x1a, 0xfc, 0x04, 0x8e, 0x1e, 0x66, 0xd4, 0x94,
+  0xd1, 0xcb, 0x7c, 0x6b, 0xed, 0xee, 0xdc, 0xb8, 0x5f, 0x38, 0x00, 0x80,
+  0x38, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0xce,
+  0xff, 0xca, 0xc3, 0xb9, 0xf5, 0xf6, 0x6b, 0x6f, 0x45, 0x9f, 0xfe, 0x95,
+  0x77, 0x87, 0xb9, 0xf1, 0x03, 0xd3, 0xed, 0xdc, 0xf8, 0xb0, 0x28, 0xa3,
+  0x97, 0xb9, 0x74, 0x60, 0x67, 0xf0, 0x45, 0xb3, 0xb6, 0x98, 0x1b, 0x5f,
+  0xfe, 0x07, 0x27, 0x72, 0xe3, 0x07, 0x07, 0x4b, 0xd1, 0xb3, 0x7f, 0xe6,
+  0x63, 0x8f, 0xe4, 0xc6, 0xbf, 0xd4, 0xab, 0x72, 0xe3, 0x6f, 0x9d, 0xdb,
+  0x8c, 0x5e, 0xe6, 0xf0, 0x72, 0xf0, 0xf2, 0xe7, 0x9e, 0xbd, 0x94, 0x1b,
+  0x3f, 0xfe, 0xf5, 0xf5, 0xe8, 0x65, 0xc6, 0x45, 0xf0, 0xaf, 0xbe, 0xcd,
+  0x36, 0xf8, 0x9a, 0xd9, 0xd1, 0x04, 0xc7, 0xab, 0xa2, 0x9d, 0xdf, 0xaf,
+  0xd5, 0xad, 0x26, 0xf8, 0xf1, 0xfe, 0x4a, 0x77, 0x25, 0xfa, 0xf0, 0xaf,
+  0x1d, 0xd9, 0x97, 0x1b, 0xf7, 0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0xd5, 0x3f, 0xfc, 0xdd, 0x6f,
+  0xe6, 0xd6, 0x5f, 0xea, 0xad, 0x44, 0x9f, 0xfe, 0x4f, 0x7f, 0xe3, 0xfd,
+  0xb9, 0xf1, 0x8f, 0xff, 0xe7, 0x93, 0xb9, 0xf1, 0x51, 0x95, 0x4d, 0xbd,
+  0x95, 0x4b, 0xb7, 0x73, 0xe3, 0x4b, 0xcf, 0x5f, 0xcf, 0x8d, 0x5f, 0xde,
+  0xdb, 0x9b, 0xdf, 0xbe, 0x3e, 0xd0, 0x5b, 0xca, 0x8d, 0x7f, 0xf2, 0x17,
+  0x4f, 0xe4, 0xc6, 0xbf, 0xf1, 0xdc, 0xd9, 0xe8, 0x65, 0xce, 0x9d, 0xbe,
+  0x99, 0x1b, 0xdf, 0xfd, 0xc6, 0x46, 0x6e, 0xfc, 0xc2, 0xca, 0x20, 0x7a,
+  0x99, 0x1f, 0x1c, 0xda, 0x9f, 0x1b, 0xff, 0xd0, 0x0b, 0x97, 0x72, 0xe3,
+  0xef, 0xf4, 0x83, 0x97, 0x79, 0x64, 0xb8, 0x1e, 0x3d, 0x7b, 0x99, 0x1c,
+  0xaf, 0xdb, 0xe0, 0xf8, 0x1b, 0x07, 0xf6, 0x44, 0x2f, 0xf3, 0xc1, 0x1f,
+  0x9c, 0x99, 0xdf, 0x4f, 0x60, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x80, 0x99, 0xa9, 0xf6, 0xb5, 0xa3, 0xdc, 0x7a, 0xd1, 0x5b,
+  0x8d, 0x3e, 0xfd, 0xc6, 0xfa, 0x76, 0x6e, 0xfc, 0xd5, 0x3d, 0xbb, 0x72,
+  0xe3, 0xbd, 0xed, 0x69, 0xf4, 0x32, 0xa7, 0x3f, 0x79, 0x22, 0x37, 0xbe,
+  0x79, 0x6e, 0x23, 0x37, 0xfe, 0xd8, 0xcf, 0x1e, 0xce, 0x8d, 0x2f, 0x86,
+  0x0b, 0xbb, 0xe9, 0xb4, 0xb9, 0xf1, 0x7d, 0x65, 0x3f, 0x37, 0xfe, 0x5b,
+  0x1f, 0x7a, 0x28, 0x7a, 0x99, 0xff, 0x30, 0x7e, 0x39, 0x37, 0xde, 0xfd,
+  0xad, 0xe0, 0xc3, 0xbf, 0xf5, 0x85, 0xd3, 0xd1, 0xcb, 0xf4, 0x3e, 0x76,
+  0x24, 0x37, 0xfe, 0xcd, 0xbf, 0x73, 0x28, 0x37, 0x7e, 0xe2, 0xf3, 0xaf,
+  0x04, 0x5f, 0xed, 0xc3, 0xed, 0xe8, 0xd9, 0xfb, 0x9d, 0x26, 0x37, 0x7e,
+  0x6d, 0x65, 0x29, 0x37, 0x7e, 0x76, 0xcf, 0x8e, 0xe8, 0x65, 0x9e, 0x78,
+  0xfb, 0x4a, 0x6e, 0xdc, 0x2f, 0x1c, 0x00, 0x40, 0x9c, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0xc0, 0xac, 0x54, 0xff, 0xeb, 0xd8, 0xa1, 0xdc,
+  0xfa, 0x33, 0x4f, 0xdc, 0x17, 0x7d, 0xfa, 0xf7, 0x3e, 0x73, 0x31, 0x37,
+  0xfe, 0xec, 0x2f, 0xdf, 0x9f, 0x1b, 0xdf, 0xb9, 0x3e, 0x89, 0x5e, 0x66,
+  0x74, 0xf7, 0x52, 0x6e, 0xbc, 0xfb, 0xe8, 0x6a, 0x6e, 0xfc, 0x89, 0xfd,
+  0xbb, 0x73, 0xe3, 0x6d, 0xf8, 0xed, 0x54, 0x14, 0xc5, 0x9c, 0x7e, 0x10,
+  0xd4, 0xe1, 0xdb, 0x7c, 0xe2, 0xa7, 0x1f, 0xc8, 0x8d, 0xff, 0xfb, 0x2f,
+  0xbf, 0x10, 0xbc, 0xcc, 0x53, 0xfb, 0xa2, 0x97, 0x59, 0x1b, 0x4f, 0x73,
+  0xe3, 0xfd, 0xef, 0x04, 0x3f, 0x21, 0x77, 0x0e, 0x83, 0x1f, 0x62, 0x57,
+  0xba, 0xfd, 0xec, 0x9f, 0xda, 0x75, 0x93, 0x1b, 0xff, 0xce, 0xe3, 0x47,
+  0x72, 0xe3, 0x07, 0x27, 0x4d, 0xf4, 0x32, 0xbd, 0xb2, 0x0e, 0x9e, 0x5d,
+  0x73, 0x01, 0x00, 0x69, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0xb3, 0x52, 0x8d, 0xde, 0x9d, 0xe6, 0xd6, 0x3f, 0xfb, 0xdf, 0x4e, 0x46,
+  0x9f, 0x7e, 0xbd, 0xec, 0xe6, 0xc6, 0x57, 0x3e, 0xbf, 0x95, 0x1b, 0xbf,
+  0xb8, 0x3a, 0x88, 0x5e, 0xe6, 0xe2, 0x3b, 0xb7, 0x83, 0x67, 0xff, 0xf9,
+  0x83, 0xc1, 0xb3, 0x57, 0x5d, 0x6f, 0xcb, 0xbf, 0x7d, 0x56, 0x17, 0x82,
+  0xff, 0xad, 0x7f, 0xff, 0xef, 0x3e, 0x92, 0x1b, 0x3f, 0x75, 0xe5, 0x56,
+  0xf4, 0x32, 0x2f, 0xfc, 0xde, 0x8f, 0x72, 0xe3, 0xdd, 0xed, 0xe0, 0xc7,
+  0xfb, 0xd5, 0x41, 0x3f, 0x37, 0xfe, 0xd6, 0xa3, 0xfb, 0xa3, 0x67, 0xbf,
+  0xfc, 0xd0, 0x6a, 0x6e, 0xfc, 0xc4, 0x76, 0xf0, 0xc9, 0x9f, 0xfc, 0xfc,
+  0xf7, 0xa3, 0x97, 0xb9, 0xbb, 0x1c, 0xe5, 0xc6, 0xfd, 0xc2, 0x01, 0x00,
+  0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a, 0xf5,
+  0xb1, 0x8d, 0x8b, 0xb9, 0xf5, 0xf5, 0xa2, 0x9b, 0xcd, 0xa5, 0x3a, 0x38,
+  0x7e, 0xbb, 0xa8, 0x72, 0xe3, 0xd7, 0x9a, 0x36, 0x7b, 0x99, 0xbd, 0x4b,
+  0xb9, 0xf1, 0xfb, 0x7e, 0xe9, 0xde, 0xdc, 0xf8, 0xb0, 0x0d, 0xfe, 0xa7,
+  0xf6, 0x8b, 0xd2, 0x7b, 0xfe, 0xff, 0xd2, 0x5f, 0x36, 0x45, 0x6e, 0xfc,
+  0x68, 0x77, 0x90, 0x1b, 0x6f, 0xd6, 0xea, 0xe8, 0x65, 0x4e, 0xfd, 0xdc,
+  0xdd, 0xb9, 0xf1, 0x9d, 0x9f, 0x3a, 0x96, 0x1b, 0x3f, 0xfd, 0xaf, 0x9f,
+  0xcf, 0x8d, 0x2f, 0xed, 0x5c, 0x8c, 0x9e, 0xfd, 0x27, 0xff, 0xeb, 0xeb,
+  0xc1, 0xcb, 0xfc, 0xc2, 0x7d, 0xb9, 0xf1, 0x1f, 0x1e, 0xb8, 0x2b, 0x7a,
+  0x99, 0x7b, 0xde, 0x1d, 0x27, 0x3f, 0x07, 0x00, 0x00, 0xe2, 0x7f, 0x78,
+  0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10,
+  0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0xd9, 0xa8, 0x96, 0xcb, 0x3a,
+  0xb7, 0xbe, 0xd8, 0x36, 0xd1, 0xa7, 0xbf, 0x5e, 0xf7, 0x72, 0xe3, 0xdf,
+  0xf8, 0xb9, 0x63, 0xb9, 0xf1, 0x41, 0xaf, 0x8c, 0x5e, 0x66, 0xb4, 0x39,
+  0xc9, 0x8d, 0x9f, 0xfd, 0xf6, 0xc5, 0xdc, 0xf8, 0xf0, 0x37, 0xf6, 0xe5,
+  0xc6, 0xd7, 0x04, 0xf6, 0xdf, 0x46, 0x6d, 0x72, 0xfc, 0xd8, 0xf2, 0x4a,
+  0xf4, 0xe1, 0x7f, 0xfb, 0xe9, 0xf7, 0xe6, 0xc6, 0xff, 0xf8, 0xaf, 0xde,
+  0xcc, 0x8d, 0x17, 0x9f, 0x38, 0x9a, 0x1b, 0xdf, 0xf5, 0x27, 0x6f, 0x47,
+  0xcf, 0x7e, 0xcf, 0x78, 0x3b, 0x37, 0xfe, 0xe8, 0x57, 0x5e, 0xc8, 0x8d,
+  0xaf, 0xd6, 0x93, 0xe8, 0x65, 0xca, 0x41, 0xf0, 0x5b, 0xdb, 0x07, 0x30,
+  0x00, 0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b,
+  0x55, 0x51, 0xb4, 0xb9, 0xf5, 0xb6, 0x2d, 0xc2, 0x4f, 0xdf, 0xe4, 0xc6,
+  0x7f, 0xea, 0x99, 0x73, 0xb9, 0xf1, 0x67, 0xfe, 0xc9, 0xe3, 0xd1, 0xcb,
+  0x14, 0x7b, 0x7a, 0xb9, 0xf1, 0x9f, 0xfc, 0xa9, 0x7b, 0x72, 0xe3, 0x87,
+  0xba, 0x4b, 0xb9, 0xf1, 0xc6, 0x3b, 0x9e, 0xbf, 0xe9, 0x87, 0x58, 0x78,
+  0xbf, 0x9f, 0xfc, 0x90, 0xfc, 0x7b, 0x4f, 0x1e, 0xcf, 0x8d, 0xff, 0x97,
+  0xe1, 0x2b, 0xc1, 0x4f, 0xb0, 0x4b, 0xc3, 0xec, 0x77, 0x47, 0x37, 0xf8,
+  0x1f, 0xbb, 0x77, 0x34, 0xce, 0x8d, 0xdf, 0xd5, 0x1d, 0x45, 0x2f, 0x73,
+  0x57, 0x27, 0xb8, 0xef, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xba, 0x2d, 0x72, 0xeb, 0x37,
+  0xeb, 0xc5, 0xe8, 0xd3, 0x17, 0x6d, 0x70, 0xbc, 0x57, 0x06, 0xd7, 0x77,
+  0x7d, 0xf5, 0x4c, 0xf4, 0x32, 0xe7, 0xde, 0xbf, 0x37, 0xf8, 0xa2, 0xf9,
+  0xe8, 0xe1, 0xdc, 0x78, 0xe3, 0x4d, 0xc9, 0xff, 0x57, 0x8a, 0xe0, 0x27,
+  0xf0, 0x42, 0x27, 0x38, 0xde, 0xdf, 0x11, 0xfc, 0x78, 0xbf, 0xf0, 0x99,
+  0x13, 0xd1, 0xab, 0x5f, 0xff, 0xdc, 0x0f, 0x73, 0xe3, 0xf7, 0x97, 0xc3,
+  0xdc, 0xf8, 0x60, 0x3c, 0x8d, 0x5e, 0xa6, 0x4d, 0x7e, 0xab, 0xfa, 0x85,
+  0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x98,
+  0x95, 0xea, 0xe4, 0xc2, 0x5a, 0x6e, 0xbd, 0x0e, 0x3f, 0x7d, 0x5d, 0x14,
+  0xb9, 0xf1, 0x72, 0xd2, 0xe4, 0xc6, 0x07, 0xeb, 0xa3, 0xe8, 0x65, 0xee,
+  0x7b, 0xfa, 0x48, 0x6e, 0xfc, 0xee, 0x5e, 0xdf, 0x3b, 0x07, 0xfe, 0xdf,
+  0x77, 0x7a, 0x6b, 0x33, 0x37, 0x7e, 0xee, 0x5b, 0xe7, 0x73, 0xe3, 0x3b,
+  0xbf, 0x75, 0x29, 0x7a, 0x99, 0x33, 0xc7, 0x56, 0x73, 0xe3, 0x1f, 0x7c,
+  0xf6, 0x6a, 0x6e, 0xbc, 0x5d, 0x2c, 0xa2, 0x97, 0x99, 0xb6, 0xc1, 0x7d,
+  0xbf, 0x70, 0x00, 0x00, 0x71, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0xb3, 0x52, 0x2d, 0x26, 0x93, 0xe3, 0x8f, 0x3e, 0x70, 0x7f, 0xf4,
+  0xe9, 0xef, 0x7b, 0xf9, 0x7a, 0x6e, 0x7c, 0x7d, 0xb0, 0x98, 0x1b, 0xbf,
+  0xf1, 0x8f, 0xdf, 0x1b, 0xbd, 0x4c, 0x77, 0xd2, 0xe4, 0xc6, 0x7f, 0x62,
+  0xe7, 0x6a, 0x6e, 0xbc, 0xee, 0xb4, 0xde, 0x96, 0xf8, 0x9b, 0x6f, 0x26,
+  0x9e, 0x7b, 0xed, 0x4a, 0x6e, 0xbc, 0xd9, 0x9c, 0xe4, 0xc6, 0xef, 0xb9,
+  0x7c, 0x3b, 0x7a, 0xf6, 0xe3, 0xeb, 0xc1, 0xfd, 0xad, 0xb2, 0xca, 0x8d,
+  0x5f, 0xae, 0xfb, 0xd1, 0xcb, 0x94, 0x75, 0x3b, 0xa7, 0xaf, 0x76, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xaa, 0x7a,
+  0xb7, 0x27, 0xc1, 0xf9, 0x6e, 0x11, 0x7d, 0xfa, 0x57, 0x7f, 0xe1, 0x68,
+  0x6e, 0xbc, 0x9c, 0x36, 0xc1, 0xd0, 0xfb, 0xc3, 0x53, 0xd1, 0xcb, 0xdc,
+  0xfb, 0xef, 0x3e, 0x9c, 0x1b, 0x6f, 0x3b, 0xed, 0x9c, 0x8e, 0x17, 0x9d,
+  0xc2, 0x7b, 0x9e, 0xbf, 0xd9, 0x0b, 0xb2, 0x6d, 0xa3, 0xfb, 0x0b, 0x45,
+  0xf0, 0xaf, 0xbe, 0xad, 0xeb, 0x5b, 0xb9, 0xf1, 0x7a, 0x6d, 0x31, 0x37,
+  0x7e, 0xfa, 0xfd, 0xfb, 0xa2, 0x67, 0xbf, 0x75, 0x6d, 0x39, 0xf8, 0xdd,
+  0xf1, 0xe2, 0xa5, 0xdc, 0xf8, 0x0b, 0xab, 0xab, 0xd9, 0x17, 0x64, 0x1d,
+  0x7c, 0xc1, 0xfb, 0x85, 0x03, 0x00, 0x88, 0x13, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x98, 0x95, 0xea, 0xbf, 0x3f, 0x7e, 0x2c, 0xb7, 0x7e,
+  0xfc, 0xc0, 0xae, 0xe8, 0xd3, 0xef, 0xff, 0xe2, 0x8b, 0xb9, 0xf1, 0xe1,
+  0x42, 0x99, 0x1b, 0x7f, 0x73, 0x6d, 0x25, 0x7a, 0x99, 0x1f, 0xfe, 0xfe,
+  0xcb, 0xb9, 0xf1, 0xde, 0x67, 0x8b, 0xe0, 0x6b, 0xe6, 0xc1, 0xbd, 0xb9,
+  0xf1, 0x03, 0x65, 0x2f, 0xfb, 0x7e, 0x2a, 0x8a, 0x0e, 0x3f, 0xf6, 0x30,
+  0xd9, 0x3f, 0x9b, 0x82, 0xf3, 0x9b, 0x45, 0x1d, 0xbd, 0xcc, 0x17, 0x9f,
+  0x3d, 0x9d, 0x1b, 0x1f, 0x7f, 0xf5, 0x6c, 0x6e, 0xfc, 0xe8, 0x38, 0x78,
+  0x99, 0x3d, 0xcf, 0x5e, 0x8a, 0x9e, 0xfd, 0xd2, 0x4f, 0x1f, 0xca, 0x8d,
+  0xff, 0xc5, 0xfe, 0xe0, 0xc7, 0xfb, 0x91, 0xcb, 0x9b, 0xd1, 0xcb, 0x7c,
+  0xe2, 0xf4, 0xeb, 0xc9, 0xb7, 0x2a, 0x00, 0x40, 0x98, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0xc0, 0xac, 0x54, 0xbb, 0x6f, 0x0c, 0x73, 0xeb,
+  0x4f, 0xfc, 0xe0, 0xaf, 0xb3, 0xb9, 0x94, 0xec, 0xa5, 0xab, 0x4d, 0x2f,
+  0x37, 0x7e, 0xfa, 0xe7, 0xef, 0x8d, 0x5e, 0xa6, 0xb8, 0xab, 0x9f, 0x1b,
+  0x7f, 0xe7, 0x2f, 0x2f, 0xe4, 0xc6, 0x5f, 0x7b, 0xe9, 0x6a, 0x6e, 0xfc,
+  0xb3, 0x9f, 0x7a, 0x5f, 0xf4, 0xec, 0x2b, 0x73, 0x5b, 0xf0, 0xb7, 0xda,
+  0x49, 0x74, 0xff, 0xad, 0x9b, 0x9b, 0xb9, 0xf1, 0x57, 0x2f, 0xbc, 0x9b,
+  0x1b, 0x3f, 0xf3, 0xfd, 0xcb, 0xd1, 0xcb, 0xdc, 0x73, 0x70, 0x25, 0x37,
+  0x3e, 0x78, 0xf1, 0x46, 0x6e, 0xfc, 0xe1, 0x4b, 0x37, 0x73, 0xe3, 0x3b,
+  0xea, 0x69, 0xf4, 0xec, 0xcb, 0xa7, 0x82, 0x97, 0xb9, 0xb1, 0xdc, 0xcd,
+  0x8d, 0xff, 0xec, 0x8f, 0x4e, 0x47, 0x2f, 0xb3, 0xa7, 0xda, 0x0e, 0x7e,
+  0x65, 0x6b, 0x2e, 0x00, 0x20, 0x4d, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x60, 0x56, 0xaa, 0xfb, 0x97, 0xa7, 0xb9, 0xf5, 0xdd, 0xe5, 0x24,
+  0xfa, 0xf4, 0x8b, 0x0b, 0x6d, 0x6e, 0xbc, 0x08, 0x6e, 0x77, 0x7e, 0xf9,
+  0x8f, 0x5e, 0x8a, 0x5e, 0xe6, 0xd4, 0x89, 0xbb, 0x72, 0xe3, 0xd3, 0x1b,
+  0xe3, 0xdc, 0xf8, 0xa5, 0xdf, 0x3c, 0x91, 0x1b, 0xff, 0xdd, 0xcf, 0x7d,
+  0x37, 0x7a, 0xf6, 0xbb, 0x56, 0x97, 0x82, 0x2f, 0xc8, 0x2a, 0xf8, 0xe7,
+  0xc1, 0xf5, 0x73, 0x1b, 0xd1, 0xcb, 0x0c, 0xf6, 0x0f, 0x72, 0xe3, 0xe3,
+  0xe7, 0xae, 0x05, 0xff, 0x4f, 0xdf, 0xc8, 0x5e, 0xe6, 0xc2, 0x53, 0xfb,
+  0x72, 0xe3, 0x0f, 0x1c, 0x0c, 0xbe, 0x20, 0x0f, 0x9e, 0xbb, 0x94, 0x1b,
+  0xef, 0x37, 0x4d, 0xf4, 0xec, 0xcd, 0x1b, 0x57, 0x73, 0xe3, 0x6f, 0x7c,
+  0xf4, 0x81, 0xdc, 0xf8, 0xf3, 0x7b, 0xf6, 0x44, 0x2f, 0xb3, 0xb9, 0x51,
+  0xe5, 0xc6, 0xfd, 0xc2, 0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0xcc, 0x4a, 0xf5, 0xc1, 0x53, 0xe7, 0x73, 0xeb, 0x2b,
+  0xd5, 0x34, 0xfa, 0xf4, 0x45, 0xd1, 0xe6, 0xc6, 0x97, 0x9a, 0xe0, 0xc3,
+  0x17, 0x75, 0xf6, 0xff, 0x75, 0xd7, 0x6b, 0xc1, 0x87, 0x3f, 0xb3, 0xb4,
+  0x9c, 0x1b, 0x7f, 0xf5, 0xf2, 0x30, 0x37, 0xfe, 0xe0, 0x77, 0x2f, 0x45,
+  0xcf, 0xfe, 0xee, 0xf1, 0xd5, 0xe0, 0x7b, 0xf5, 0xee, 0x1d, 0xb9, 0xf1,
+  0xe3, 0x7f, 0x71, 0x3e, 0x7a, 0x99, 0x1b, 0x9f, 0x7e, 0x30, 0xf8, 0x6a,
+  0x3f, 0xb5, 0x9e, 0x1b, 0x3f, 0x7c, 0x61, 0x3d, 0x7a, 0x99, 0x95, 0x5d,
+  0x65, 0x6e, 0x7c, 0x79, 0x63, 0x9c, 0x1b, 0xdf, 0x51, 0x07, 0x3f, 0x64,
+  0x56, 0x3a, 0xd9, 0xef, 0x8e, 0xdd, 0xc5, 0x28, 0x37, 0xbe, 0xf6, 0xe7,
+  0xa7, 0x72, 0xe3, 0x5f, 0xfb, 0xe7, 0x1f, 0x89, 0x5e, 0x66, 0xf2, 0x07,
+  0x2f, 0xe4, 0xc6, 0xfd, 0xc2, 0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0xcc, 0x4a, 0x75, 0xef, 0xd2, 0x56, 0x6e, 0xbd,
+  0x69, 0x8b, 0xe8, 0xd3, 0x0f, 0x9b, 0x32, 0xf8, 0xf0, 0x45, 0x9b, 0x1b,
+  0x1f, 0x14, 0x75, 0x36, 0x24, 0xeb, 0xe0, 0xc3, 0x6f, 0x17, 0xc1, 0xff,
+  0xd6, 0xbd, 0xc9, 0xf1, 0x63, 0x57, 0x37, 0xa3, 0x67, 0xbf, 0xf6, 0xe1,
+  0x83, 0xb9, 0xf1, 0x23, 0xff, 0xf3, 0xed, 0xdc, 0xf8, 0xfd, 0x57, 0x6f,
+  0x47, 0x2f, 0x73, 0xe5, 0x73, 0x2f, 0xe4, 0xc6, 0x5f, 0xfa, 0xd5, 0x07,
+  0x73, 0xe3, 0xbb, 0x4f, 0x5f, 0x8b, 0x5e, 0xe6, 0x3d, 0xcf, 0xbc, 0x95,
+  0x1b, 0xef, 0xb7, 0xc1, 0xcf, 0x99, 0xa3, 0x0b, 0x77, 0x82, 0xdf, 0x4c,
+  0xc9, 0x8f, 0xdf, 0x4e, 0xa7, 0x33, 0x49, 0x7e, 0x37, 0xbd, 0xb1, 0xb2,
+  0x33, 0x37, 0xfe, 0x81, 0xff, 0xf4, 0x7c, 0xf4, 0x32, 0x9b, 0xfb, 0x83,
+  0x0f, 0xef, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x60, 0x56, 0xaa, 0x41, 0x55, 0xe7, 0xd6, 0xcb, 0xa2, 0x8d,
+  0x3e, 0x7d, 0xbf, 0x0e, 0x3e, 0xfc, 0xe5, 0xed, 0x7e, 0x6e, 0x7c, 0xab,
+  0x29, 0xa3, 0x97, 0xf9, 0xf2, 0x47, 0x1f, 0xca, 0x8d, 0x6f, 0x27, 0x9f,
+  0xfc, 0x91, 0x2f, 0x9c, 0xca, 0x8d, 0x3f, 0x38, 0xdc, 0x8c, 0x9e, 0x7d,
+  0xd7, 0x57, 0x5f, 0xcd, 0x8d, 0x1f, 0xb9, 0x11, 0x7c, 0xf8, 0x61, 0x91,
+  0xfd, 0xdb, 0xa3, 0x6e, 0x8b, 0xdc, 0xf8, 0x9d, 0x2a, 0xf8, 0xe4, 0x3b,
+  0x27, 0xd3, 0xe8, 0x65, 0x76, 0x36, 0x93, 0xdc, 0xf8, 0xfe, 0xce, 0x28,
+  0x37, 0x1e, 0xfd, 0xee, 0xe8, 0x64, 0xbf, 0x3a, 0x3a, 0x83, 0x85, 0x26,
+  0x37, 0xfe, 0xf4, 0xf0, 0x62, 0xf0, 0xad, 0x34, 0x2c, 0xa2, 0x97, 0x79,
+  0xa9, 0xda, 0x97, 0x1b, 0xf7, 0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x30, 0x2b, 0xd5, 0xce, 0xfe, 0x38, 0xb7,
+  0x7e, 0x67, 0xd4, 0x8d, 0x3e, 0xfd, 0x52, 0x55, 0xe7, 0xc6, 0x6f, 0x2d,
+  0xf5, 0x73, 0xe3, 0x5f, 0x7e, 0xec, 0x44, 0xf4, 0x32, 0xfb, 0xaf, 0x6d,
+  0xe4, 0xc6, 0x1f, 0x78, 0xfb, 0x46, 0x6e, 0xfc, 0xb5, 0x87, 0xf7, 0xe5,
+  0xc6, 0xef, 0x7e, 0xfe, 0x7a, 0xf4, 0xec, 0x8f, 0xdd, 0x5a, 0xcf, 0x8d,
+  0x8f, 0x17, 0x82, 0x7f, 0x1e, 0x5c, 0x6f, 0x7a, 0xd1, 0xcb, 0x7c, 0xe5,
+  0xe3, 0x8f, 0xe6, 0xc6, 0x0f, 0x0d, 0x83, 0x4f, 0x7e, 0x75, 0xd7, 0x52,
+  0xf4, 0x32, 0xc7, 0x6f, 0x6c, 0xe6, 0xc6, 0xcb, 0xb6, 0xcd, 0x8d, 0x17,
+  0x9d, 0xe0, 0x78, 0xb5, 0xd0, 0x46, 0xcf, 0xbe, 0xda, 0x9d, 0x24, 0xbf,
+  0x98, 0xa6, 0xf3, 0xdb, 0x04, 0x6b, 0xeb, 0xef, 0xe4, 0xc6, 0xfd, 0xc2,
+  0x01, 0x00, 0xc4, 0x09, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0xcc,
+  0x4a, 0xb5, 0x58, 0x35, 0xb9, 0xf5, 0x72, 0x61, 0x12, 0x7d, 0xfa, 0x8d,
+  0x61, 0x37, 0x37, 0xbe, 0xe3, 0xf6, 0x28, 0x78, 0x99, 0xb5, 0xe5, 0xe8,
+  0x65, 0x1e, 0x7f, 0xf5, 0x9d, 0xdc, 0xf8, 0x89, 0xad, 0x9b, 0xb9, 0xf1,
+  0xcd, 0x9b, 0x2b, 0xb9, 0xf1, 0x9d, 0x45, 0xf6, 0x05, 0xd9, 0x2d, 0xda,
+  0xe4, 0x78, 0x1d, 0x3c, 0x7b, 0xdb, 0x44, 0x2f, 0xf3, 0xc0, 0x5f, 0x07,
+  0x5f, 0x90, 0x6b, 0x1b, 0xdb, 0xb9, 0xf1, 0xbf, 0x7c, 0xe2, 0x70, 0xf6,
+  0xad, 0xfa, 0xed, 0xeb, 0xb9, 0xf1, 0xd5, 0xe4, 0x0b, 0xb2, 0x69, 0x8b,
+  0xdc, 0xf8, 0x52, 0x39, 0x8d, 0x9e, 0x7d, 0xb1, 0x0c, 0xbe, 0x9b, 0xda,
+  0xe4, 0x65, 0xaa, 0x32, 0xfb, 0x56, 0x3d, 0xb0, 0xbc, 0x95, 0x1b, 0xf7,
+  0x0b, 0x07, 0x00, 0x10, 0x27, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x30, 0x2b, 0xd5, 0x72, 0x7f, 0x32, 0xbf, 0x4f, 0x3f, 0xaa, 0x83, 0xc1,
+  0xf4, 0xfd, 0xfe, 0x9e, 0xdc, 0xf8, 0xe3, 0xcf, 0xbd, 0x1e, 0xbd, 0xcc,
+  0x93, 0x93, 0x2b, 0xb9, 0xf1, 0xdd, 0xfd, 0x71, 0x6e, 0xbc, 0x3e, 0x77,
+  0x2e, 0x37, 0xbe, 0x5a, 0x8d, 0xa3, 0x67, 0x5f, 0xeb, 0x06, 0xdf, 0x4d,
+  0xe5, 0x42, 0x9b, 0x1b, 0x5f, 0x9a, 0xd4, 0xd1, 0xcb, 0x7c, 0xfa, 0xca,
+  0x99, 0xdc, 0xf8, 0x7a, 0xa7, 0x9b, 0x1b, 0xdf, 0xb8, 0xb1, 0x1a, 0xbd,
+  0xcc, 0xb7, 0xdf, 0x77, 0x5f, 0x6e, 0xfc, 0xa9, 0x53, 0x17, 0x83, 0xef,
+  0xa6, 0xc9, 0x8d, 0xdc, 0x78, 0x31, 0xcf, 0x7f, 0x6a, 0x57, 0x65, 0x13,
+  0x7c, 0xab, 0x76, 0xb3, 0x6f, 0xd5, 0xa5, 0xc5, 0xe9, 0x9c, 0x9e, 0x1d,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60, 0x96, 0xaa,
+  0x85, 0x64, 0x72, 0xd4, 0x75, 0x11, 0x7d, 0xfa, 0x3d, 0x3b, 0xb6, 0x73,
+  0xe3, 0xbf, 0x5e, 0x5e, 0xca, 0x8d, 0x3f, 0x7b, 0x69, 0x25, 0x7a, 0x99,
+  0xa3, 0xbb, 0xef, 0x24, 0x5f, 0x34, 0x4d, 0x6e, 0xfc, 0x83, 0x83, 0x49,
+  0xf0, 0x2e, 0x93, 0xec, 0xdb, 0xa9, 0x6e, 0x83, 0x2f, 0xf8, 0xa2, 0x68,
+  0x73, 0xe3, 0x77, 0x95, 0x75, 0xf8, 0x2f, 0x9b, 0x5e, 0x6e, 0xbc, 0xd7,
+  0x04, 0x5f, 0x90, 0xbf, 0xf4, 0xca, 0xe9, 0xe8, 0x65, 0x2e, 0x8e, 0x16,
+  0x73, 0xe3, 0x5f, 0xfb, 0xd5, 0xc7, 0x72, 0xe3, 0x77, 0x7f, 0xf3, 0x64,
+  0x6e, 0x7c, 0x35, 0xfd, 0x5e, 0x4d, 0x5a, 0xea, 0x06, 0xdf, 0x4d, 0x0b,
+  0xc9, 0xcf, 0x81, 0xf4, 0xe7, 0x8c, 0x5f, 0x38, 0x00, 0x80, 0x38, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10,
+  0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20,
+  0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x80, 0x59, 0xa9, 0x96, 0x96, 0x26,
+  0xb9, 0xf5, 0xba, 0xce, 0x06, 0xcd, 0x74, 0x5a, 0xe4, 0xc6, 0x77, 0x6c,
+  0x6d, 0xe7, 0xc6, 0x77, 0x1f, 0x59, 0x89, 0x5e, 0x66, 0xb5, 0x1e, 0xe5,
+  0xc6, 0xfb, 0x8b, 0x75, 0x6e, 0xbc, 0x28, 0xda, 0xe0, 0x0b, 0x26, 0xfc,
+  0x82, 0xdc, 0x1a, 0x55, 0xb9, 0xf1, 0xe1, 0x38, 0x38, 0x3e, 0x6d, 0xb2,
+  0x97, 0xe9, 0x97, 0x75, 0x67, 0x3e, 0x6d, 0x2d, 0x64, 0x9f, 0x7c, 0xb5,
+  0x9b, 0x7c, 0x37, 0xed, 0xe9, 0x07, 0xbf, 0x3c, 0x26, 0xc1, 0x27, 0x9f,
+  0x2e, 0x14, 0xd9, 0x17, 0x64, 0x77, 0x5e, 0x3f, 0xc4, 0x16, 0x16, 0xda,
+  0xce, 0xdc, 0xf2, 0x0b, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e,
+  0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x30, 0x37, 0xaa, 0xb2, 0xdb, 0xe4, 0xd6, 0xbb, 0xfd, 0x3a,
+  0xfa, 0xf4, 0x6d, 0x53, 0xe4, 0xc6, 0x8f, 0x0d, 0xd6, 0x73, 0xe3, 0x87,
+  0x46, 0xb7, 0xa3, 0x97, 0x99, 0x4c, 0xca, 0xdc, 0x78, 0x5d, 0x17, 0x73,
+  0xfb, 0x72, 0x6f, 0xa2, 0xfb, 0x8b, 0xdd, 0xe8, 0xfe, 0x34, 0x37, 0x3d,
+  0x1c, 0x57, 0xd1, 0xcb, 0xf4, 0xca, 0xe0, 0x6b, 0xa6, 0x6e, 0x82, 0x7f,
+  0x38, 0x75, 0x8b, 0x36, 0x7a, 0x99, 0x69, 0x11, 0x7c, 0xf8, 0x5e, 0x27,
+  0xf8, 0x39, 0xf0, 0xf5, 0x23, 0x87, 0x73, 0xe3, 0x4f, 0x5e, 0xbd, 0x1a,
+  0x3d, 0xfb, 0xbd, 0xc5, 0x9d, 0xe4, 0x7c, 0xf4, 0x13, 0x32, 0xfb, 0x82,
+  0x8c, 0xf2, 0x0b, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10,
+  0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00,
+  0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x30, 0x37, 0xaa, 0xee, 0x62, 0x93, 0x5b, 0x2f, 0x16, 0xda, 0xe8,
+  0xd3, 0xb7, 0xc9, 0xf9, 0xb6, 0x29, 0x72, 0xe3, 0xe5, 0x62, 0x1d, 0xbd,
+  0xcc, 0x78, 0x58, 0xe5, 0xc6, 0x9b, 0xe4, 0x65, 0xc6, 0xe3, 0x32, 0x37,
+  0x3e, 0x9d, 0x66, 0x0b, 0xbb, 0x57, 0x05, 0xff, 0x5b, 0x47, 0xc9, 0xcb,
+  0x2c, 0x2d, 0x4e, 0xa3, 0x97, 0x99, 0x26, 0x5f, 0x33, 0xd1, 0x4f, 0x99,
+  0xa2, 0xc9, 0x7e, 0x88, 0x9d, 0xdc, 0xb5, 0x96, 0x1b, 0x1f, 0x7c, 0xf3,
+  0x74, 0x6e, 0xfc, 0x23, 0x17, 0x2f, 0xe6, 0xc6, 0x4f, 0xf4, 0x6e, 0x67,
+  0xbf, 0x3b, 0x3a, 0xc9, 0x17, 0x64, 0x9b, 0x7d, 0xcd, 0xcc, 0x2f, 0xbf,
+  0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03,
+  0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80,
+  0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x73,
+  0xa3, 0xea, 0x2d, 0x4f, 0x72, 0xeb, 0x45, 0xd1, 0xce, 0xef, 0x69, 0x9a,
+  0xba, 0xc8, 0x8d, 0x8f, 0x87, 0x55, 0xf4, 0xe1, 0x7b, 0x83, 0x69, 0x6e,
+  0x7c, 0xfb, 0x4e, 0x37, 0x37, 0xde, 0xef, 0x07, 0x9f, 0x7c, 0x32, 0x29,
+  0xa3, 0x67, 0x1f, 0x8d, 0xca, 0xb9, 0x7d, 0xbd, 0x17, 0xd1, 0xf5, 0xb6,
+  0x0d, 0xee, 0x4f, 0x93, 0xe3, 0x1b, 0x9d, 0x6e, 0xf4, 0x32, 0xe7, 0x1f,
+  0xda, 0x13, 0x1c, 0x1f, 0x2c, 0xe5, 0xc6, 0x7f, 0xed, 0xe6, 0x85, 0xe0,
+  0x37, 0x53, 0xf8, 0xbb, 0x63, 0x52, 0x07, 0xff, 0xd8, 0xae, 0xca, 0x69,
+  0x87, 0x1f, 0xc7, 0x2f, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00,
+  0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00,
+  0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82,
+  0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10,
+  0x1c, 0x00, 0xc0, 0xdc, 0xa8, 0x8a, 0x22, 0xba, 0x5f, 0xcc, 0xef, 0x69,
+  0x8a, 0x64, 0x8c, 0xf5, 0x06, 0xd3, 0xe8, 0xc3, 0x6f, 0xdf, 0xe9, 0xe6,
+  0xc6, 0x17, 0xfb, 0x75, 0x6e, 0x7c, 0x32, 0x0a, 0xde, 0xbd, 0xdb, 0xad,
+  0xa3, 0x67, 0xaf, 0xeb, 0xf9, 0x7d, 0xc1, 0xb7, 0xd1, 0xf5, 0xab, 0xe3,
+  0x7e, 0x6e, 0xfc, 0xdd, 0x49, 0xf0, 0xd5, 0x7e, 0xae, 0x5c, 0x8a, 0x5e,
+  0x66, 0xdf, 0xeb, 0xb7, 0x72, 0xe3, 0xef, 0xbf, 0x73, 0x31, 0x37, 0xbe,
+  0xd2, 0x04, 0x3f, 0xc4, 0x8a, 0x2a, 0xfb, 0x82, 0x1c, 0x4d, 0xcb, 0xe0,
+  0xe7, 0x4c, 0xd9, 0x24, 0xbf, 0x53, 0x9b, 0xce, 0xdc, 0xf2, 0x0b, 0x07,
+  0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00, 0x00,
+  0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e,
+  0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00,
+  0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00,
+  0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00,
+  0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x30, 0x37, 0x2a,
+  0x27, 0xf8, 0x3f, 0x29, 0x8a, 0xe8, 0x7a, 0x1b, 0x7d, 0xf8, 0xb2, 0xdb,
+  0xcc, 0xe9, 0x2c, 0x96, 0xde, 0xcd, 0x00, 0x00, 0x01, 0x91, 0x49, 0x44,
+  0x41, 0x54, 0xd9, 0xdb, 0xb6, 0x9c, 0xdf, 0xd7, 0x4c, 0xaf, 0x57, 0x07,
+  0x5f, 0x32, 0x9d, 0xe0, 0x6b, 0xe6, 0xd6, 0x56, 0x2f, 0x7a, 0x99, 0xf3,
+  0xa3, 0xa5, 0xdc, 0xf8, 0xb3, 0x83, 0xb5, 0xdc, 0xf8, 0xa5, 0x13, 0xfb,
+  0xa3, 0x97, 0x39, 0x7b, 0x78, 0x67, 0x6e, 0x7c, 0xf9, 0xcf, 0xde, 0xcc,
+  0x8d, 0x0f, 0x87, 0xc1, 0xbf, 0x57, 0xb7, 0x9b, 0xec, 0xe7, 0x40, 0xb7,
+  0x09, 0x7e, 0x42, 0x6e, 0x8d, 0x83, 0x5f, 0xac, 0xcb, 0xbd, 0x49, 0xfa,
+  0xab, 0x2f, 0x37, 0xed, 0x17, 0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00,
+  0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1,
+  0x01, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x82, 0x03, 0x00, 0x60, 0x56, 0xaa, 0xb6, 0x0d, 0xae, 0x17, 0x85,
+  0x0b, 0xff, 0x78, 0x6d, 0x9b, 0x3d, 0x4d, 0xb5, 0x58, 0xe7, 0xc6, 0xeb,
+  0x49, 0xb0, 0x53, 0x17, 0xfb, 0xd3, 0xdc, 0xf8, 0x64, 0x54, 0x85, 0xff,
+  0x5b, 0x83, 0xe3, 0x2f, 0x6e, 0xac, 0xe6, 0xc6, 0x5f, 0xee, 0xad, 0x46,
+  0x2f, 0xf3, 0x6e, 0xb7, 0x9b, 0x1b, 0x7f, 0xf6, 0x9f, 0xfe, 0x4c, 0x6e,
+  0xfc, 0x37, 0xff, 0xd5, 0xd7, 0xa3, 0x97, 0x19, 0x3e, 0x1f, 0x1c, 0xff,
+  0xd6, 0x93, 0x27, 0x72, 0xe3, 0xd7, 0xbe, 0xb7, 0x11, 0x7c, 0x2b, 0x4d,
+  0xa3, 0x57, 0xef, 0xdc, 0x99, 0x96, 0xb9, 0xf1, 0xe5, 0xb5, 0xe0, 0xc7,
+  0xfb, 0x78, 0x38, 0x8c, 0x5e, 0x66, 0xc7, 0xd2, 0x24, 0x37, 0xee, 0x17,
+  0x0e, 0x00, 0x20, 0x4e, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c,
+  0x00, 0x00, 0x82, 0x03, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00,
+  0x10, 0x1c, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x10, 0x1c, 0x00, 0x80, 0xe0,
+  0x00, 0x00, 0x04, 0x07, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x04, 0x07, 0x00,
+  0x20, 0x38, 0x00, 0x00, 0x04, 0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0x04,
+  0x07, 0x00, 0x20, 0x38, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x20, 0x38, 0x00,
+  0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08,
+  0x0e, 0x00, 0x00, 0xc1, 0x01, 0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00,
+  0x00, 0x08, 0x0e, 0x00, 0x40, 0x70, 0x00, 0x00, 0x82, 0x03, 0x00, 0x60,
+  0x56, 0xfe, 0x37, 0x78, 0x5d, 0xa8, 0x59, 0xa3, 0x1a, 0x66, 0x14, 0x00,
+  0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82
+};
+
+static const unsigned int sEncodedBufferImageDataPNGLength = sizeof( sEncodedBufferImageDataPNG );
+
+} // anonymous namespace
+
+
+int UtcDaliEncodedBufferImageCtorsP(void)
+{
+  TestApplication application;
+
+  EncodedBufferImage image1;
+  DALI_TEST_CHECK( !image1 );
+
+  image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER );
+  EncodedBufferImage image2( image1 );
+
+  DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliEncodedBufferImageOperatorAssignmentP(void)
+{
+  TestApplication application;
+
+  EncodedBufferImage image1;
+  DALI_TEST_CHECK( !image1 );
+
+  image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER );
+  EncodedBufferImage image2;
+  image2 = image1;
+
+  DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliEncodedBufferImageDownCastP(void)
+{
+  TestApplication application;
+
+  Image image1 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER );
+  EncodedBufferImage image2 = DownCast< EncodedBufferImage >(image1);
+
+  DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
+  END_TEST;
+}
+
+// Positive test case for constructors:
+int UtcDaliEncodedBufferImageNew01(void)
+{
+  TestApplication application;
+
+  tet_infoline( "UtcDaliEncodedBufferImageNew01() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount, ImageDimensions size, FittingMode::Type scalingMode, SamplingMode::Type samplingMode, ReleasePolicy releasePol, bool orientationCorrection )" );
+
+  // Invoke default handle constructor for the Image base class:
+  Image image;
+
+  DALI_TEST_CHECK( !image );
+
+  // Trigger image decode to initialise the handle
+  image = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::NEVER );
+
+  DALI_TEST_CHECK( image );
+
+  // Change the release policy to Unused:
+  Image image2;
+
+  DALI_TEST_CHECK( !image2 );
+
+  // Trigger image decode to initialise the handle
+  image2 = EncodedBufferImage::New( sEncodedBufferImageDataPNG, sEncodedBufferImageDataPNGLength, ImageDimensions(), FittingMode::DEFAULT, SamplingMode::DEFAULT, Image::UNUSED );
+
+  DALI_TEST_CHECK( image2 );
+  END_TEST;
+}
+
+// Negative test case for constructor - null pointer:
+int UtcDaliEncodedBufferImageNew02(void)
+{
+  TestApplication application;
+
+  tet_infoline( "UtcDaliEncodedBufferImageNew02() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount )" );
+
+  // Invoke default handle constructor for the Image base class:
+  Image image;
+
+  DALI_TEST_CHECK( !image );
+
+  // Trigger image decode to initialise the handle
+  try
+  {
+    // This should throw on the null pointer:
+    image = EncodedBufferImage::New( 0, sEncodedBufferImageDataPNGLength );
+    tet_result( TET_FAIL );
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+  END_TEST;
+}
+
+// Negative test case for constructor - zero-length input buffer:
+int UtcDaliEncodedBufferImageNew03(void)
+{
+  TestApplication application;
+
+  tet_infoline( "UtcDaliEncodedBufferImageNew03() - EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount )" );
+
+  // Invoke default handle constructor for the Image base class:
+  Image image;
+
+  DALI_TEST_CHECK( !image );
+
+  // Trigger image decode to initialise the handle
+  try
+  {
+    // This should throw on the zero size:
+    image = EncodedBufferImage::New( sEncodedBufferImageDataPNG, /** Trigger the assertion.*/ 0 );
+    tet_result( TET_FAIL );
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp b/automated-tests/src/dali/utc-Dali-FrameBufferImage.cpp
new file mode 100644 (file)
index 0000000..31c4939
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+#include <dali/integration-api/gl-abstraction.h>
+
+using std::max;
+using namespace Dali;
+
+void utc_dali_framebuffer_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_framebuffer_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+static const float ROTATION_EPSILON = 0.0001f;
+
+
+int UtcDaliFrameBufferImageNew01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageNew01 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+
+  // initialise handle
+  image = FrameBufferImage::New();            // create framebuffer with the same dimensions as the stage
+  ImageActor actor=ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image );
+  DALI_TEST_EQUALS((float)image.GetWidth(), stageSize.width, TEST_LOCATION);
+  DALI_TEST_EQUALS((float)image.GetHeight(), stageSize.height, TEST_LOCATION);
+
+  image = FrameBufferImage::New(16, 16);      // create framebuffer with dimensions of 16x16
+  actor.SetImage(image);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_CHECK( image );
+  DALI_TEST_EQUALS(image.GetWidth(), 16u, TEST_LOCATION);
+  DALI_TEST_EQUALS(image.GetHeight(), 16u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageNew02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageNew02 - FrameBufferImage::New(NativeImageInterface&)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+  TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16);
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = FrameBufferImage::New(*(nativeImage.Get()));
+
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageNew03(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageNew03 - FrameBufferImage::New(NativeImageInterface&, ReleasePolicy)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+  TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16);
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle with UNUSED release policy
+  image = FrameBufferImage::New(*(nativeImage.Get()), Image::UNUSED);
+
+  DALI_TEST_CHECK( image );
+  DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::UNUSED, TEST_LOCATION );
+
+  // initialise handle with NEVER release policy
+  image.Reset();
+  DALI_TEST_CHECK( !image );
+
+  image = FrameBufferImage::New(*(nativeImage.Get()), Image::NEVER);
+
+  DALI_TEST_CHECK( image );
+  DALI_TEST_EQUALS( image.GetReleasePolicy(), Image::NEVER, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageAttachments01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageAttachments01 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+
+  // initialise handle
+  image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR);       // create framebuffer with Color buffer
+  ImageActor actor=ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageAttachments02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageAttachments02 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+
+  // initialise handle
+  image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH); // create framebuffer with Color and Depth buffer
+  ImageActor actor=ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageAttachments03(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageAttachments03 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+
+  // initialise handle
+  image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_STENCIL);  // create framebuffer with Color and Stencil
+  ImageActor actor=ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageAttachments04(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliFrameBufferImageAttachments04 - FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format)");
+
+  // invoke default handle constructor
+  FrameBufferImage image;
+
+  // initialise handle
+  image = FrameBufferImage::New(64, 64, Pixel::RGBA8888, RenderBuffer::COLOR_DEPTH_STENCIL);  // create framebuffer with Color, Depth and Stencil buffers
+  ImageActor actor=ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferColorAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferDepthAttachment(), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(application.GetGlAbstraction().CheckFramebufferStencilAttachment(), true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliFrameBufferImageDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::FrameBufferImage::DownCast()");
+
+  FrameBufferImage image = FrameBufferImage::New();
+
+  BaseHandle object(image);
+
+  FrameBufferImage image2 = FrameBufferImage::DownCast(object);
+  DALI_TEST_CHECK(image2);
+
+  FrameBufferImage image3 = DownCast< FrameBufferImage >(object);
+  DALI_TEST_CHECK(image3);
+
+  BaseHandle unInitializedObject;
+  FrameBufferImage image4 = FrameBufferImage::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!image4);
+
+  FrameBufferImage image5 = DownCast< FrameBufferImage >(unInitializedObject);
+  DALI_TEST_CHECK(!image5);
+
+  Image image6 = FrameBufferImage::New();
+  FrameBufferImage image7 = FrameBufferImage::DownCast(image6);
+  DALI_TEST_CHECK(image7);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Gesture.cpp b/automated-tests/src/dali/utc-Dali-Gesture.cpp
new file mode 100644 (file)
index 0000000..ccd31a6
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_gesture_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_gesture_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+// TestGesture Struct (Gesture constructor is protected)
+struct TestGesture : public Gesture
+{
+public:
+  TestGesture(Gesture::Type type, Gesture::State state)
+  : Gesture(type, state) {}
+
+  virtual ~TestGesture() {}
+};
+
+} // anon namespace
+
+int UtcDaliGestureConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  TestGesture pan(Gesture::Pan, Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, pan.state, TEST_LOCATION);
+
+  TestGesture pinch(Gesture::Pinch, Gesture::Clear);
+  DALI_TEST_EQUALS(Gesture::Pinch, pinch.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Clear, pinch.state, TEST_LOCATION);
+
+  // Test copy constructor
+  TestGesture pan2(pan);
+  DALI_TEST_EQUALS(Gesture::Pan, pan2.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, pan2.state, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGestureAssignment(void)
+{
+  // Test Assignment operator
+  TestGesture pan(Gesture::Pan, Gesture::Finished);
+  DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, pan.state, TEST_LOCATION);
+
+  TestGesture test(Gesture::Pinch, Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Pinch, test.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, test.state, TEST_LOCATION);
+
+  test = pan;
+  DALI_TEST_EQUALS(Gesture::Pan, test.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, test.state, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-GestureDetector.cpp b/automated-tests/src/dali/utc-Dali-GestureDetector.cpp
new file mode 100644 (file)
index 0000000..12a41c4
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <algorithm>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_gesture_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_gesture_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliGestureDetectorConstructorN(void)
+{
+  TestApplication application;
+
+  GestureDetector detector;
+
+  Actor actor = Actor::New();
+
+  try
+  {
+    detector.Attach(actor);
+    tet_result(TET_FAIL);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_ASSERT( e, "detector", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorConstructorP(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  Actor actor = Actor::New();
+
+  try
+  {
+    detector.Attach(actor);
+    tet_result(TET_PASS);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorAssignP(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+  GestureDetector detector2;
+
+  detector2 = detector;
+
+  Actor actor = Actor::New();
+
+  try
+  {
+    detector2.Attach(actor);
+    tet_result(TET_PASS);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDownCastP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::GestureDetector::DownCast()");
+
+  GestureDetector detector = PanGestureDetector::New();
+
+  BaseHandle object(detector);
+
+  GestureDetector detector2 = GestureDetector::DownCast(object);
+  DALI_TEST_CHECK(detector2);
+
+  GestureDetector detector3 = DownCast< GestureDetector >(object);
+  DALI_TEST_CHECK(detector3);
+
+  BaseHandle unInitializedObject;
+  GestureDetector detector4 = GestureDetector::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!detector4);
+
+  GestureDetector detector5 = DownCast< GestureDetector >(unInitializedObject);
+  DALI_TEST_CHECK(!detector5);
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorAttachP(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  Actor actor = Actor::New();
+
+  detector.Attach(actor);
+
+  bool found = false;
+  for(size_t i = 0; i < detector.GetAttachedActorCount(); i++)
+  {
+    if( detector.GetAttachedActor(i) == actor )
+    {
+      tet_result(TET_PASS);
+      found = true;
+    }
+  }
+
+  if(!found)
+  {
+    tet_result(TET_FAIL);
+  }
+
+  // Scoped gesture detector. GestureDetectors connect to a destroy signal of the actor. If the
+  // actor is still alive when the gesture detector is destroyed, then it should disconnect from
+  // this signal.  If it does not, then when this function ends, there will be a segmentation fault
+  // thus, a TET case failure.
+  {
+    GestureDetector detector2 = PanGestureDetector::New();
+    detector2.Attach(actor);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorAttachN(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  // Do not initialise actor
+  Actor actor;
+
+  try
+  {
+    detector.Attach(actor);
+    tet_result(TET_FAIL);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_ASSERT( e, "actor", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachP(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  Actor actor = Actor::New();
+  detector.Attach(actor);
+
+  bool found = false;
+  for(size_t i = 0; i < detector.GetAttachedActorCount(); i++)
+  {
+    if( detector.GetAttachedActor(i) == actor )
+    {
+      tet_result(TET_PASS);
+      found = true;
+    }
+  }
+
+  if(!found)
+  {
+    tet_result(TET_FAIL);
+  }
+
+  // Detach and retrieve attached actors again, the vector should be empty.
+  detector.Detach(actor);
+
+  found = false;
+  for(size_t i = 0; i < detector.GetAttachedActorCount(); i++)
+  {
+    if( detector.GetAttachedActor(i) == actor )
+    {
+      found = true;
+    }
+  }
+
+  if(found)
+  {
+    tet_result(TET_FAIL);
+  }
+  else
+  {
+    tet_result(TET_PASS);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachN01(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  // Do not initialise actor
+  Actor actor;
+
+  try
+  {
+    detector.Detach(actor);
+    tet_result(TET_FAIL);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_ASSERT( e, "actor", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachN02(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  Actor actor = Actor::New();
+  detector.Attach(actor);
+
+  // Detach an actor that hasn't been attached.  This should not cause an exception, it's a no-op.
+  try
+  {
+    Actor actor2 = Actor::New();
+    detector.Detach(actor2);
+    tet_result(TET_PASS);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachN03(void)
+{
+  TestApplication application;
+  TestGestureManager& gestureManager = application.GetGestureManager();
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  Actor actor = Actor::New();
+  detector.Attach(actor);
+
+  // Detach an actor twice - no exception should happen.
+  try
+  {
+    detector.Detach(actor);
+    DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+    gestureManager.Initialize(); // Reset values
+    detector.Detach(actor);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachAllP(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  const unsigned int actorsToAdd = 5;
+  std::vector<Actor> myActors;
+
+  for (unsigned int i = 0; i < actorsToAdd; ++i)
+  {
+    Actor actor = Actor::New();
+    myActors.push_back(actor);
+    detector.Attach(actor);
+  }
+
+  DALI_TEST_EQUALS(actorsToAdd, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach and retrieve attached actors again, the vector should be empty.
+  detector.DetachAll();
+
+  DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorDetachAllN(void)
+{
+  TestApplication application;
+  TestGestureManager& gestureManager = application.GetGestureManager();
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  const unsigned int actorsToAdd = 5;
+  std::vector<Actor> myActors;
+
+  for (unsigned int i = 0; i < actorsToAdd; ++i)
+  {
+    Actor actor = Actor::New();
+    myActors.push_back(actor);
+    detector.Attach(actor);
+  }
+
+  DALI_TEST_EQUALS(actorsToAdd, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach and retrieve attached actors again, the vector should be empty.
+  detector.DetachAll();
+
+  DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION);
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Call DetachAll again, there should not be any exception
+  try
+  {
+    gestureManager.Initialize(); // Reset values
+    detector.DetachAll();
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  }
+  catch (DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+int UtcDaliGestureDetectorGetAttachedActors(void)
+{
+  TestApplication application;
+
+  // Use pan gesture as GestureDetector cannot be created.
+  GestureDetector detector = PanGestureDetector::New();
+
+  // Initially there should not be any actors.
+  DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Attach one actor
+  Actor actor1 = Actor::New();
+  detector.Attach(actor1);
+  DALI_TEST_EQUALS(1u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Attach another actor
+  Actor actor2 = Actor::New();
+  detector.Attach(actor2);
+  DALI_TEST_EQUALS(2u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Attach another five actors
+  std::vector<Actor> myActors;
+  for (unsigned int i = 0; i < 5; ++i)
+  {
+    Actor actor = Actor::New();
+    myActors.push_back(actor);
+    detector.Attach(actor);
+  }
+  DALI_TEST_EQUALS(7u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach actor2
+  detector.Detach(actor2);
+  DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Attach actor1 again, count should not increase.
+  detector.Attach(actor1);
+  DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach actor2 again, count should not decrease.
+  detector.Detach(actor2);
+  DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach actor1.
+  detector.Detach(actor1);
+  DALI_TEST_EQUALS(5u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Create scoped actor, actor should be automatically removed from the detector when it goes out
+  // of scope.
+  {
+    Actor scopedActor = Actor::New();
+    detector.Attach(scopedActor);
+    DALI_TEST_EQUALS(6u, detector.GetAttachedActorCount(), TEST_LOCATION);
+  }
+  DALI_TEST_EQUALS(5u, detector.GetAttachedActorCount(), TEST_LOCATION);
+
+  // Detach all so nothing remains.
+  detector.DetachAll();
+  DALI_TEST_EQUALS(0u, detector.GetAttachedActorCount(), TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Handle.cpp b/automated-tests/src/dali/utc-Dali-Handle.cpp
new file mode 100644 (file)
index 0000000..b0cd8cf
--- /dev/null
@@ -0,0 +1,760 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include "dali-test-suite-utils/dali-test-suite-utils.h"
+#include <mesh-builder.h>
+
+using namespace Dali;
+
+void handle_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void handle_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+/// Allows the creation of a BaseObject
+class BaseObjectType : public BaseObject
+{
+public:
+  BaseObjectType()
+  {
+  }
+};
+
+Handle ImplicitCopyConstructor(Handle passedByValue)
+{
+  // object + copy + passedByValue, ref count == 3
+  DALI_TEST_CHECK(passedByValue);
+  if (passedByValue)
+  {
+    DALI_TEST_EQUALS(3, passedByValue.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  return passedByValue;
+}
+
+} // anon namespace
+
+
+int UtcDaliHandleConstructorVoid(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Handle::Handle()");
+
+  Handle object;
+
+  DALI_TEST_CHECK(!object);
+
+  END_TEST;
+}
+
+int UtcDaliHandleCopyConstructor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Handle::Handle(const Handle&)");
+
+  // Initialize an object, ref count == 1
+  Handle object = Actor::New();
+
+  DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  // Copy the object, ref count == 2
+  Handle copy(object);
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+
+  {
+    // Pass by value, and return another copy, ref count == 3
+    Handle anotherCopy = ImplicitCopyConstructor(copy);
+
+    DALI_TEST_CHECK(anotherCopy);
+    if (anotherCopy)
+    {
+      DALI_TEST_EQUALS(3, anotherCopy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+    }
+  }
+
+  // anotherCopy out of scope, ref count == 2
+  DALI_TEST_CHECK(copy);
+  if (copy)
+  {
+    DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliHandleAssignmentOperator(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Handle::operator=");
+
+  Handle object = Actor::New();
+
+  DALI_TEST_CHECK(object);
+  DALI_TEST_EQUALS(1, object.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+
+  Handle copy;
+  DALI_TEST_CHECK(!copy);
+
+  copy = object;
+  DALI_TEST_CHECK(copy);
+  DALI_TEST_EQUALS(2, copy.GetBaseObject().ReferenceCount(), TEST_LOCATION);
+  DALI_TEST_CHECK(&(copy.GetBaseObject()) == &(object.GetBaseObject()));
+  END_TEST;
+}
+
+int UtcDaliHandleSupports(void)
+{
+  tet_infoline("Positive Test Dali::Handle::Supports()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( true == actor.Supports( Handle::DYNAMIC_PROPERTIES ) );
+  END_TEST;
+}
+
+int UtcDaliHandleGetPropertyCount(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyCount()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  int defaultPropertyCount( actor.GetPropertyCount() );
+
+  // Register a dynamic property
+  actor.RegisterProperty( "test-property", float(123.0f) );
+  DALI_TEST_CHECK( (defaultPropertyCount + 1u) == actor.GetPropertyCount() );
+  END_TEST;
+}
+
+int UtcDaliHandleGetPropertyName(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyName()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( "parent-origin" == actor.GetPropertyName( Actor::Property::PARENT_ORIGIN ) );
+
+  // Register a dynamic property
+  std::string name("this-name-should-match");
+  Property::Index index = actor.RegisterProperty( name, float(123.0f) );
+  DALI_TEST_CHECK( name == actor.GetPropertyName( index ) );
+
+  END_TEST;
+}
+
+int UtcDaliHandleGetPropertyIndex(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyIndex()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( Actor::Property::PARENT_ORIGIN == actor.GetPropertyIndex("parent-origin") );
+
+  // Register a dynamic property
+  std::string name("this-name-should-match");
+  Property::Index index = actor.RegisterProperty( name, float(123.0f) );
+  DALI_TEST_CHECK( index == actor.GetPropertyIndex( name ) );
+  END_TEST;
+}
+
+int UtcDaliHandleIsPropertyWritable(void)
+{
+  tet_infoline("Positive Test Dali::Handle::IsPropertyWritable()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Actor properties which are writable:
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::PARENT_ORIGIN_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ANCHOR_POINT_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_WIDTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_HEIGHT ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SIZE_DEPTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::POSITION_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::ORIENTATION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::SCALE_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::VISIBLE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_RED ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_GREEN ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_BLUE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyWritable( Actor::Property::COLOR_ALPHA ) );
+
+  // World-properties are not writable:
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_ORIENTATION ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_SCALE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_COLOR ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_X ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_Y ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyWritable( Actor::Property::WORLD_POSITION_Z ) );
+
+  END_TEST;
+}
+
+int UtcDaliHandleIsPropertyAnimatable(void)
+{
+  tet_infoline("Positive Test Dali::Handle::IsPropertyAnimatable()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Actor properties which are animatable:
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_X ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_Y ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::PARENT_ORIGIN_Z ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_X ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_Y ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::ANCHOR_POINT_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_WIDTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_HEIGHT ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SIZE_DEPTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::POSITION_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::ORIENTATION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::SCALE_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::VISIBLE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_RED ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_GREEN ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_BLUE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAnimatable( Actor::Property::COLOR_ALPHA ) );
+
+  // World-properties can not be animated
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_ORIENTATION ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_SCALE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_COLOR ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_X ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_Y ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAnimatable( Actor::Property::WORLD_POSITION_Z ) );
+
+  END_TEST;
+}
+
+int UtcDaliHandleIsPropertyAConstraintInput(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Actor properties which can be used as a constraint input:
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::PARENT_ORIGIN_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ANCHOR_POINT_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_WIDTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_HEIGHT ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_DEPTH  ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::ORIENTATION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::SCALE_Z ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::VISIBLE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_RED ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_GREEN ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_BLUE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_ALPHA ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_ORIENTATION ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_SCALE ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_COLOR ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_X ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_Y ) );
+  DALI_TEST_CHECK( true == actor.IsPropertyAConstraintInput( Actor::Property::WORLD_POSITION_Z ) );
+
+  // Actor properties that cannot be used as a constraint input
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::NAME ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::SENSITIVE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::LEAVE_REQUIRED ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::INHERIT_ORIENTATION ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::INHERIT_SCALE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::COLOR_MODE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::POSITION_INHERITANCE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::DRAW_MODE ) );
+  DALI_TEST_CHECK( false == actor.IsPropertyAConstraintInput( Actor::Property::SIZE_MODE_FACTOR ) );
+
+  END_TEST;
+}
+
+
+int UtcDaliHandleGetPropertyType(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetPropertyType()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( Actor::Property::PARENT_ORIGIN ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( Actor::Property::ANCHOR_POINT ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( Actor::Property::SIZE ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( Actor::Property::POSITION ) );
+  DALI_TEST_CHECK( Property::ROTATION == actor.GetPropertyType( Actor::Property::ORIENTATION ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( Actor::Property::SCALE ) );
+  DALI_TEST_CHECK( Property::BOOLEAN  == actor.GetPropertyType( Actor::Property::VISIBLE ) );
+  DALI_TEST_CHECK( Property::VECTOR4  == actor.GetPropertyType( Actor::Property::COLOR ) );
+
+  // Register some dynamic properties
+  Property::Index boolIndex     = actor.RegisterProperty( "bool-property",     bool(true) );
+  Property::Index floatIndex    = actor.RegisterProperty( "float-property",    float(123.0f) );
+  Property::Index intIndex      = actor.RegisterProperty( "int-property",      123 );
+  Property::Index vector2Index  = actor.RegisterProperty( "vector2-property",  Vector2(1.0f, 2.0f) );
+  Property::Index vector3Index  = actor.RegisterProperty( "vector3-property",  Vector3(1.0f, 2.0f, 3.0f) );
+  Property::Index vector4Index  = actor.RegisterProperty( "vector4-property",  Vector4(1.0f, 2.0f, 3.0f, 4.0f) );
+  Property::Index rotationIndex = actor.RegisterProperty( "rotation-property", AngleAxis(Degree(180.0f), Vector3::YAXIS) );
+
+  DALI_TEST_CHECK( Property::BOOLEAN  == actor.GetPropertyType( boolIndex ) );
+  DALI_TEST_CHECK( Property::FLOAT    == actor.GetPropertyType( floatIndex ) );
+  DALI_TEST_CHECK( Property::INTEGER  == actor.GetPropertyType( intIndex ) );
+  DALI_TEST_CHECK( Property::VECTOR2  == actor.GetPropertyType( vector2Index ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( vector3Index ) );
+  DALI_TEST_CHECK( Property::VECTOR4  == actor.GetPropertyType( vector4Index ) );
+  DALI_TEST_CHECK( Property::ROTATION == actor.GetPropertyType( rotationIndex ) );
+
+  // Non animatable properties
+  Property::Index nonAnimStringIndex = actor.RegisterProperty( "man-from-delmonte", std::string("yes"), Property::READ_WRITE);
+  Property::Index nonAnimV2Index = actor.RegisterProperty( "v2", Vector2(1.f, 2.f), Property::READ_WRITE);
+  Property::Index nonAnimV3Index = actor.RegisterProperty( "v3", Vector3(1.f, 2.f, 3.f), Property::READ_WRITE);
+  Property::Index nonAnimV4Index = actor.RegisterProperty( "v4", Vector4(1.f, 2.f, 3.f, 4.f), Property::READ_WRITE);
+  Property::Index nonAnimBooleanIndex = actor.RegisterProperty( "bool", true, Property::READ_WRITE);
+  Property::Index nonAnimFloatIndex = actor.RegisterProperty( "float", 0.f, Property::READ_WRITE);
+  Property::Index nonAnimIntegerIndex = actor.RegisterProperty( "int", 0, Property::READ_WRITE);
+
+  DALI_TEST_CHECK( nonAnimStringIndex  != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimV2Index      != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimV3Index      != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimV4Index      != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimBooleanIndex != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimFloatIndex   != Property::INVALID_INDEX );
+  DALI_TEST_CHECK( nonAnimIntegerIndex != Property::INVALID_INDEX );
+
+  DALI_TEST_CHECK( Property::STRING   == actor.GetPropertyType( nonAnimStringIndex ) );
+  DALI_TEST_CHECK( Property::VECTOR2  == actor.GetPropertyType( nonAnimV2Index ) );
+  DALI_TEST_CHECK( Property::VECTOR3  == actor.GetPropertyType( nonAnimV3Index ) );
+  DALI_TEST_CHECK( Property::VECTOR4  == actor.GetPropertyType( nonAnimV4Index ) );
+  DALI_TEST_CHECK( Property::BOOLEAN  == actor.GetPropertyType( nonAnimBooleanIndex ) );
+  DALI_TEST_CHECK( Property::FLOAT    == actor.GetPropertyType( nonAnimFloatIndex ) );
+  DALI_TEST_CHECK( Property::INTEGER  == actor.GetPropertyType( nonAnimIntegerIndex ) );
+
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimStringIndex ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV2Index ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV3Index ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimV4Index ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimBooleanIndex ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimFloatIndex ) );
+  DALI_TEST_CHECK( !actor.IsPropertyAnimatable( nonAnimIntegerIndex ) );
+
+  DALI_TEST_EQUALS( "yes" , actor.GetProperty( nonAnimStringIndex ).Get<std::string>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector2(1.f, 2.f) , actor.GetProperty( nonAnimV2Index ).Get<Vector2>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3(1.f, 2.f, 3.f) , actor.GetProperty( nonAnimV3Index ).Get<Vector3>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector4(1.f, 2.f, 3.f, 4.f) , actor.GetProperty( nonAnimV4Index ).Get<Vector4>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, actor.GetProperty( nonAnimBooleanIndex ).Get<bool>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.f, actor.GetProperty( nonAnimFloatIndex ).Get<float>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0, actor.GetProperty( nonAnimIntegerIndex ).Get<int>(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliHandleNonAnimtableProperties(void)
+{
+  tet_infoline("Test Non Animatable Properties");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Property::Index nonAnimStringIndex = actor.RegisterProperty( "man-from-delmonte", std::string("no"), Property::READ_WRITE);
+
+  //// modify writable?
+  try
+  {
+    actor.SetProperty( nonAnimStringIndex, Property::Value("yes") );
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_CHECK(!"exception");
+  }
+
+  DALI_TEST_CHECK( "yes"  == actor.GetProperty( nonAnimStringIndex ).Get<std::string>() );
+
+  //// cannot modify read only?
+  Property::Index readonly = actor.RegisterProperty( "float", 0.f, Property::READ_ONLY);
+
+  DALI_TEST_CHECK(!actor.IsPropertyAnimatable(readonly));
+  DALI_TEST_CHECK(!actor.IsPropertyWritable(readonly));
+
+  bool exception = false;
+  try
+  {
+    actor.SetProperty( readonly, Property::Value(1.f) );
+  }
+  catch (Dali::DaliException& e)
+  {
+    exception = true;
+  }
+
+  DALI_TEST_CHECK(!exception);// trying to set a read-only property is a no-op
+
+  DALI_TEST_EQUALS( 0.f, actor.GetProperty( readonly ).Get<float>(), TEST_LOCATION );
+
+  /// animatable can be set
+  Property::Index write_anim = actor.RegisterProperty( "write_float", 0.f, Property::ANIMATABLE);
+
+  DALI_TEST_CHECK(actor.IsPropertyAnimatable(write_anim));
+  DALI_TEST_CHECK(actor.IsPropertyWritable(write_anim));
+
+  exception = false;
+  try
+  {
+    actor.SetProperty( write_anim, Property::Value(1.f) );
+  }
+  catch (Dali::DaliException& e)
+  {
+    exception = true;
+  }
+
+  DALI_TEST_CHECK(!exception);
+
+  //// animate a non animatable property is a noop?
+  float durationSeconds(2.0f);
+  Animation animation = Animation::New(durationSeconds);
+  bool relativeValue(true);
+
+  exception = false;
+
+  try
+  {
+    animation.AnimateBy(Property(actor, nonAnimStringIndex), relativeValue, AlphaFunction::EASE_IN);
+    animation.Play();
+    application.SendNotification();
+    application.Render(static_cast<unsigned int>(durationSeconds*0100.0f)/* some progress */);
+  }
+  catch (Dali::DaliException& e)
+  {
+    exception = true;
+  }
+
+  DALI_TEST_CHECK(!exception);
+  DALI_TEST_EQUALS( "yes", actor.GetProperty( nonAnimStringIndex ).Get<std::string>(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliHandleNonAnimtableCompositeProperties(void)
+{
+  tet_infoline("Test Non Animatable Composite Properties");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  Property::Value value(Property::ARRAY);
+  Property::Array* array = value.GetArray();
+  DALI_TEST_CHECK( array );
+
+  array->PushBack( Property::Value( 0.1f ) );
+  array->PushBack( "a string" );
+  array->PushBack( Property::Value( Vector3(1,2,3) ) );
+
+  DALI_TEST_EQUALS( 3, array->Count(), TEST_LOCATION );
+
+  Property::Index propertyIndex = actor.RegisterProperty( "composite", value, Property::READ_WRITE );
+
+  Property::Value out = actor.GetProperty( propertyIndex );
+  Property::Array* outArray = out.GetArray();
+  DALI_TEST_CHECK( outArray != NULL );
+
+  DALI_TEST_CHECK( Property::FLOAT     == outArray->GetElementAt(0).GetType());
+  DALI_TEST_CHECK( Property::STRING    == outArray->GetElementAt(1).GetType());
+  DALI_TEST_CHECK( Property::VECTOR3   == outArray->GetElementAt(2).GetType());
+
+  DALI_TEST_EQUALS( 0.1f,            outArray->GetElementAt(0).Get<float>(),       TEST_LOCATION);
+  DALI_TEST_EQUALS( "a string",     outArray->GetElementAt(1).Get<std::string>(),  TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector3(1,2,3), outArray->GetElementAt(2).Get<Vector3>(),      TEST_LOCATION);
+
+  // composite types not animatable
+  bool exception = false;
+  try
+  {
+    actor.RegisterProperty( "compositemap", value, Property::ANIMATABLE);
+  }
+  catch (Dali::DaliException& e)
+  {
+    exception = true;
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+
+  DALI_TEST_EQUALS(exception, true, TEST_LOCATION);
+
+  // Map of maps
+  Property::Value mapOfMaps(Property::MAP);
+  Property::Map* map = mapOfMaps.GetMap();
+
+  map->Insert( "key", Property::Value(Property::MAP) );
+  map->Insert( "2key", "a string" );
+
+  DALI_TEST_EQUALS( "a string",  (*map)["2key"].Get<std::string>(),  TEST_LOCATION);
+
+  Property::Map* innerMap = map->Find("key")->GetMap();
+  innerMap->Insert( "subkey", 5.f );
+
+  DALI_TEST_CHECK( NULL != map->Find("key")->GetMap()->Find("subkey") );
+  DALI_TEST_EQUALS( 5.f, map->Find("key")->GetMap()->Find("subkey")->Get<float>(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliHandleSetProperty01(void)
+{
+  tet_infoline("Positive Test Dali::Handle::SetProperty()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get<Vector3>() );
+
+  actor.SetProperty( Actor::Property::PARENT_ORIGIN, ParentOrigin::CENTER );
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_CHECK( ParentOrigin::CENTER == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get<Vector3>() );
+  END_TEST;
+}
+
+int UtcDaliHandleSetProperty02(void)
+{
+  tet_infoline("Positive Test Dali::Handle::SetProperty()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK( !actor.IsPropertyWritable( Actor::Property::WORLD_POSITION ) );
+
+  // World position is not writable so this is a no-op and should not crash
+  actor.SetProperty( Actor::Property::WORLD_POSITION, Vector3(1,2,3) );
+
+  END_TEST;
+}
+
+int UtcDaliHandleRegisterProperty(void)
+{
+  tet_infoline("Positive Test Dali::Handle::RegisterProperty()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN ).Get<Vector3>() );
+
+  END_TEST;
+}
+
+int UtcDaliHandleGetProperty(void)
+{
+  tet_infoline("Positive Test Dali::Handle::GetProperty()");
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  DALI_TEST_CHECK( ParentOrigin::TOP_LEFT == actor.GetProperty( Actor::Property::PARENT_ORIGIN   ).Get<Vector3>() );
+  DALI_TEST_CHECK( AnchorPoint::CENTER    == actor.GetProperty( Actor::Property::ANCHOR_POINT    ).Get<Vector3>() );
+  DALI_TEST_CHECK( Vector3::ZERO          == actor.GetProperty( Actor::Property::SIZE            ).Get<Vector3>() );
+  DALI_TEST_CHECK( Vector3::ZERO          == actor.GetProperty( Actor::Property::POSITION        ).Get<Vector3>() );
+  DALI_TEST_CHECK( Vector3::ONE           == actor.GetProperty( Actor::Property::SCALE           ).Get<Vector3>() );
+  DALI_TEST_CHECK( true                   == actor.GetProperty( Actor::Property::VISIBLE         ).Get<bool>() );
+  DALI_TEST_CHECK( Color::WHITE           == actor.GetProperty( Actor::Property::COLOR           ).Get<Vector4>() );
+  END_TEST;
+}
+
+int UtcDaliHandleDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Handle::DownCast()");
+
+  Actor actor = Actor::New();
+
+  BaseHandle baseHandle = actor;
+
+  Handle handle = Handle::DownCast(baseHandle);
+
+  DALI_TEST_CHECK( handle );
+
+  baseHandle = BaseHandle();
+
+  handle = Handle::DownCast(baseHandle);
+
+  DALI_TEST_CHECK( !handle );
+
+  END_TEST;
+}
+
+int UtcDaliHandleDownCastNegative(void)
+{
+  TestApplication application;
+
+  // BaseObject is NOT an Object, so this DownCast should fail
+  BaseHandle handle( new BaseObjectType );
+  Handle customHandle1 = Handle::DownCast( handle );
+  DALI_TEST_CHECK( ! customHandle1 );
+
+  // A DownCast on an empty handle will also fail
+  Handle empty;
+  Handle customHandle2 = Handle::DownCast( empty );
+  DALI_TEST_CHECK( ! customHandle2 );
+  END_TEST;
+}
+
+int UtcDaliHandleGetPropertyIndices(void)
+{
+  TestApplication application;
+  Property::IndexContainer indices;
+
+  // Actor
+  Actor actor = Actor::New();
+  actor.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() );
+  DALI_TEST_EQUALS( indices.Size(), actor.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHandleRegisterPropertyTypes(void)
+{
+  TestApplication application;
+
+  struct PropertyTypeAnimatable
+  {
+    const char * name;
+    Property::Value value;
+    bool animatable;
+  };
+
+  Property::Array array;
+  Property::Map map;
+
+  PropertyTypeAnimatable properties[] =
+  {
+    { "Property::BOOLEAN",          true,              true  },
+    { "Property::FLOAT",            1.0f,              true  },
+    { "Property::INTEGER",          1,                 true  },
+    { "Property::VECTOR2",          Vector2::ONE,      true  },
+    { "Property::VECTOR3",          Vector3::ONE,      true  },
+    { "Property::VECTOR4",          Vector4::ONE,      true  },
+    { "Property::MATRIX3",          Matrix3::IDENTITY, true  },
+    { "Property::MATRIX",           Matrix::IDENTITY,  true  },
+    { "Property::RECTANGLE",        Rect<int>(),       false },
+    { "Property::ROTATION",         AngleAxis(),       true  },
+    { "Property::STRING",           std::string("Me"), false },
+    { "Property::ARRAY",            array,             false },
+    { "Property::MAP",              map,               false },
+  };
+
+  unsigned int numOfProperties( sizeof( properties ) / sizeof( properties[0] ) );
+
+  for ( unsigned int i = 0; i < numOfProperties; ++i )
+  {
+    tet_printf( "Testing: %s\n", properties[i].name );
+
+    bool exception = false;
+    try
+    {
+      Actor actor = Actor::New();
+      actor.RegisterProperty( "man-from-delmonte", properties[i].value );
+    }
+    catch (Dali::DaliException& e)
+    {
+      exception = true;
+    }
+
+    DALI_TEST_CHECK( properties[i].animatable != exception );
+  }
+  END_TEST;
+}
+
+int UtcDaliHandleCustomProperty(void)
+{
+  TestApplication application;
+
+  Handle handle = Handle::New();
+
+  float startValue(1.0f);
+  Property::Index index = handle.RegisterProperty( "test-property", startValue );
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == startValue );
+
+  handle.SetProperty( index, 5.0f );
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == 5.0f );
+  application.Render(0);
+  DALI_TEST_CHECK( handle.GetProperty<float>(index) == 5.0f );
+  END_TEST;
+}
+int UtcDaliHandleWeightNew(void)
+{
+  TestApplication application;
+
+  Handle handle = WeightObject::New();;
+  DALI_TEST_CHECK( handle.GetProperty<float>(WeightObject::WEIGHT) == 0.0f );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp b/automated-tests/src/dali/utc-Dali-HoverProcessing.cpp
new file mode 100644 (file)
index 0000000..97f1b28
--- /dev/null
@@ -0,0 +1,1286 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_hover_processing_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_hover_processing_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled( false ),
+    hoverEvent(),
+    hoveredActor()
+  {
+  }
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    hoverEvent.time = 0u;
+    hoverEvent.points.clear();
+
+    hoveredActor.Reset();
+  }
+
+  bool functorCalled;
+  HoverEvent hoverEvent;
+  Actor hoveredActor;
+};
+
+// Functor that sets the data when called
+struct HoverEventFunctor
+{
+  /**
+   * Constructor.
+   * @param[in]  data         Reference to the data to store callback information.
+   * @param[in]  returnValue  What the functor should return.
+   */
+  HoverEventFunctor( SignalData& data, bool returnValue = true )
+  : signalData( data ),
+    returnValue( returnValue )
+  {
+  }
+
+  bool operator()( Actor actor, const HoverEvent& hoverEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.hoveredActor = actor;
+    signalData.hoverEvent = hoverEvent;
+
+    return returnValue;
+  }
+
+  SignalData& signalData;
+  bool returnValue;
+};
+
+// Functor that removes the actor when called.
+struct RemoveActorFunctor : public HoverEventFunctor
+{
+  /**
+   * Constructor.
+   * @param[in]  data         Reference to the data to store callback information.
+   * @param[in]  returnValue  What the functor should return.
+   */
+  RemoveActorFunctor( SignalData& data, bool returnValue = true )
+  : HoverEventFunctor( data, returnValue )
+  {
+  }
+
+  bool operator()( Actor actor, const HoverEvent& hoverEvent )
+  {
+    Actor parent( actor.GetParent() );
+    if ( parent )
+    {
+      parent.Remove( actor );
+    }
+
+    return HoverEventFunctor::operator()( actor, hoverEvent );
+  }
+};
+
+Integration::HoverEvent GenerateSingleHover( TouchPoint::State state, Vector2 screenPosition )
+{
+  Integration::HoverEvent hoverEvent;
+  hoverEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) );
+  return hoverEvent;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliHoverNormalProcessing(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Vector2 localCoordinates;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+
+  TouchPoint point = data.hoverEvent.GetPoint(0);
+  DALI_TEST_EQUALS( TouchPoint::Started, point.state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, point.screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, point.local, 0.1f, TEST_LOCATION );
+
+  data.Reset();
+
+  // Emit a motion signal
+  screenCoordinates.x = screenCoordinates.y = 11.0f;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a finished signal
+  screenCoordinates.x = screenCoordinates.y = 12.0f;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal where the actor is not present
+  screenCoordinates.x = screenCoordinates.y = 200.0f;
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverOutsideCameraNearFarPlanes(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::CENTER);
+  actor.SetParentOrigin(ParentOrigin::CENTER);
+  stage.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Get the camera's near and far planes
+  RenderTaskList taskList = stage.GetRenderTaskList();
+  Dali::RenderTask task = taskList.GetTask(0);
+  CameraActor camera = task.GetCameraActor();
+  float nearPlane = camera.GetNearClippingPlane();
+  float farPlane = camera.GetFarClippingPlane();
+
+  // Calculate the current distance of the actor from the camera
+  float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
+  float distance = (stageSize.y * 0.5f) / tanHalfFov;
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  Vector2 screenCoordinates( stageSize.x * 0.5f, stageSize.y * 0.5f );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal where actor is just at the camera's near plane
+  actor.SetZ(distance - nearPlane);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal where actor is closer than the camera's near plane
+  actor.SetZ((distance - nearPlane) + 1.0f);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal where actor is just at the camera's far plane
+  actor.SetZ(distance - farPlane);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal where actor is further than the camera's far plane
+  actor.SetZ((distance - farPlane) - 1.0f);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverEmitEmpty(void)
+{
+  TestApplication application;
+
+  try
+  {
+    // Emit an empty HoverEvent
+    Integration::HoverEvent event;
+    application.ProcessEvent( event );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "!event.points.empty()", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliHoverInterrupted(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit another interrupted signal, our signal handler should not be called.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data, false );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Connect to root actor's hovered signal
+  SignalData rootData;
+  HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Vector2 actorCoordinates, rootCoordinates;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a motion signal
+  screenCoordinates.x = screenCoordinates.y = 11.0f;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a finished signal
+  screenCoordinates.x = screenCoordinates.y = 12.0f;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Finished, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Finished, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Finished, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a started signal where the actor is not present, will hit the root actor though
+  screenCoordinates.x = screenCoordinates.y = 200.0f;
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.hoverEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.hoverEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.hoverEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+  END_TEST;
+}
+
+int UtcDaliHoverInterruptedParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data, false );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Connect to root actor's hovered signal
+  SignalData rootData;
+  HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit an interrupted signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit another started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  rootData.Reset();
+
+  // Remove actor from Stage
+  Stage::GetCurrent().Remove( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit an interrupted signal, only root actor's signal should be called.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit another interrupted state, none of the signal's should be called.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, rootData.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverLeave(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Set actor to require leave events
+  actor.SetLeaveRequired( true );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a motion signal outside of actor, should be signalled with a Leave
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Another motion outside of actor, no signalling
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Another motion event inside actor, signalled with motion
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // We do not want to listen to leave events anymore
+  actor.SetLeaveRequired( false );
+
+  // Another motion event outside of actor, no signalling
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverLeaveParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data, false );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Connect to root actor's hovered signal
+  SignalData rootData;
+  HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+  // Set actor to require leave events
+  actor.SetLeaveRequired( true );
+  rootActor.SetLeaveRequired( true );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a motion signal outside of actor, should be signalled with a Leave
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Another motion outside of actor, only rootActor signalled
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Another motion event inside actor, signalled with motion
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // We do not want to listen to leave events of actor anymore
+  actor.SetLeaveRequired( false );
+
+  // Another motion event outside of root actor, only root signalled
+  Vector2 stageSize( Stage::GetCurrent().GetSize() );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( stageSize.width + 10.0f, stageSize.height + 10.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverActorBecomesInsensitive(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Change actor to insensitive
+  actor.SetSensitive( false );
+
+  // Emit a motion signal, signalled with an interrupted
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverActorBecomesInsensitiveParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data, false );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Connect to root actor's hovered signal
+  SignalData rootData;
+  HoverEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.HoveredSignal().Connect( &application, rootFunctor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, data.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Started, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoverEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.hoverEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Remove actor from Stage
+  Stage::GetCurrent().Remove( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Make root actor insensitive
+  rootActor.SetSensitive( false );
+
+  // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor)
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.hoverEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverMultipleLayers(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+
+  Layer layer1 ( Layer::New() );
+  layer1.SetSize(100.0f, 100.0f);
+  layer1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer1 );
+
+  Actor actor1 ( Actor::New() );
+  actor1.SetSize( 100.0f, 100.0f );
+  actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor1.SetZ( 1.0f ); // Should hit actor1 in this layer
+  layer1.Add( actor1 );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer1 and actor1
+  layer1.HoveredSignal().Connect( &application, functor );
+  actor1.HoveredSignal().Connect( &application, functor );
+
+  // Hit in hittable area, actor1 should be hit
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.hoveredActor == actor1 );
+  data.Reset();
+
+  // Make layer1 insensitive, nothing should be hit
+  layer1.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Make layer1 sensitive again, again actor1 will be hit
+  layer1.SetSensitive( true );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.hoveredActor == actor1 );
+  data.Reset();
+
+  // Make rootActor insensitive, nothing should be hit
+  rootActor.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Make rootActor sensitive
+  rootActor.SetSensitive( true );
+
+  // Add another layer
+  Layer layer2 ( Layer::New() );
+  layer2.SetSize(100.0f, 100.0f );
+  layer2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  layer2.SetZ( 10.0f ); // Should hit layer2 in this layer rather than actor2
+  Stage::GetCurrent().Add( layer2 );
+
+  Actor actor2 ( Actor::New() );
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  layer2.Add( actor2 );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer2 and actor2
+  layer2.HoveredSignal().Connect( &application, functor );
+  actor2.HoveredSignal().Connect( &application, functor );
+
+  // Emit an event, should hit layer2
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+  data.Reset();
+
+  // Make layer2 insensitive, should hit actor1
+  layer2.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.hoveredActor == actor1 );
+  data.Reset();
+
+  // Make layer2 sensitive again, should hit layer2
+  layer2.SetSensitive( true );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  //DALI_TEST_CHECK( data.hoveredActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+  data.Reset();
+
+  // Make layer2 invisible, render and notify
+  layer2.SetVisible( false );
+  application.SendNotification();
+  application.Render();
+
+  // Should hit actor1
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.hoveredActor == actor1 );
+  data.Reset();
+
+  // Make rootActor invisible, render and notify
+  rootActor.SetVisible( false );
+  application.SendNotification();
+  application.Render();
+
+  // Should not hit anything
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderTasks(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  // Create render task
+  Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+  RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+  renderTask.SetViewport( viewport );
+  renderTask.SetInputEnabled( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure renderTask actor can be hit too.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Disable input on renderTask, should not be hittable
+  renderTask.SetInputEnabled( false );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderTasksWithChildLayer(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.Add(layer);
+
+  // Create render task
+  Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+  RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+  renderTask.SetViewport( viewport );
+  renderTask.SetInputEnabled( true );
+  renderTask.SetSourceActor( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+  layer.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure renderTask actor can be hit too.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Disable input on renderTask, should not be hittable
+  renderTask.SetInputEnabled( false );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverOffscreenRenderTasks(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  // FrameBufferImage for offscreen RenderTask
+  FrameBufferImage frameBufferImage( FrameBufferImage::New( stageSize.width, stageSize.height, Pixel::RGBA8888 ) );
+
+  // Create an image actor to display the FrameBufferImage
+  ImageActor imageActor ( ImageActor::New( frameBufferImage ) );
+  imageActor.SetParentOrigin(ParentOrigin::CENTER);
+  imageActor.SetSize( stageSize.x, stageSize.y );
+  imageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+  stage.Add( imageActor );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add( actor );
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); // Ensure framebuffer connects
+
+  stage.GetRenderTaskList().GetTask( 0u ).SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
+
+  // Create a RenderTask
+  RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
+  renderTask.SetSourceActor( actor );
+  renderTask.SetTargetFrameBuffer( frameBufferImage );
+  renderTask.SetInputEnabled( true );
+
+  // Create another RenderTask
+  RenderTask renderTask2( stage.GetRenderTaskList().CreateTask() );
+  renderTask2.SetInputEnabled( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverMultipleRenderableActors(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  ImageActor parent = ImageActor::New();
+  parent.SetSize( 100.0f, 100.0f );
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(parent);
+
+  ImageActor actor = ImageActor::New();
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.SetSortModifier( 1.0f );
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  parent.HoveredSignal().Connect( &application, functor );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.hoveredActor );
+  END_TEST;
+}
+
+int UtcDaliHoverActorRemovedInSignal(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  RemoveActorFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Register for leave events
+  actor.SetLeaveRequired( true );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Re-add, render and notify
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Re-add actor back to stage, render and notify
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  // Emit another started event
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Completely delete the actor
+  actor.Reset();
+
+  // Emit event, should not crash and should not receive an event.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverActorSignalNotConsumed(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data, false );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliHoverActorUnStaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started signal
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Remove actor from stage
+  Stage::GetCurrent().Remove( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a move at the same point, we should not be signalled.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliHoverSystemOverlayActor(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core( application.GetCore() );
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // Create an actor and add it to the system overlay.
+  Actor systemActor = Actor::New();
+  systemActor.SetSize(100.0f, 100.0f);
+  systemActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add( systemActor );
+
+  // Create an actor and add it to the stage as per normal, same position and size as systemActor
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Connect to the hover signals.
+  SignalData data;
+  HoverEventFunctor functor( data );
+  systemActor.HoveredSignal().Connect( &application, functor );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a started signal, the system overlay is drawn last so is at the top, should hit the systemActor.
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( systemActor == data.hoveredActor );
+  END_TEST;
+}
+
+int UtcDaliHoverLeaveActorReadded(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  // Set actor to receive hover-events
+  actor.SetLeaveRequired( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit a started and motion
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 11.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Remove actor from stage and add again
+  stage.Remove( actor );
+  stage.Add( actor );
+
+  // Emit a motion within the actor's bounds
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 12.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a motion outside the actor's bounds
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Motion, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.hoverEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+
+int UtcDaliHoverStencilNonRenderableActor(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's hovered signal
+  SignalData data;
+  HoverEventFunctor functor( data );
+  actor.HoveredSignal().Connect( &application, functor );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event outside the stencil area but within the actor area, we should have a hit!
+  application.ProcessEvent( GenerateSingleHover( TouchPoint::Started, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Image.cpp b/automated-tests/src/dali/utc-Dali-Image.cpp
new file mode 100644 (file)
index 0000000..1c1ba77
--- /dev/null
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+
+using namespace Dali;
+
+void utc_dali_image_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_image_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+static const char* gTestImageFilename = "icon_wrt.png";
+
+namespace
+{
+void LoadBitmapResource(TestPlatformAbstraction& platform)
+{
+  Integration::ResourceRequest* request = platform.GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
+
+  if(request)
+  {
+    platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource);
+  }
+}
+
+}
+
+int UtcDaliImageDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Image::DownCast()");
+
+  Image image = ResourceImage::New(gTestImageFilename);
+
+  BaseHandle object(image);
+
+  Image image2 = Image::DownCast(object);
+  DALI_TEST_CHECK(image2);
+
+  Image image3 = DownCast< Image >(object);
+  DALI_TEST_CHECK(image3);
+
+  BaseHandle unInitializedObject;
+  Image image4 = Image::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!image4);
+
+  Image image5 = DownCast< Image >(unInitializedObject);
+  DALI_TEST_CHECK(!image5);
+  END_TEST;
+}
+
+int UtcDaliImageGetReleasePolicy(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliImageGetReleasePolicy");
+
+  Image image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED);
+
+  DALI_TEST_CHECK( image );
+
+  DALI_TEST_CHECK( Image::UNUSED == image.GetReleasePolicy() );
+
+  END_TEST;
+}
+
+int UtcDaliImageGetWidthHeight(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliImageGetWidthHeight - Image::GetWidth() & Image::GetHeight");
+
+  Vector2 testSize(8.0f, 16.0f);
+  application.GetPlatform().SetClosestImageSize(testSize);
+  Image image1 = ResourceImage::New(gTestImageFilename);
+  DALI_TEST_EQUALS( image1.GetWidth(), testSize.width, TEST_LOCATION );
+  DALI_TEST_EQUALS( image1.GetHeight(), testSize.height, TEST_LOCATION );
+
+  Image image2 = ResourceImage::New( gTestImageFilename, ImageDimensions(128, 256), FittingMode::SCALE_TO_FILL, SamplingMode::DEFAULT );
+  DALI_TEST_EQUALS( image2.GetWidth(), 128u, TEST_LOCATION );
+  DALI_TEST_EQUALS( image2.GetHeight(), 256u, TEST_LOCATION );
+
+  Image image3 = FrameBufferImage::New(16, 32);
+  DALI_TEST_EQUALS(image3.GetWidth(), 16u, TEST_LOCATION);
+  DALI_TEST_EQUALS(image3.GetHeight(), 32u, TEST_LOCATION);
+
+  TestNativeImagePointer nativeImage = TestNativeImage::New(32, 64);
+  Image image4 = NativeImage::New(*(nativeImage.Get()));
+  DALI_TEST_EQUALS(image4.GetWidth(), 32u, TEST_LOCATION);
+  DALI_TEST_EQUALS(image4.GetHeight(), 64u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+static bool SignalUploadedFlag = false;
+
+static void SignalUploadedHandler(Image image)
+{
+  tet_infoline("Received image uploaded signal");
+
+  SignalUploadedFlag = true;
+}
+
+int UtcDaliImageSignalUploaded(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  tet_infoline("UtcDaliImageSignalUploaded - Image::SignalUploaded()");
+
+  // set up image in fake platform abstraction
+  Vector2 testSize(80.0f, 80.0f);
+  platform.SetClosestImageSize(testSize);
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename);
+
+  // Load image
+  application.SendNotification();
+  application.Render(16);
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+  Integration::ResourceRequest* request = platform.GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
+
+  if(request)
+  {
+    platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource);
+  }
+  application.Render(16);
+  application.SendNotification();
+
+  image.UploadedSignal().Connect( SignalUploadedHandler );
+
+  Dali::ImageActor imageActor = ImageActor::New(image);
+  Stage::GetCurrent().Add(imageActor);
+  imageActor.SetSize(80, 80);
+  imageActor.SetVisible(true);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( SignalUploadedFlag == true );
+  SignalUploadedFlag = false;
+
+  image.Reload();
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 160, 160, 160, 160);
+
+  // image loading
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  //upload
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK( SignalUploadedFlag == true );
+  END_TEST;
+}
+
+int UtcDaliImageDiscard01(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliImageDiscard01 - no actors");
+
+  {
+    Image image = ResourceImage::New(gTestImageFilename);
+
+    // Load image
+    application.SendNotification();
+    application.Render(16);
+    std::vector<GLuint> ids;
+    ids.push_back( 23 );
+    application.GetGlAbstraction().SetNextTextureIds( ids );
+    TestPlatformAbstraction& platform = application.GetPlatform();
+    LoadBitmapResource( platform );
+    application.Render(16);
+    application.SendNotification();
+  } // Drop image handle
+
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  // Shouldn't have been sent to GL...
+  const std::vector<GLuint>& texIds = application.GetGlAbstraction().GetNextTextureIds();
+  DALI_TEST_CHECK( texIds.size() == 1 );
+  DALI_TEST_CHECK( texIds[0] == 23 );
+  END_TEST;
+}
+
+int UtcDaliImageDiscard02(void)
+{
+  TestApplication application;
+  application.GetGlAbstraction().EnableTextureCallTrace( true );
+  tet_infoline("UtcDaliImageDiscard02 - one actor, tests TextureCache::DiscardTexture");
+
+  {
+    {
+      ImageActor actor;
+      {
+        Image image = ResourceImage::New(gTestImageFilename, ImageDimensions( 40, 30 ) );
+        actor = ImageActor::New(image);
+        Stage::GetCurrent().Add(actor);
+
+        application.SendNotification();
+        application.Render(16);
+
+        std::vector<GLuint> ids;
+        ids.push_back( 23 );
+        application.GetGlAbstraction().SetNextTextureIds( ids );
+
+        TestPlatformAbstraction& platform = application.GetPlatform();
+        LoadBitmapResource( platform );
+        application.Render(16);
+        application.SendNotification();
+        DALI_TEST_CHECK( application.GetGlAbstraction().GetTextureTrace().FindMethod("BindTexture") );
+      } // lose image handle, actor should still keep one
+      application.SendNotification();
+      application.Render(16);
+
+      Stage::GetCurrent().Remove(actor);
+      application.SendNotification();
+      application.Render(16);
+    } // lose actor
+    application.SendNotification();
+    application.Render(16);
+  }
+
+  // Cleanup
+  application.SendNotification();
+  application.Render(16);
+  application.Render(16);
+  application.SendNotification();
+
+  // texture should have been removed:
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckTextureDeleted( 23 ));
+  END_TEST;
+}
+
+int UtcDaliImageDiscard03(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliImageDiscard03 - one actor, tests TextureCache::RemoveObserver");
+
+  const Vector2 closestImageSize( 1, 1);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Image image = ResourceImage::New(gTestImageFilename);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  LoadBitmapResource( platform );
+  application.Render(16);
+  application.SendNotification();
+  application.SendNotification();
+  application.Render(16);
+
+  const std::vector<GLuint>& texIds = application.GetGlAbstraction().GetNextTextureIds();
+  DALI_TEST_CHECK( texIds.size() == 0 );
+  const std::vector<GLuint>& boundTexIds = application.GetGlAbstraction().GetBoundTextures();
+  DALI_TEST_CHECK( boundTexIds[0] == 23 );
+
+  Stage::GetCurrent().Remove(actor);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16); // Should remove image renderer
+
+  END_TEST;
+}
+
+int UtcDaliImageContextLoss(void)
+{
+  TestApplication application; // Default config: DALI_DISCARDS_ALL_DATA
+
+  const Vector2 closestImageSize( 80, 80 );
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  platform.SetClosestImageSize(closestImageSize);
+
+  tet_infoline("UtcDaliImageContextLoss - Load image with LoadPolicy::Immediate, ReleasePolicy::Never, bitmap discard. Check that the image is re-requested on context regain\n");
+
+  Image image = ResourceImage::New("image.png", ResourceImage::IMMEDIATE, Image::NEVER);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading immediately
+
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  textureTrace.Enable(true);
+
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  LoadBitmapResource(platform);
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") );
+
+  textureTrace.Reset();
+  textureTrace.Enable(true);
+  platform.ResetTrace();
+  platform.EnableTrace(true);
+
+  // Lose & regain context (in render 'thread')
+  application.ResetContext();
+
+  application.GetCore().RecoverFromContextLoss(); // start the recovery process
+  application.SendNotification();
+
+  // Run update/render loop
+  application.Render(16);
+  application.SendNotification();
+
+  // Expect new load request
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  // Finish loading image
+  LoadBitmapResource(platform);
+  ids.clear();
+  ids.push_back( 57 );
+  glAbstraction.SetNextTextureIds(ids);
+
+  // Run update/render loop
+  application.Render(16);
+  application.SendNotification();
+
+  // Expect new GenTextures
+  DALI_TEST_CHECK( textureTrace.FindMethod("GenTextures") );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-ImageActor.cpp b/automated-tests/src/dali/utc-Dali-ImageActor.cpp
new file mode 100644 (file)
index 0000000..6c44479
--- /dev/null
@@ -0,0 +1,1653 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/bitmap.h>
+#include "dali-test-suite-utils/dali-test-suite-utils.h"
+
+using namespace Dali;
+
+static const char* TestImageFilename = "icon_wrt.png";
+
+void image_actor_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void image_actor_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliImageActorConstructorVoid(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor::ImageActor()");
+
+  ImageActor actor;
+
+  DALI_TEST_CHECK(!actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorDestructor(void)
+{
+  TestApplication application;
+
+  ImageActor* actor = new ImageActor();
+  delete actor;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+int UtcDaliImageActorNew01(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::New()");
+
+  Image image = ResourceImage::New(TestImageFilename);
+  ImageActor actor = ImageActor::New(image);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  DALI_TEST_CHECK(application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc));
+
+  DALI_TEST_CHECK(actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorNew02(void)
+{
+  TestApplication application;
+  tet_infoline("Negative test for Dali::ImageActor::New()");
+
+  Image image = ResourceImage::New("hopefully-this-image-file-does-not-exist");
+  ImageActor actor = ImageActor::New(image);
+
+  DALI_TEST_CHECK(actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor::DownCast()");
+
+  Image image = ResourceImage::New("IncorrectImageName");
+  ImageActor actor1 = ImageActor::New(image);
+  Actor anActor = Actor::New();
+  anActor.Add(actor1);
+
+  Actor child = anActor.GetChildAt(0);
+  ImageActor imageActor = DownCast< ImageActor >(child);
+
+  DALI_TEST_CHECK(imageActor);
+  END_TEST;
+}
+
+int UtcDaliImageActorDownCast2(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor::DownCast()");
+
+  Actor actor1 = Actor::New();
+  Actor anActor = Actor::New();
+  anActor.Add(actor1);
+
+  Actor child = anActor.GetChildAt(0);
+  ImageActor imageActor = ImageActor::DownCast(child);
+  DALI_TEST_CHECK(!imageActor);
+
+  Actor unInitialzedActor;
+  imageActor = ImageActor::DownCast( unInitialzedActor );
+  DALI_TEST_CHECK(!imageActor);
+  END_TEST;
+}
+
+int UtcDaliImageActorCopyConstructor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor::ImageActor(const ImageActor& )");
+
+  Image image = ResourceImage::New("IncorrectImageName");
+  ImageActor actor1 = ImageActor::New(image);
+
+  ImageActor actor2(actor1);
+  DALI_TEST_CHECK(actor2);
+  DALI_TEST_EQUALS( actor2, actor1, TEST_LOCATION );
+  DALI_TEST_EQUALS( actor2.GetImage(), image, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageActor9Patch(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor:: 9 patch api");
+
+  Image image = ResourceImage::New(TestImageFilename);
+  ImageActor actor = ImageActor::New(image);
+
+  actor.SetStyle(ImageActor::STYLE_NINE_PATCH);
+  Vector4 border(0.1,0.2,0.3,0.4);
+  actor.SetNinePatchBorder(border);
+
+  DALI_TEST_EQUALS( 0.1f, actor.GetNinePatchBorder().x, TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.2f, actor.GetNinePatchBorder().y, TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.3f, actor.GetNinePatchBorder().z, TEST_LOCATION );
+  DALI_TEST_EQUALS( 0.4f, actor.GetNinePatchBorder().w, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorPixelArea(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::UtcDaliImageActorPixelArea");
+
+  BufferImage img = BufferImage::New( 10, 10 );
+  ImageActor actor = ImageActor::New( img );
+
+  ImageActor::PixelArea area( 1, 2, 3, 4 );
+  actor.SetPixelArea( area );
+
+  DALI_TEST_EQUALS( 1, actor.GetPixelArea().x, TEST_LOCATION );
+  DALI_TEST_EQUALS( 2, actor.GetPixelArea().y, TEST_LOCATION );
+  DALI_TEST_EQUALS( 3, actor.GetPixelArea().width, TEST_LOCATION );
+  DALI_TEST_EQUALS( 4, actor.GetPixelArea().height, TEST_LOCATION );
+
+  ImageActor actor2 = ImageActor::New( img, ImageActor::PixelArea( 5, 6, 7, 8 ) );
+
+  DALI_TEST_EQUALS( 5, actor2.GetPixelArea().x, TEST_LOCATION );
+  DALI_TEST_EQUALS( 6, actor2.GetPixelArea().y, TEST_LOCATION );
+  DALI_TEST_EQUALS( 7, actor2.GetPixelArea().width, TEST_LOCATION );
+  DALI_TEST_EQUALS( 8, actor2.GetPixelArea().height, TEST_LOCATION );
+  END_TEST;
+}
+
+// Set a size that is too large on an Image with a shader that requires grid
+int UtcDaliImageActorSetSize01(void)
+{
+  TestApplication application;
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+
+  ShaderEffect effect = ShaderEffect::New( " ", " ", ShaderEffect::HINT_GRID );
+  actor.SetShaderEffect( effect );
+
+  const float INVALID_SIZE = float(1u<<31);
+  Vector3 vector( INVALID_SIZE, INVALID_SIZE, INVALID_SIZE );
+
+  DALI_TEST_CHECK(vector != actor.GetCurrentSize());
+
+  actor.SetSize(vector);
+  Stage::GetCurrent().Add(actor);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS(vector, actor.GetCurrentSize(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorGetCurrentSize01(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize");
+
+  Vector2 initialImageSize(100, 50);
+  BufferImage image = BufferImage::New( initialImageSize.width, initialImageSize.height );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION );
+
+  Vector2 size(200.0f, 200.0f);
+  actor.SetSize(size);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  size.x = 200.0f;
+  size.y = 200.0f;
+  actor.SetSize(size);
+  application.Render(8);
+
+  // Test when a pixel area is set
+  ImageActor::PixelArea area(0, 0, 10, 10);
+  actor.SetPixelArea(area);
+  application.Render(9);
+  // natural size is not used as setsize is called
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorGetCurrentSize02(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - Test that using an image resource sets the actor size with it's natural size immediately rather than on load");
+
+  Vector2 initialImageSize(100, 50);
+
+  application.GetPlatform().SetClosestImageSize(initialImageSize);
+
+  Image image = ResourceImage::New("image.jpg");
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  initialImageSize.width,initialImageSize.height, initialImageSize.width,initialImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), initialImageSize, TEST_LOCATION );
+
+  Vector2 size(200.0f, 200.0f);
+  actor.SetSize(size);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorGetCurrentSize03(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - Test that using an image resource with a requested size sets the actor size with it's nearest size immediately rather than on load");
+
+  const Vector2 closestImageSize( 80, 45);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Vector2 requestedSize( 40, 30 );
+  Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorGetCurrentSize04(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doesn't change a set actor size");
+
+  const Vector2 closestImageSize( 80, 45);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Vector2 requestedSize( 40, 30 );
+  Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  Vector2 size(200.0f, 200.0f);
+  actor.SetSize(size);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  // Load a different image
+
+  Vector2 image2ClosestSize = Vector2(240, 150); // The actual size image loader will return for the request below
+  application.GetPlatform().SetClosestImageSize(image2ClosestSize);
+
+  const Vector2 request2Size( 100, 100 );
+  Image image2 = ResourceImage::New("image.jpg", ImageDimensions( request2Size.x, request2Size.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  actor.SetImage(image2);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  // Ensure the actor size is kept
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  // Now complete the image load
+  req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height );
+
+  Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr2);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  // Ensure the actor size is kept
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), size, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorGetCurrentSize05(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete");
+
+  Vector2 closestImageSize( 80, 45);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Vector2 requestedSize( 40, 30 );
+  Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Load a different image
+
+  Vector2 image2ClosestSize = Vector2(240, 150);
+  application.GetPlatform().SetClosestImageSize(image2ClosestSize);
+
+  const Vector2 requestedSize2( 100, 100 );
+  Image image2 = ResourceImage::New("image.jpg", ImageDimensions( requestedSize2.x, requestedSize2.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  actor.SetImage(image2);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  // Ensure the actor size is kept
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize2, TEST_LOCATION );
+
+  // Now complete the image load
+  req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap2 = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap2->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  image2ClosestSize.width, image2ClosestSize.height, image2ClosestSize.width, image2ClosestSize.height );
+
+  Integration::ResourcePointer resourcePtr2(bitmap2); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr2);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+
+  // Ensure the actor size gets the new image's natural size
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorNaturalPixelAreaSize01(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete");
+
+//If an image is loaded without setting size, then the actor gets the natural size of the image
+//Setting the pixel area will change the actor size to match the pixel area
+//Setting the actor size will not change pixel area, and will cause the partial image to stretch
+//to the new size.
+//Clearing the pixel area will not change actor size, and the actor will show the whole image.
+
+
+  Vector2 closestImageSize( 80, 45);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Vector2 requestedSize( 40, 30 );
+  Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Set a pixel area on a naturally sized actor - expect the actor to take the
+  // pixel area as size
+  actor.SetPixelArea(ImageActor::PixelArea(0, 0, 30, 30));
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(30, 30), TEST_LOCATION );
+
+  // Set a size. Expect the partial image to stretch to fill the new size
+  actor.SetSize(100, 100);
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION );
+
+  // Clear the pixel area. Expect the whole image to be shown, filling the set size.
+  actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) );
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorNaturalPixelAreaSize02(void)
+{
+  TestApplication application;
+  tet_infoline("Positive test for Dali::ImageActor::GetCurrentSize - check a new image doens't change actor size until load complete");
+
+//If an image is loaded without setting size, then the actor gets the natural size of the image
+//Setting the pixel area will change the actor size to match the pixel area
+//Setting the actor size will not change pixel area, and will cause the partial image to stretch
+//to the new size.
+//Clearing the pixel area will not change actor size, and the actor will show the whole image.
+
+
+  Vector2 closestImageSize( 80, 45);
+  application.GetPlatform().SetClosestImageSize(closestImageSize);
+
+  Vector2 requestedSize( 40, 30 );
+  Image image = ResourceImage::New("image.jpg", ImageDimensions( requestedSize.x, requestedSize.y ), FittingMode::DEFAULT, SamplingMode::DEFAULT );
+  ImageActor actor = ImageActor::New( image );
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification(); // Flush update messages
+  application.Render();           // Process resource request
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Now complete the image load
+  Integration::ResourceRequest* req = application.GetPlatform().GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  closestImageSize.width, closestImageSize.height, closestImageSize.width, closestImageSize.height );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  application.GetPlatform().SetResourceLoaded(req->GetId(), req->GetType()->id, resourcePtr);
+  application.Render();           // Process LoadComplete
+  application.SendNotification(); // Process event messages
+  application.GetPlatform().DiscardRequest(); // Ensure load request is discarded
+  application.GetPlatform().ClearReadyResources(); //
+
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Set a pixel area on a naturally sized actor - expect the actor to take the
+  // pixel area as size
+  actor.SetPixelArea(ImageActor::PixelArea(0, 0, 30, 30));
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(30, 30), TEST_LOCATION );
+
+  // Clear the pixel area. Expect the whole image to be shown, changing actor size
+  actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) );
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+
+  // Set a size. Expect the partial image to stretch to fill the new size
+  actor.SetSize(100, 100);
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION );
+
+  // Set a pixel area, don't expect size to change
+  actor.SetPixelArea(ImageActor::PixelArea(0, 0, 40, 40));
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), Vector2(100, 100), TEST_LOCATION );
+
+  // Clearing pixel area should change actor size to image size
+  actor.SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+  actor.SetPixelArea( ImageActor::PixelArea( 0, 0, image.GetWidth(), image.GetHeight()) );
+  application.SendNotification(); // Process event messages
+  application.Render();           // Process LoadComplete
+  DALI_TEST_EQUALS( Vector2(actor.GetCurrentSize()), requestedSize, TEST_LOCATION );
+  END_TEST;
+}
+
+
+
+int UtcDaliImageActorDefaultProperties(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ImageActor DefaultProperties");
+
+  BufferImage img = BufferImage::New( 10, 10 );
+  ImageActor actor = ImageActor::New( img );
+
+  std::vector<Property::Index> indices;
+  indices.push_back(ImageActor::Property::PIXEL_AREA      );
+  indices.push_back(ImageActor::Property::STYLE           );
+  indices.push_back(ImageActor::Property::BORDER          );
+  indices.push_back(ImageActor::Property::IMAGE           );
+
+  DALI_TEST_CHECK(actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) );
+
+  for(std::vector<Property::Index>::iterator iter = indices.begin(); iter != indices.end(); ++iter)
+  {
+    DALI_TEST_CHECK( *iter == actor.GetPropertyIndex(actor.GetPropertyName(*iter)) );
+    DALI_TEST_CHECK( actor.IsPropertyWritable(*iter) );
+    DALI_TEST_CHECK( !actor.IsPropertyAnimatable(*iter) );
+    DALI_TEST_CHECK( actor.GetPropertyType(*iter) == actor.GetPropertyType(*iter) );  // just checking call succeeds
+  }
+
+  // set/get one of them
+  actor.SetPixelArea(ImageActor::PixelArea( 0, 0, 0, 0 ));
+
+  ImageActor::PixelArea area( 1, 2, 3, 4 );
+  actor.SetProperty(ImageActor::Property::PIXEL_AREA, Property::Value(Rect<int>(area)));
+
+  DALI_TEST_CHECK(Property::RECTANGLE == actor.GetPropertyType(ImageActor::Property::PIXEL_AREA));
+
+  Property::Value v = actor.GetProperty(ImageActor::Property::PIXEL_AREA);
+
+  DALI_TEST_CHECK(v.Get<Rect<int> >() == area);
+
+  END_TEST;
+}
+
+int UtcDaliImageActorUseImageAlpha01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()");
+
+  BufferImage image = BufferImage::New( 100, 50 );
+  ImageActor actor = ImageActor::New( image );
+  actor.SetBlendMode( BlendingMode::ON );
+  actor.SetSize(100, 50);
+  application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorUseImageAlpha02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()");
+
+  BufferImage image = BufferImage::New( 100, 50 );
+  ImageActor actor = ImageActor::New( image );
+  actor.SetBlendMode( BlendingMode::OFF );
+  actor.SetSize(100, 50);
+  application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( BlendEnabled( callTrace), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorUseImageAlpha03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()");
+
+  BufferImage image = BufferImage::New( 100, 50 );
+  ImageActor actor = ImageActor::New( image );
+  actor.SetBlendMode( BlendingMode::AUTO );
+  actor.SetColor(Vector4(1.0, 1.0, 1.0, 0.5));
+  actor.SetSize(100, 50);
+  application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorUseImageAlpha04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()");
+
+  FrameBufferImage image = FrameBufferImage::New( 100, 50, Pixel::RGBA8888 );
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+  task.SetTargetFrameBuffer( image ); // To ensure frame buffer is connected
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  application.SendNotification();
+  application.Render(0);
+
+  ImageActor actor = ImageActor::New( image );
+  application.SendNotification();
+  application.Render(0);
+
+  actor.SetBlendMode( BlendingMode::ON );
+  actor.SetColor(Vector4(1.0, 1.0, 1.0, 1.0));
+  actor.SetSize(100, 50);
+  application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( BlendEnabled( callTrace), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorUseImageAlpha05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::RenderableActor::SetUseImageAlpha()");
+
+  BufferImage image = BufferImage::New( 100, 50, Pixel::RGB888 );
+  ImageActor actor = ImageActor::New( image );
+  actor.SetBlendMode( BlendingMode::AUTO );
+  actor.SetColor(Vector4(1.0, 1.0, 1.0, 1.0));
+  actor.SetSize(100, 50);
+  application.GetGlAbstraction().EnableCullFaceCallTrace(true); // For Enable(GL_BLEND)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  const TraceCallStack& callTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  DALI_TEST_EQUALS( BlendDisabled( callTrace ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( BlendEnabled( callTrace), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageGetStyle(void)
+{
+  TestApplication application;
+
+  Image image = ResourceImage::New(TestImageFilename);
+  ImageActor actor = ImageActor::New(image);
+
+  actor.SetStyle(ImageActor::STYLE_NINE_PATCH);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( ImageActor::STYLE_NINE_PATCH, actor.GetStyle(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageSetNinePatchBorder(void)
+{
+  TestApplication application;
+
+  Image image = ResourceImage::New(TestImageFilename);
+  ImageActor actor = ImageActor::New(image);
+
+  actor.SetStyle(ImageActor::STYLE_NINE_PATCH);
+  actor.SetNinePatchBorder(Vector4( 1.0f, 2.0f, 3.0f, 4.0f));
+
+  DALI_TEST_EQUALS( 1.0f, actor.GetNinePatchBorder().x, TEST_LOCATION );
+  DALI_TEST_EQUALS( 2.0f, actor.GetNinePatchBorder().y, TEST_LOCATION );
+  DALI_TEST_EQUALS( 3.0f, actor.GetNinePatchBorder().z, TEST_LOCATION );
+  DALI_TEST_EQUALS( 4.0f, actor.GetNinePatchBorder().w, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorNewNull(void)
+{
+  TestApplication application;
+
+  ImageActor actor = ImageActor::New(Image());
+
+  DALI_TEST_CHECK(actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorNewNullWithArea(void)
+{
+  TestApplication application;
+
+  ImageActor::PixelArea area( 1, 2, 3, 4 );
+
+  ImageActor actor = ImageActor::New(Image(), area);
+
+  DALI_TEST_CHECK(actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorSetImage(void)
+{
+  TestApplication application;
+
+  ImageActor actor = ImageActor::New(Image());
+
+  DALI_TEST_CHECK(actor);
+
+  actor.SetImage( Image() );
+
+  DALI_TEST_CHECK(!actor.GetImage());
+  END_TEST;
+}
+
+int UtcDaliImageActorPropertyIndices(void)
+{
+  TestApplication application;
+  Actor basicActor = Actor::New();
+  ImageActor imageActor = ImageActor::New();
+
+  Property::IndexContainer indices;
+  imageActor.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() );
+  DALI_TEST_EQUALS( indices.Size(), imageActor.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorImageProperty(void)
+{
+  TestApplication application;
+  Image image = ResourceImage::New( "MY_PATH" );
+  ImageActor imageActor = ImageActor::New( image );
+
+  Stage::GetCurrent().Add( imageActor );
+  application.SendNotification();
+  application.Render();
+
+  Property::Value imageProperty = imageActor.GetProperty( ImageActor::Property::IMAGE );
+  Property::Map* imageMap = imageProperty.GetMap();
+  DALI_TEST_CHECK( imageMap != NULL );
+  DALI_TEST_CHECK( NULL != imageMap->Find( "filename" ) );
+  DALI_TEST_EQUALS( (*imageMap)[ "filename" ].Get< std::string >(), "MY_PATH", TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorNinePatch01(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  tet_infoline("Test the successful loading of a nine-patch image\n");
+
+  platform.SetClosestImageSize(Vector2(4, 4));
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  4,4,4,4 );
+  memset( pixels, 0, 64 );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+
+  Image ninePatchImage = ResourceImage::New( "blah.#.png" );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  ImageActor imageActor = ImageActor::New( ninePatchImage );
+  DALI_TEST_CHECK( imageActor );
+  Stage::GetCurrent().Add( imageActor );
+
+  drawTrace.Reset();
+  textureTrace.Reset();
+  drawTrace.Enable(true);
+  textureTrace.Enable(true);
+  glAbstraction.ClearBoundTextures();
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+  typedef std::vector<GLuint> TexVec;
+  const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+  DALI_TEST_CHECK( textures.size() > 0 );
+  if( textures.size() > 0 )
+  {
+    DALI_TEST_EQUALS( textures[0], 23u, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorNinePatch02(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  tet_infoline("Test the failed loading of a nine-patch image\n");
+
+  platform.SetClosestImageSize(Vector2(0, 0));
+  Integration::ResourcePointer resourcePtr;
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+
+  Image ninePatchImage = ResourceImage::New( "blah.#.png" );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  ImageActor imageActor = ImageActor::New( ninePatchImage );
+  DALI_TEST_CHECK( imageActor );
+  Stage::GetCurrent().Add( imageActor );
+
+  drawTrace.Reset();
+  textureTrace.Reset();
+  drawTrace.Enable(true);
+  textureTrace.Enable(true);
+  glAbstraction.ClearBoundTextures();
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was drawn.
+  DALI_TEST_CHECK( ! drawTrace.FindMethod( "DrawArrays" ) );
+  typedef std::vector<GLuint> TexVec;
+  const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+  DALI_TEST_CHECK( textures.size() == 0u );
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorNinePatch03(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  tet_infoline("Test the successful loading of a nine-patch image added using ImageActor::SetImage()\n");
+
+  platform.SetClosestImageSize(Vector2(4, 4));
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Integration::PixelBuffer* pixels = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  4,4,4,4 );
+  memset( pixels, 0, 64 );
+
+  Integration::ResourcePointer resourcePtr(bitmap); // reference it
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+
+  Image ninePatchImage = ResourceImage::New( "blah.#.png" );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  ImageActor imageActor = ImageActor::New();
+  DALI_TEST_CHECK( imageActor );
+  Stage::GetCurrent().Add( imageActor );
+
+  imageActor.SetImage( ninePatchImage );
+
+  drawTrace.Reset();
+  textureTrace.Reset();
+  drawTrace.Enable(true);
+  textureTrace.Enable(true);
+  glAbstraction.ClearBoundTextures();
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( drawTrace.FindMethod( "DrawArrays" ) );
+  typedef std::vector<GLuint> TexVec;
+  const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+  DALI_TEST_CHECK( textures.size() > 0 );
+  if( textures.size() > 0 )
+  {
+    DALI_TEST_EQUALS( textures[0], 23u, TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliImageActorNinePatch04(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+  TraceCallStack& textureTrace = glAbstraction.GetTextureTrace();
+  TraceCallStack& drawTrace = glAbstraction.GetDrawTrace();
+
+  tet_infoline("Test the failed loading of a nine-patch image using ImageActor::SetImage()\n");
+
+  platform.SetClosestImageSize(Vector2(0, 0));
+  Integration::ResourcePointer resourcePtr;
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+
+  Image ninePatchImage = ResourceImage::New( "blah.#.png" );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  ImageActor imageActor = ImageActor::New();
+  DALI_TEST_CHECK( imageActor );
+  Stage::GetCurrent().Add( imageActor );
+
+  imageActor.SetImage( ninePatchImage );
+
+  drawTrace.Reset();
+  textureTrace.Reset();
+  drawTrace.Enable(true);
+  textureTrace.Enable(true);
+  glAbstraction.ClearBoundTextures();
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  glAbstraction.SetNextTextureIds( ids );
+
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was drawn.
+  DALI_TEST_CHECK( ! drawTrace.FindMethod( "DrawArrays" ) );
+  typedef std::vector<GLuint> TexVec;
+  const TexVec& textures = glAbstraction.GetBoundTextures(GL_TEXTURE0);
+  DALI_TEST_CHECK( textures.size() == 0u );
+
+  END_TEST;
+}
+
+int UtcDaliImageActorGetNaturalSize(void)
+{
+  TestApplication application;
+
+  // Standard image
+  BufferImage img = BufferImage::New( 10, 10 );
+  ImageActor actor = ImageActor::New( img );
+
+  DALI_TEST_CHECK( actor.GetNaturalSize().GetVectorXY() == Vector2( 10, 10 ) );
+
+  // Pixel area set
+  ImageActor::PixelArea area( 1, 2, 3, 4 );
+  actor.SetPixelArea( area );
+
+  DALI_TEST_CHECK( actor.GetNaturalSize().GetVectorXY() == Vector2( 3, 4 ) );
+
+  END_TEST;
+}
+
+int UtcDaliImageActorGetSortModifier(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::GetSortModifier()");
+
+  ImageActor actor = ImageActor::New();
+  Stage::GetCurrent().Add(actor);
+
+  DALI_TEST_EQUALS(actor.GetSortModifier(), 0.0f, TEST_LOCATION);
+
+  Stage::GetCurrent().Remove(actor);
+  END_TEST;
+}
+
+int UtcDaliImageActorSetGetBlendMode(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::SetBlendMode() / Dali::ImageActor::GetBlendMode()");
+
+  ImageActor actor = ImageActor::New();
+
+  actor.SetBlendMode( BlendingMode::OFF );
+  DALI_TEST_CHECK( BlendingMode::OFF == actor.GetBlendMode() );
+
+  actor.SetBlendMode( BlendingMode::AUTO );
+  DALI_TEST_CHECK( BlendingMode::AUTO == actor.GetBlendMode() );
+
+  actor.SetBlendMode( BlendingMode::ON );
+  DALI_TEST_CHECK( BlendingMode::ON == actor.GetBlendMode() );
+  END_TEST;
+}
+
+int UtcDaliImageActorSetGetBlendFunc(void)
+{
+  TestApplication application;
+  TestGlAbstraction& glAbstraction = application.GetGlAbstraction();
+
+  tet_infoline("Testing Dali::ImageActor::UtcDaliImageActorSetGetBlendFunc()");
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+  Stage::GetCurrent().Add( actor );
+  application.SendNotification();
+  application.Render();
+
+  // Test the defaults as documented int blending.h
+  {
+    BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO );
+    actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+    DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA,           srcFactorRgb,    TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_ALPHA, destFactorRgb,   TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE,                 srcFactorAlpha,  TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_ALPHA, destFactorAlpha, TEST_LOCATION );
+  }
+
+  // Set to non-default values
+  actor.SetBlendFunc( BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE, BlendingFactor::ONE_MINUS_SRC_COLOR, BlendingFactor::SRC_ALPHA_SATURATE );
+
+  // Test that Set was successful
+  {
+    BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO );
+    actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorRgb,    TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE,  destFactorRgb,   TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_SRC_COLOR, srcFactorAlpha,  TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::SRC_ALPHA_SATURATE,  destFactorAlpha, TEST_LOCATION );
+  }
+
+  // Render & check GL commands
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE,  glAbstraction.GetLastBlendFuncDstRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_SRC_COLOR, glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_SRC_ALPHA_SATURATE,  glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION );
+
+  // Set using separate alpha settings
+  actor.SetBlendFunc( BlendingFactor::CONSTANT_COLOR, BlendingFactor::ONE_MINUS_CONSTANT_COLOR,
+                      BlendingFactor::CONSTANT_ALPHA, BlendingFactor::ONE_MINUS_CONSTANT_ALPHA );
+
+  // Test that Set was successful
+  {
+    BlendingFactor::Type srcFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorRgb( BlendingFactor::ZERO );
+    BlendingFactor::Type srcFactorAlpha( BlendingFactor::ZERO );
+    BlendingFactor::Type destFactorAlpha( BlendingFactor::ZERO );
+    actor.GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+    DALI_TEST_EQUALS( BlendingFactor::CONSTANT_COLOR,            srcFactorRgb,    TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_COLOR,  destFactorRgb,   TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::CONSTANT_ALPHA,            srcFactorAlpha,  TEST_LOCATION );
+    DALI_TEST_EQUALS( BlendingFactor::ONE_MINUS_CONSTANT_ALPHA,  destFactorAlpha, TEST_LOCATION );
+  }
+
+  // Render & check GL commands
+  application.SendNotification();
+  application.Render();
+  DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_COLOR,           glAbstraction.GetLastBlendFuncSrcRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_COLOR, glAbstraction.GetLastBlendFuncDstRgb(),   TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_CONSTANT_ALPHA,           glAbstraction.GetLastBlendFuncSrcAlpha(), TEST_LOCATION );
+  DALI_TEST_EQUALS( (GLenum)GL_ONE_MINUS_CONSTANT_ALPHA, glAbstraction.GetLastBlendFuncDstAlpha(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorSetGetAlpha(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::SetGetAlpha()");
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+  Stage::GetCurrent().Add( actor );
+  application.SendNotification();
+  application.Render();
+
+  // use the image alpha on actor
+  actor.SetBlendMode(BlendingMode::ON);
+
+  // Test that Set was successful
+  DALI_TEST_EQUALS( BlendingMode::ON, actor.GetBlendMode(), TEST_LOCATION );
+
+  // Now test that it can be set to false
+  actor.SetBlendMode(BlendingMode::OFF);
+  DALI_TEST_EQUALS(BlendingMode::OFF, actor.GetBlendMode(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliImageActorSetGetFilterModes(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::SetFilterMode() / Dali::ImageActor::GetFilterMode()");
+
+  ImageActor actor = ImageActor::New();
+
+  FilterMode::Type minifyFilter = FilterMode::NEAREST;
+  FilterMode::Type magnifyFilter = FilterMode::NEAREST;
+
+  // Default test
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::DEFAULT == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::DEFAULT == magnifyFilter );
+
+  // Default/Default
+  actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::DEFAULT == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::DEFAULT == magnifyFilter );
+
+  // Nearest/Nearest
+  actor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST );
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::NEAREST == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::NEAREST == magnifyFilter );
+
+  // Linear/Linear
+  actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR );
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::LINEAR == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::LINEAR == magnifyFilter );
+
+  // Nearest/Linear
+  actor.SetFilterMode( FilterMode::NEAREST, FilterMode::LINEAR );
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::NEAREST == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::LINEAR == magnifyFilter );
+
+  // Linear/Nearest
+  actor.SetFilterMode( FilterMode::LINEAR, FilterMode::NEAREST );
+  actor.GetFilterMode( minifyFilter, magnifyFilter );
+  DALI_TEST_CHECK( FilterMode::LINEAR == minifyFilter );
+  DALI_TEST_CHECK( FilterMode::NEAREST == magnifyFilter );
+
+  END_TEST;
+}
+
+int UtcDaliImageActorSetFilterMode(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::SetFilterMode()");
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetParentOrigin(ParentOrigin::CENTER);
+  actor.SetAnchorPoint(AnchorPoint::CENTER);
+
+  Stage::GetCurrent().Add(actor);
+
+  /**************************************************************/
+
+  // Default/Default
+  TraceCallStack& texParameterTrace = application.GetGlAbstraction().GetTexParameterTrace();
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  std::stringstream out;
+
+  // Verify actor gl state
+
+  // There are two calls to TexParameteri when the texture is first created
+  // Texture mag filter is not called as the first time set it uses the system default
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 3, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(2, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+
+  // Default/Default
+  texParameterTrace = application.GetGlAbstraction().GetTexParameterTrace();
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+
+  // Should not make any calls when settings are the same
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 0, TEST_LOCATION);
+
+  /**************************************************************/
+
+  // Nearest/Nearest
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::NEAREST, FilterMode::NEAREST );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_NEAREST;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+
+  // Linear/Linear
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::LINEAR, FilterMode::LINEAR );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 2, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MAG_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(1, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+
+  /**************************************************************/
+
+  // Nearest/Linear
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::NEAREST, FilterMode::LINEAR );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+
+  // Default/Default
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::DEFAULT, FilterMode::DEFAULT );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+
+  // None/None
+  texParameterTrace.Reset();
+  texParameterTrace.Enable( true );
+
+  actor.SetFilterMode( FilterMode::NONE, FilterMode::NONE );
+
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  texParameterTrace.Enable( false );
+
+  // Verify actor gl state
+  DALI_TEST_EQUALS( texParameterTrace.CountMethod( "TexParameteri" ), 1, TEST_LOCATION);
+
+  out.str("");
+  out << GL_TEXTURE_2D << ", " << GL_TEXTURE_MIN_FILTER << ", " << GL_NEAREST_MIPMAP_LINEAR;
+  DALI_TEST_EQUALS( texParameterTrace.TestMethodAndParams(0, "TexParameteri", out.str()), true, TEST_LOCATION);
+
+  /**************************************************************/
+
+  Stage::GetCurrent().Remove(actor);
+
+  END_TEST;
+}
+
+int UtcDaliImageActorSetShaderEffect(void)
+{
+  TestApplication application;
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+  Stage::GetCurrent().Add( actor );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  application.GetGlAbstraction().EnableShaderCallTrace( true );
+
+  const std::string vertexShader = "UtcDaliImageActorSetShaderEffect-VertexSource";
+  const std::string fragmentShader = "UtcDaliImageActorSetShaderEffect-FragmentSource";
+  ShaderEffect effect = ShaderEffect::New(vertexShader, fragmentShader );
+  DALI_TEST_CHECK( effect != actor.GetShaderEffect() );
+
+  actor.SetShaderEffect( effect );
+  DALI_TEST_CHECK( effect == actor.GetShaderEffect() );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled();
+  DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION );
+
+  std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 );
+  DALI_TEST_EQUALS( vertexShader,
+                    actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION );
+  std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 );
+  DALI_TEST_EQUALS( fragmentShader,
+                    actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliImageActorGetShaderEffect(void)
+{
+  TestApplication application;
+  ImageActor actor = ImageActor::New();
+
+  ShaderEffect effect = ShaderEffect::New("UtcDaliImageActorGetShaderEffect-VertexSource", "UtcDaliImageActorGetShaderEffect-FragmentSource" );
+  actor.SetShaderEffect(effect);
+
+  DALI_TEST_CHECK(effect == actor.GetShaderEffect());
+  END_TEST;
+}
+
+int UtcDaliImageActorRemoveShaderEffect01(void)
+{
+  TestApplication application;
+  ImageActor actor = ImageActor::New();
+
+  ShaderEffect defaultEffect = actor.GetShaderEffect();
+
+  ShaderEffect effect = ShaderEffect::New("UtcDaliImageActorRemoveShaderEffect-VertexSource", "UtcDaliImageActorRemoveShaderEffect-FragmentSource" );
+  actor.SetShaderEffect(effect);
+
+  DALI_TEST_CHECK(effect == actor.GetShaderEffect());
+
+  actor.RemoveShaderEffect();
+
+  DALI_TEST_CHECK(defaultEffect == actor.GetShaderEffect());
+  END_TEST;
+}
+
+int UtcDaliImageActorRemoveShaderEffect02(void)
+{
+  TestApplication application;
+  ImageActor actor = ImageActor::New();
+
+  ShaderEffect defaultEffect = actor.GetShaderEffect();
+
+  actor.RemoveShaderEffect();
+
+  DALI_TEST_CHECK(defaultEffect == actor.GetShaderEffect());
+  END_TEST;
+}
+
+int UtcDaliSetShaderEffectRecursively(void)
+{
+  TestApplication application;
+  /**
+   * create a tree
+   *                 actor1
+   *           actor2       actor4
+   *       actor3 imageactor1
+   * imageactor2
+   */
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor1 = ImageActor::New( img );
+  Actor actor2 = Actor::New();
+  actor1.Add( actor2 );
+  Actor actor3 = Actor::New();
+  actor2.Add( actor3 );
+  ImageActor imageactor1 = ImageActor::New( img );
+  actor2.Add( imageactor1 );
+  ImageActor imageactor2 = ImageActor::New( img );
+  actor3.Add( imageactor2 );
+  Actor actor4 = Actor::New();
+  actor1.Add( actor4 );
+  Stage::GetCurrent().Add( actor1 );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+  GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  application.GetGlAbstraction().EnableShaderCallTrace( true );
+
+  const std::string vertexShader = "UtcDaliImageActorSetShaderEffect-VertexSource";
+  const std::string fragmentShader = "UtcDaliImageActorSetShaderEffect-FragmentSource";
+  // test with empty effect
+  ShaderEffect effect;
+  SetShaderEffectRecursively( actor1, effect );
+
+  effect = ShaderEffect::New(vertexShader, fragmentShader );
+
+  DALI_TEST_CHECK( effect != actor1.GetShaderEffect() );
+  DALI_TEST_CHECK( effect != imageactor1.GetShaderEffect() );
+  DALI_TEST_CHECK( effect != imageactor2.GetShaderEffect() );
+
+  SetShaderEffectRecursively( actor1, effect );
+  DALI_TEST_CHECK( effect == imageactor1.GetShaderEffect() );
+  DALI_TEST_CHECK( effect == imageactor2.GetShaderEffect() );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled();
+  DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION );
+
+  std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 );
+  DALI_TEST_EQUALS( vertexShader,
+                    actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION );
+  std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 );
+  DALI_TEST_EQUALS( fragmentShader,
+                    actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION );
+
+  // remove from one that does not have shader
+  RemoveShaderEffectRecursively( actor4 );
+
+  // remove partially
+  RemoveShaderEffectRecursively( actor3 );
+  DALI_TEST_CHECK( effect == imageactor1.GetShaderEffect() );
+  DALI_TEST_CHECK( effect != imageactor2.GetShaderEffect() );
+
+  // test with empty actor just to check it does not crash
+  Actor empty;
+  SetShaderEffectRecursively( empty, effect );
+  RemoveShaderEffectRecursively( empty );
+
+  // test with actor with no children just to check it does not crash
+  Actor loner = Actor::New();
+  Stage::GetCurrent().Add( loner );
+  SetShaderEffectRecursively( loner, effect );
+  RemoveShaderEffectRecursively( loner );
+
+  END_TEST;
+}
+
+int UtcDaliImageActorTestClearCache(void)
+{
+  // Testing the framebuffer state caching in frame-buffer-state-caching.cpp
+  TestApplication application;
+
+  tet_infoline("Testing Dali::ImageActor::ClearCache()");
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor actor = ImageActor::New( img );
+
+  actor.SetParentOrigin(ParentOrigin::CENTER);
+  actor.SetAnchorPoint(AnchorPoint::CENTER);
+
+  Stage::GetCurrent().Add(actor);
+
+  /**************************************************************/
+  // Flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  // There should be a single call to Clear
+  DALI_TEST_EQUALS( application.GetGlAbstraction().GetClearCountCalled() , 1u, TEST_LOCATION );
+
+  // the last set clear mask should be COLOR, DEPTH & STENCIL which occurs at the start of each frame
+  GLbitfield mask = application.GetGlAbstraction().GetLastClearMask();
+  DALI_TEST_CHECK( mask & GL_DEPTH_BUFFER_BIT );
+  DALI_TEST_CHECK( mask & GL_STENCIL_BUFFER_BIT );
+  DALI_TEST_CHECK( mask & GL_COLOR_BUFFER_BIT );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp b/automated-tests/src/dali/utc-Dali-IntrusivePtr.cpp
new file mode 100644 (file)
index 0000000..23c7880
--- /dev/null
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+const int REPEAT = 1000;
+
+size_t g_creationCount = 0;
+size_t g_destructionCount = 0;
+size_t g_creationCountSubclass = 0;
+size_t g_destructionCountSubclass = 0;
+size_t g_creationCountUnrelated = 0;
+size_t g_destructionCountUnrelated = 0;
+
+class Counted : public RefObject
+{
+public:
+  Counted()
+  {
+    ++g_creationCount;
+  }
+  ~Counted()
+  {
+    ++g_destructionCount;
+  }
+};
+
+class CountedSubclass : public Counted
+{
+public:
+  CountedSubclass()
+  {
+    ++g_creationCountSubclass;
+  }
+  ~CountedSubclass()
+  {
+    ++g_destructionCountSubclass;
+  }
+};
+
+class UnrelatedCounted : public RefObject
+{
+public:
+  UnrelatedCounted()
+  {
+    ++g_creationCountUnrelated;
+  }
+  ~UnrelatedCounted()
+  {
+    ++g_destructionCountUnrelated;
+  }
+};
+}
+
+/**
+ * Test that a default constructed pointer is null and harmless.
+ */
+int UtcDaliIntrusivePtrIntrusivePtr(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr()" );
+
+  g_creationCount = g_destructionCount = 0;
+
+  IntrusivePtr<Counted> counted;
+  DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+  // Test the pointer is null
+  DALI_TEST_EQUALS( counted.Get(), (Counted*) 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( &(*counted), (Counted*) 0, TEST_LOCATION );
+  // Check destruction of the null smart pointer does nothing:
+  counted = IntrusivePtr<Counted>();
+  DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrIntrusivePtrTP(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(T*)" );
+
+  g_creationCount = g_destructionCount = 0;
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+  counted = 0;
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+// Class is too simple for a negative case to be created: int UtcDaliIntrusiveIntrusivePtrTN(void)
+
+int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrUP(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(IntrusivePtr<U> const &)" );
+
+  g_creationCount = g_destructionCount = g_creationCountSubclass = g_destructionCountSubclass = 0;
+
+  IntrusivePtr<CountedSubclass> countedSubclass( new CountedSubclass );
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_creationCountSubclass, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCountSubclass, 0u, TEST_LOCATION );
+
+  IntrusivePtr<Counted> counted( countedSubclass );
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION );
+
+  // Make loads more references:
+  std::vector< IntrusivePtr<Counted> > intrusivePtrs;
+  for( int i = 0; i < REPEAT; ++i )
+  {
+    intrusivePtrs.push_back( IntrusivePtr<Counted>( countedSubclass ) );
+  }
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2 + REPEAT, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_creationCountSubclass, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+// The negative version of this test would fail at compile time:
+// int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrUN(void)
+
+int UtcDaliIntrusivePtrIntrusivePtrIntrusivePtrP(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::IntrusivePtr(IntrusivePtr const &)" );
+
+  // Pass a pointer to a constructed second object:
+  // Pass a pointer to null:
+
+  g_creationCount = g_destructionCount = 0;
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION );
+
+  IntrusivePtr<Counted> counted2( counted );
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( counted.Get(), counted2.Get(), TEST_LOCATION );
+
+  // Make loads more references:
+  std::vector< IntrusivePtr<Counted> > intrusivePtrs;
+  for( int i = 0; i < REPEAT; ++i )
+  {
+    intrusivePtrs.push_back( IntrusivePtr<Counted>( counted ) );
+  }
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2 + REPEAT, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+
+  intrusivePtrs.clear();
+
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 0u, TEST_LOCATION );
+
+  counted.Reset();
+  DALI_TEST_EQUALS( counted2->ReferenceCount(), 1, TEST_LOCATION );
+  counted2.Reset();
+
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrGetP(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::Get()" );
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_CHECK( counted.Get() != 0 );
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrGetN(void)
+{
+  tet_infoline( "Testing Dali::IntrusivePtr::Get()" );
+
+  g_creationCount = 0;
+
+  IntrusivePtr<Counted> counted( 0 );
+  DALI_TEST_CHECK( counted.Get() == 0 );
+  DALI_TEST_EQUALS( g_creationCount, 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrArrowOperatorP(void)
+{
+  tet_infoline( "Positive Test for Dali::IntrusivePtr::operator->()" );
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_CHECK( (counted.operator->()) != 0 );
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrArrowOperatorN(void)
+{
+  tet_infoline( "Negative Test for Dali::IntrusivePtr::operator->()" );
+
+  IntrusivePtr<Counted> counted;
+  DALI_TEST_CHECK( (counted.operator->()) == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrIndirectionOperatorP(void)
+{
+  tet_infoline( "Positive Test for Dali::IntrusivePtr::operator*()" );
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_CHECK( &(counted.operator*()) != 0 );
+  DALI_TEST_EQUALS( (*counted).ReferenceCount(), 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrIndirectionOperatorN(void)
+{
+  tet_infoline( "Negative Test for Dali::IntrusivePtr::operator*()" );
+
+  IntrusivePtr<Counted> counted;
+  DALI_TEST_CHECK( &(counted.operator*()) == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrResetP(void)
+{
+  tet_infoline( "Positive Test for Dali::IntrusivePtr::Reset()" );
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_CHECK( counted.Get() != 0 );
+  counted.Reset();
+  DALI_TEST_CHECK( counted.Get() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrResetN(void)
+{
+  tet_infoline( "Negative Test for Dali::IntrusivePtr::Reset()" );
+
+  IntrusivePtr<Counted> counted;
+  Counted* firstGet = counted.Get();
+  counted.Reset();
+  DALI_TEST_EQUALS( counted.Get(), firstGet, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrResetTP(void)
+{
+  tet_infoline( "Positive Test for Dali::IntrusivePtr::Reset(T*)" );
+
+  g_creationCount = g_destructionCount = 0;
+
+  IntrusivePtr<Counted> counted( new Counted );
+
+  IntrusivePtr<Counted> counted2( new Counted );
+
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( counted2->ReferenceCount(), 1, TEST_LOCATION );
+
+  counted.Reset( counted2.Get() );
+
+  DALI_TEST_EQUALS( counted->ReferenceCount(), 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( counted2->ReferenceCount(), 2, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( counted.Get(), counted2.Get(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( g_creationCount, 2u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION );
+
+  counted2.Reset( (Counted*) 0 );
+  counted.Reset( counted2.Get() );
+  DALI_TEST_EQUALS( g_destructionCount, 2u, TEST_LOCATION );
+
+  // Check that reseting nulls is harmless:
+  counted2.Reset( counted.Get() );
+  counted.Reset( counted2.Get() );
+
+  DALI_TEST_EQUALS( g_destructionCount, 2u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliIntrusivePtrResetTN(void)
+{
+  tet_infoline( "Negative Test for Dali::IntrusivePtr::Reset(T*)" );
+
+  g_creationCount = g_destructionCount = 0;
+
+  IntrusivePtr<Counted> counted( new Counted );
+
+  counted.Reset( (Counted*) 0 );
+
+  DALI_TEST_EQUALS( counted.Get(), (Counted*) 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_creationCount, 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( g_destructionCount, 1u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliIntrusivePtrOperatorBooleanTypeP(void)
+{
+  tet_infoline( "Positive Test for Dali::IntrusivePtr::operator Booleantype()" );
+
+  IntrusivePtr<Counted> counted( new Counted );
+  DALI_TEST_CHECK( counted.operator BooleanType() != 0 );
+  DALI_TEST_CHECK( counted );
+
+  typedef void (IntrusivePtr<Counted>::*BoolIdiomFunc)() const;
+  BoolIdiomFunc func = static_cast<BoolIdiomFunc>( counted.operator BooleanType() );
+  ((counted).*func)(); // purely for test coverage
+
+  counted.Reset();
+  DALI_TEST_CHECK( counted.operator BooleanType() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliIntrusivePtrOperatorBooleanTypeN(void)
+{
+  tet_infoline( "Negative Test for Dali::IntrusivePtr::operator Booleantype()" );
+
+  IntrusivePtr<Counted> counted;
+  DALI_TEST_CHECK( counted.operator BooleanType() == 0 );
+  DALI_TEST_CHECK( !counted );
+  END_TEST;
+}
+
+/** Equality of two different types*/
+int UtcDaliIntrusivePtrOperatorEqualTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T, U)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator==( counted1, countedSubclass1 ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator==( counted2, countedSubclass2 ), true, TEST_LOCATION );
+  END_TEST;
+}
+
+/** Inequality of two different types*/
+int UtcDaliIntrusivePtrOperatorNotEqualTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T, U)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator!=( counted1, countedSubclass1 ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator!=( counted2, countedSubclass2 ), false, TEST_LOCATION );
+  END_TEST;
+}
+
+/** Equality of two different types where right hand side is a raw pointer */
+int UtcDaliIntrusivePtrOperatorEqualRightPointerTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T, U*)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator==( counted1, countedSubclass1.Get() ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator==( counted2, countedSubclass2.Get() ), true, TEST_LOCATION );
+  END_TEST;
+}
+
+/** Inequality of two different types where the right hand side is a raw pointer */
+int UtcDaliIntrusivePtrOperatorNotEqualRightPointerTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T, U*)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator!=( counted1, countedSubclass1.Get() ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator!=( counted2, countedSubclass2.Get() ), false, TEST_LOCATION );
+  END_TEST;
+}
+
+/** Equality of two different types where left hand side is a raw pointer */
+int UtcDaliIntrusivePtrOperatorEqualLeftPointerTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator ==(T*, U)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator==( counted1.Get(), countedSubclass1 ), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator==( counted2.Get(), countedSubclass2 ), true, TEST_LOCATION );
+  END_TEST;
+}
+
+/** Inequality of two different types where the left hand side is a raw pointer */
+int UtcDaliIntrusivePtrOperatorNotEqualLeftPointerTU(void)
+{
+  tet_infoline( "Test for Dali::IntrusivePtr::operator !=(T*, U)" );
+
+  IntrusivePtr<Counted> counted1( new Counted );
+  IntrusivePtr<CountedSubclass> countedSubclass1( new CountedSubclass );
+  IntrusivePtr<CountedSubclass> countedSubclass2( new CountedSubclass );
+  IntrusivePtr<Counted> counted2( countedSubclass2 );
+
+  DALI_TEST_EQUALS( operator!=( counted1.Get(), countedSubclass1 ), true, TEST_LOCATION );
+  DALI_TEST_EQUALS( operator!=( counted2.Get(), countedSubclass2 ), false, TEST_LOCATION );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-KeyEvent.cpp b/automated-tests/src/dali/utc-Dali-KeyEvent.cpp
new file mode 100644 (file)
index 0000000..0ffb592
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/key-event-integ.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_key_event_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_key_event_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+// Key Event Test references
+const static int SHIFT_MODIFIER  = 0x1;
+const static int CTRL_MODIFIER  = 0x2;
+const static int ALT_MODIFIER  = 0x4;
+const static int SHIFT_AND_CTRL_MODIFIER  = SHIFT_MODIFIER | CTRL_MODIFIER;
+const static int SHIFT_AND_ALT_MODIFIER  = SHIFT_MODIFIER | ALT_MODIFIER;
+const static int CTRL_AND_ALT_MODIFIER  = CTRL_MODIFIER | ALT_MODIFIER;
+
+const static char* TEST_STRING_1 = "alpha";
+
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    receivedKeyEvent.keyModifier = 0;
+    receivedKeyEvent.keyPressedName.clear();
+    receivedKeyEvent.keyPressed.clear();
+
+    keyedActor.Reset();
+  }
+
+  bool functorCalled;
+  KeyEvent receivedKeyEvent;
+  Actor keyedActor;
+};
+
+// Functor that sets the data when called
+struct KeyEventReceivedFunctor
+{
+  KeyEventReceivedFunctor( SignalData& data ) : signalData( data ) { }
+
+  bool operator()( Actor actor, const KeyEvent& keyEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.receivedKeyEvent = keyEvent;
+    signalData.keyedActor = actor;
+
+    return true;
+  }
+
+  SignalData& signalData;
+};
+
+} // anon namespace
+
+int UtcDaliKeyEventConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event(TEST_STRING_1,"i", 99, SHIFT_MODIFIER, 0, KeyEvent::Down);  // set name to test, key string to i and modifier to shift
+
+  DALI_TEST_EQUALS(TEST_STRING_1, event.keyPressedName, TEST_LOCATION); // check key name
+  DALI_TEST_EQUALS("i", event.keyPressed, TEST_LOCATION); // check key string
+  DALI_TEST_EQUALS(99, event.keyCode, TEST_LOCATION); // check keyCode
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(KeyEvent::Down, event.state, TEST_LOCATION); // check state
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventIsShiftModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event;
+  DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION);
+
+  event.keyModifier = SHIFT_MODIFIER; // Set to Shift Modifier
+
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsShiftModifier(), TEST_LOCATION); // check IsShiftModifier
+
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventIsCtrlModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event;
+  DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION);
+
+  event.keyModifier = CTRL_MODIFIER; // Set to Ctrl Modifier
+
+  DALI_TEST_EQUALS(CTRL_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier(), TEST_LOCATION); // check IsCtrlModifier
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventIsAltModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event;
+  DALI_TEST_EQUALS(0, event.keyModifier, TEST_LOCATION);
+
+  event.keyModifier = ALT_MODIFIER; // Set to Alt Modifier
+
+  DALI_TEST_EQUALS(ALT_MODIFIER, event.keyModifier, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsAltModifier(), TEST_LOCATION);  // IsAltModifier
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliKeyEventIsNotShiftModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, CTRL_MODIFIER, 0, KeyEvent::Down);
+
+  DALI_TEST_EQUALS(CTRL_MODIFIER, event.keyModifier, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsShiftModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliKeyEventIsNotCtrlModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, ALT_MODIFIER, 0, KeyEvent::Up);
+
+  DALI_TEST_EQUALS(ALT_MODIFIER, event.keyModifier, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliKeyEventIsNotAltModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, SHIFT_MODIFIER, 0, KeyEvent::Up);
+
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.keyModifier, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsAltModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventANDModifer(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down);
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier() & event.IsShiftModifier(), TEST_LOCATION);
+
+  event.keyModifier = SHIFT_MODIFIER;
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsShiftModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventORModifer(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down);
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier() | event.IsAltModifier(), TEST_LOCATION);
+
+  event.keyModifier = SHIFT_MODIFIER;
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsAltModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliKeyEventState(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  KeyEvent event("i","i", 0, SHIFT_AND_CTRL_MODIFIER, 0, KeyEvent::Down);
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier() | event.IsAltModifier(), TEST_LOCATION);
+
+  event.keyModifier = SHIFT_MODIFIER;
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier() & event.IsAltModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliIntegrationKeyEvent(void)
+{
+  TestApplication application;
+
+  {
+    Integration::KeyEvent keyEvent;
+    DALI_TEST_EQUALS( keyEvent.type, Integration::Event::Key, TEST_LOCATION );
+    DALI_TEST_CHECK( keyEvent.keyName == std::string() );
+    DALI_TEST_CHECK( keyEvent.keyString == std::string() );
+    DALI_TEST_EQUALS( keyEvent.keyCode, -1, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.keyModifier, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.time, 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.state, Integration::KeyEvent::Down, TEST_LOCATION);
+  }
+
+  {
+    const std::string keyName("keyName");
+    const std::string keyString("keyString");
+    const int keyCode(333);
+    const int keyModifier(312);
+    const unsigned long timeStamp(132);
+    const Integration::KeyEvent::State keyState(Integration::KeyEvent::Up);
+
+    Integration::KeyEvent keyEvent(keyName, keyString, keyCode, keyModifier, timeStamp, keyState);
+    DALI_TEST_EQUALS( keyEvent.type, Integration::Event::Key, TEST_LOCATION );
+    DALI_TEST_CHECK( keyEvent.keyName == keyName );
+    DALI_TEST_CHECK( keyEvent.keyString == keyString );
+    DALI_TEST_EQUALS( keyEvent.keyCode, keyCode, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.keyModifier, keyModifier, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.time, timeStamp, TEST_LOCATION );
+    DALI_TEST_EQUALS( keyEvent.state, keyState, TEST_LOCATION);
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Layer.cpp b/automated-tests/src/dali/utc-Dali-Layer.cpp
new file mode 100644 (file)
index 0000000..ee8c51d
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+
+#include <dali/public-api/dali-core.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void layer_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void layer_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliLayerNew(void)
+{
+  TestApplication application;
+  Layer layer = Layer::New();
+
+  DALI_TEST_CHECK(layer);
+  END_TEST;
+}
+
+int UtcDaliLayerDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Layer::DownCast()");
+
+  Layer actor1 = Layer::New();
+  Actor anActor = Actor::New();
+  anActor.Add(actor1);
+
+  Actor child = anActor.GetChildAt(0);
+  Layer layer = DownCast< Layer >(child);
+
+  DALI_TEST_CHECK(layer);
+  END_TEST;
+}
+
+int UtcDaliLayerDownCast2(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Layer::DownCast()");
+
+  Actor actor1 = Actor::New();
+  Actor anActor = Actor::New();
+  anActor.Add(actor1);
+
+  Actor child = anActor.GetChildAt(0);
+  Layer layer = DownCast< Layer >(child);
+  DALI_TEST_CHECK(!layer);
+
+  Actor unInitialzedActor;
+  layer = Layer::DownCast( unInitialzedActor );
+  DALI_TEST_CHECK(!layer);
+  END_TEST;
+}
+
+
+int UtcDaliLayerGetDepth(void)
+{
+  tet_infoline("Testing Dali::Layer::GetDepth()");
+  TestApplication application;
+  Layer layer1 = Layer::New();
+  Layer layer2 = Layer::New();
+
+  // layers are not on stage
+  DALI_TEST_EQUALS(layer1.GetDepth(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION);
+
+  // root depth is 0
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_EQUALS(root.GetDepth(), 0u, TEST_LOCATION);
+
+  Stage::GetCurrent().Add(layer1);
+  Stage::GetCurrent().Add(layer2);
+
+  DALI_TEST_EQUALS(  root.GetDepth(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLayerRaise(void)
+{
+  tet_infoline("Testing Dali::Layer::Raise()");
+  TestApplication application;
+  Layer layer1 = Layer::New();
+  Layer layer2 = Layer::New();
+
+  Stage::GetCurrent().Add(layer1);
+  Stage::GetCurrent().Add(layer2);
+  DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION);
+
+  layer1.Raise();
+  DALI_TEST_EQUALS(layer1.GetDepth(), 2u, TEST_LOCATION);
+
+  // get root
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_EQUALS(  root.GetDepth(), 0u, TEST_LOCATION);
+  root.Raise();
+  DALI_TEST_EQUALS(  root.GetDepth(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer1.GetDepth(), 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLayerLower(void)
+{
+  tet_infoline("Testing Dali::Layer::Lower()");
+  TestApplication application;
+  Layer layer1 = Layer::New();
+  Layer layer2 = Layer::New();
+
+  Stage::GetCurrent().Add(layer1);
+  Stage::GetCurrent().Add(layer2);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION);
+
+  layer2.Lower();
+  DALI_TEST_EQUALS(layer2.GetDepth(), 1u, TEST_LOCATION);
+
+  // get root
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  root.Lower();
+  DALI_TEST_EQUALS(  root.GetDepth(), 0u, TEST_LOCATION);
+  layer2.Lower();
+  DALI_TEST_EQUALS(  root.GetDepth(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 0u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLayerRaiseToTop(void)
+{
+  tet_infoline("Testing Dali::Layer::RaiseToTop()");
+  TestApplication application;
+  Layer layer1 = Layer::New();
+  Layer layer2 = Layer::New();
+  Layer layer3 = Layer::New();
+
+  Stage::GetCurrent().Add(layer1);
+  Stage::GetCurrent().Add(layer2);
+  Stage::GetCurrent().Add(layer3);
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+
+  DALI_TEST_EQUALS(  root.GetDepth(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer3.GetDepth(), 3u, TEST_LOCATION);
+
+  layer1.RaiseToTop();
+  DALI_TEST_EQUALS(layer1.GetDepth(), 3u, TEST_LOCATION);
+
+  root.RaiseToTop();
+  DALI_TEST_EQUALS(  root.GetDepth(), 3u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLayerLowerToBottom(void)
+{
+  tet_infoline("Testing Dali::Layer::LowerToBottom()");
+  TestApplication application;
+  Layer layer1 = Layer::New();
+  Layer layer2 = Layer::New();
+  Layer layer3 = Layer::New();
+
+  Stage::GetCurrent().Add(layer1);
+  Stage::GetCurrent().Add(layer2);
+  Stage::GetCurrent().Add(layer3);
+
+  DALI_TEST_EQUALS(layer1.GetDepth(), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer2.GetDepth(), 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(layer3.GetDepth(), 3u, TEST_LOCATION);
+
+  layer3.LowerToBottom();
+  DALI_TEST_EQUALS(layer3.GetDepth(), 0u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLayerSetClipping(void)
+{
+  tet_infoline("Testing Dali::Layer::SetClipping()");
+  TestApplication application;
+
+  Layer layer = Layer::New();
+  DALI_TEST_CHECK(!layer.IsClipping());
+
+  layer.SetClipping(true);
+  DALI_TEST_CHECK(layer.IsClipping());
+  END_TEST;
+}
+
+int UtcDaliLayerIsClipping(void)
+{
+  tet_infoline("Testing Dali::Layer::IsClipping()");
+  TestApplication application;
+
+  Layer layer = Layer::New();
+  DALI_TEST_CHECK(!layer.IsClipping());
+  END_TEST;
+}
+
+int UtcDaliLayerSetClippingBox(void)
+{
+  tet_infoline("Testing Dali::Layer::SetClippingBox()");
+  TestApplication application;
+
+  ClippingBox testBox(5,6, 77,83);
+
+  Layer layer = Layer::New();
+  DALI_TEST_CHECK(layer.GetClippingBox() != testBox);
+
+  layer.SetClippingBox(5,6, 77,83);
+  DALI_TEST_CHECK(layer.GetClippingBox() == testBox);
+  END_TEST;
+}
+
+int UtcDaliLayerGetClippingBox(void)
+{
+  tet_infoline("Testing Dali::Layer::GetClippingBox()");
+  TestApplication application;
+
+  Layer layer = Layer::New();
+  DALI_TEST_CHECK(layer.GetClippingBox() == ClippingBox(0,0,0,0));
+  END_TEST;
+}
+
+static int gTestSortFunctionCalled;
+
+static float TestSortFunction(const Vector3& /*position*/)
+{
+  ++gTestSortFunctionCalled;
+  return 0.0f;
+}
+
+int UtcDaliLayerSetSortFunction(void)
+{
+  tet_infoline("Testing Dali::Layer::SetSortFunction()");
+  TestApplication application;
+  BufferImage img = BufferImage::New( 1,1 );
+  // create two transparent actors so there is something to sort
+  ImageActor actor = ImageActor::New( img );
+  ImageActor actor2 = ImageActor::New( img );
+  actor.SetSize(1,1);
+  actor.SetColor( Vector4(1, 1, 1, 0.5f ) ); // 50% transparent
+  actor2.SetSize(1,1);
+  actor2.SetColor( Vector4(1, 1, 1, 0.5f ) ); // 50% transparent
+
+  // add to stage
+  Stage::GetCurrent().Add( actor );
+  Stage::GetCurrent().Add( actor2 );
+
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  gTestSortFunctionCalled = 0;
+  root.SetSortFunction(TestSortFunction);
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( gTestSortFunctionCalled > 0 );
+  END_TEST;
+}
+
+
+int UtcDaliLayerRaiseAbove(void)
+{
+  tet_infoline("Testing Dali::Layer::RaiseAbove()");
+  TestApplication application;
+  Layer layer = Layer::New();
+  // try to raise above root layer
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  layer.RaiseAbove( root );
+  // layer depth is zero as its not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  // add to stage
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseAbove( root );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+  root.RaiseAbove( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  layer.RaiseAbove( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+
+  // make another layer on the stage
+  Layer layer2 = Layer::New();
+  Stage::GetCurrent().Add( layer2 );
+  layer.RaiseAbove( layer2 );
+  DALI_TEST_GREATER( layer.GetDepth(), layer2.GetDepth(), TEST_LOCATION );
+  layer2.RaiseAbove( layer );
+  DALI_TEST_GREATER( layer2.GetDepth(), layer.GetDepth(), TEST_LOCATION );
+  root.RaiseAbove( layer2 );
+  DALI_TEST_GREATER( root.GetDepth(), layer2.GetDepth(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerRaiseBelow(void)
+{
+  tet_infoline("Testing Dali::Layer::RaiseBelow()");
+  TestApplication application;
+  Layer layer = Layer::New();
+  // try to lower below root layer
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  layer.LowerBelow( root );
+  // layer depth is zero as its not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  // add to stage
+  Stage::GetCurrent().Add( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+  layer.LowerBelow( root );
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  root.LowerBelow( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+  layer.LowerBelow( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+
+  // make another layer on the stage
+  Layer layer2 = Layer::New();
+  Stage::GetCurrent().Add( layer2 );
+  layer.LowerBelow( layer2 );
+  DALI_TEST_GREATER( layer2.GetDepth(), layer.GetDepth(), TEST_LOCATION );
+  layer2.LowerBelow( layer );
+  DALI_TEST_GREATER( layer.GetDepth(), layer2.GetDepth(), TEST_LOCATION );
+  root.LowerBelow( layer2 );
+  DALI_TEST_GREATER( layer2.GetDepth(), root.GetDepth(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerMoveAbove(void)
+{
+  tet_infoline("Testing Dali::Layer::MoveAbove()");
+  TestApplication application;
+  Layer layer = Layer::New();
+  // try to raise above root layer
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  layer.MoveAbove( root );
+  // layer depth is zero as its not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  root.MoveAbove( layer );
+  // root depth is zero as layer is not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  // add to stage
+  Stage::GetCurrent().Add( layer );
+  layer.MoveAbove( root );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION );
+  root.MoveAbove( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION );
+
+  // make another layer on the stage
+  Layer layer2 = Layer::New();
+  Stage::GetCurrent().Add( layer2 );
+  layer.MoveAbove( layer2 );
+  DALI_TEST_EQUALS( layer.GetDepth(), layer2.GetDepth() + 1u, TEST_LOCATION );
+  layer2.MoveAbove( root );
+  DALI_TEST_EQUALS( layer2.GetDepth(), root.GetDepth() + 1u, TEST_LOCATION );
+  root.MoveAbove( layer );
+  DALI_TEST_EQUALS( root.GetDepth(), layer.GetDepth() + 1u, TEST_LOCATION );
+
+  Layer layer3 = Layer::New();
+  Stage::GetCurrent().Add( layer3 );
+  DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION );
+  root.MoveAbove( layer3 );
+  DALI_TEST_EQUALS( root.GetDepth(), 3u, TEST_LOCATION );
+  DALI_TEST_EQUALS( layer3.GetDepth(), 2u, TEST_LOCATION );
+  DALI_TEST_EQUALS( Stage::GetCurrent().GetLayer( 0 ).GetDepth(), 0u, TEST_LOCATION );
+  layer3.MoveAbove( Stage::GetCurrent().GetLayer( 0 ) );
+  DALI_TEST_EQUALS( layer3.GetDepth(), 1u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerMoveBelow(void)
+{
+  tet_infoline("Testing Dali::Layer::MoveBelow()");
+  TestApplication application;
+  Layer layer = Layer::New();
+  // try to raise above root layer
+  Layer root = Stage::GetCurrent().GetLayer( 0 );
+  layer.MoveBelow( root );
+  // layer depth is zero as its not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  root.MoveBelow( layer );
+  // root depth is zero as layer is not on stage
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  // add to stage
+  Stage::GetCurrent().Add( layer );
+  layer.MoveBelow( root );
+  DALI_TEST_EQUALS( layer.GetDepth(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( root.GetDepth(), 1u, TEST_LOCATION );
+  root.MoveBelow( layer );
+  DALI_TEST_EQUALS( layer.GetDepth(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( root.GetDepth(), 0u, TEST_LOCATION );
+
+  // make another layer on the stage
+  Layer layer2 = Layer::New();
+  Stage::GetCurrent().Add( layer2 );
+  layer.MoveBelow( layer2 );
+  DALI_TEST_EQUALS( layer.GetDepth(), layer2.GetDepth() - 1u, TEST_LOCATION );
+  layer2.MoveBelow( root );
+  DALI_TEST_EQUALS( layer2.GetDepth(), root.GetDepth() - 1u, TEST_LOCATION );
+  root.MoveBelow( layer );
+  DALI_TEST_EQUALS( root.GetDepth(), layer.GetDepth() - 1u, TEST_LOCATION );
+
+  Layer layer3 = Layer::New();
+  Stage::GetCurrent().Add( layer3 );
+  DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION );
+  root.MoveBelow( layer3 );
+  DALI_TEST_EQUALS( root.GetDepth(), 2u, TEST_LOCATION );
+  DALI_TEST_EQUALS( layer3.GetDepth(), 3u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerDefaultProperties(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Layer DefaultProperties");
+
+  Layer actor = Layer::New();
+
+  std::vector<Property::Index> indices;
+  indices.push_back(Layer::Property::CLIPPING_ENABLE);
+  indices.push_back(Layer::Property::CLIPPING_BOX);
+  indices.push_back(Layer::Property::BEHAVIOR);
+
+  DALI_TEST_CHECK(actor.GetPropertyCount() == ( Actor::New().GetPropertyCount() + indices.size() ) );
+
+  for(std::vector<Property::Index>::iterator iter = indices.begin(); iter != indices.end(); ++iter)
+  {
+    DALI_TEST_CHECK( *iter == actor.GetPropertyIndex(actor.GetPropertyName(*iter)) );
+    DALI_TEST_CHECK( actor.IsPropertyWritable(*iter) );
+    DALI_TEST_CHECK( !actor.IsPropertyAnimatable(*iter) );
+    DALI_TEST_CHECK( actor.GetPropertyType(*iter) == actor.GetPropertyType(*iter) );  // just checking call succeeds
+  }
+
+  // set/get one of them
+  actor.SetClippingBox(0,0,0,0);
+
+  ClippingBox testBox(10,20,30,40);
+  DALI_TEST_CHECK(actor.GetClippingBox() != testBox);
+
+  actor.SetProperty(Layer::Property::CLIPPING_BOX, Property::Value(Rect<int>(testBox)));
+
+  DALI_TEST_CHECK(Property::RECTANGLE == actor.GetPropertyType(Layer::Property::CLIPPING_BOX));
+
+  Property::Value v = actor.GetProperty(Layer::Property::CLIPPING_BOX);
+
+  DALI_TEST_CHECK(v.Get<Rect<int> >() == testBox);
+
+  // set the same boundaries, but through a clipping box object
+  actor.SetClippingBox( testBox );
+
+  DALI_TEST_CHECK( actor.GetClippingBox() == testBox );
+
+
+  Property::Value behavior = actor.GetProperty(Layer::Property::BEHAVIOR);
+  DALI_TEST_CHECK( std::strcmp( behavior.Get<std::string>().c_str(), "LAYER_2D") );
+
+  END_TEST;
+}
+
+int UtcDaliLayerSetDepthTestDisabled(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Layer::SetDepthTestDisabled() ");
+
+  Layer actor = Layer::New();
+  DALI_TEST_CHECK( actor.IsDepthTestDisabled() );
+
+  actor.SetBehavior( Layer::LAYER_3D );
+  DALI_TEST_CHECK( !actor.IsDepthTestDisabled() );
+
+  actor.SetDepthTestDisabled( true );
+  DALI_TEST_CHECK( actor.IsDepthTestDisabled() );
+  END_TEST;
+}
+
+int UtcDaliLayerCreateDestroy(void)
+{
+  tet_infoline("Testing Dali::Layer::CreateDestroy() ");
+  Layer* layer = new Layer;
+  DALI_TEST_CHECK( layer );
+  delete layer;
+  END_TEST;
+}
+
+int UtcDaliLayerPropertyIndices(void)
+{
+  TestApplication application;
+  Actor basicActor = Actor::New();
+  Layer layer = Layer::New();
+
+  Property::IndexContainer indices;
+  layer.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() > basicActor.GetPropertyCount() );
+  DALI_TEST_EQUALS( indices.Size(), layer.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerTouchConsumed(void)
+{
+  TestApplication application;
+  Layer layer = Layer::New();
+
+  DALI_TEST_EQUALS( layer.IsTouchConsumed(), false, TEST_LOCATION );
+  layer.SetTouchConsumed( true );
+  DALI_TEST_EQUALS( layer.IsTouchConsumed(), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerHoverConsumed(void)
+{
+  TestApplication application;
+  Layer layer = Layer::New();
+
+  DALI_TEST_EQUALS( layer.IsHoverConsumed(), false, TEST_LOCATION );
+  layer.SetHoverConsumed( true );
+  DALI_TEST_EQUALS( layer.IsHoverConsumed(), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerClippingGLCalls(void)
+{
+  TestApplication application;
+  const TestGlAbstraction::ScissorParams& glScissorParams( application.GetGlAbstraction().GetScissorParams() );
+  Stage stage( Stage::GetCurrent() );
+
+  ClippingBox testBox( 5, 6, 77, 83 );
+  Layer layer = Stage::GetCurrent().GetRootLayer();
+  layer.SetClipping( true );
+  layer.SetClippingBox( testBox );
+
+  // Add at least one renderable actor so the GL calls are actually made
+  BufferImage img = BufferImage::New( 1,1 );
+  Actor actor = ImageActor::New( img );
+  stage.Add( actor );
+
+  // flush the queue and render once
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( testBox.x, glScissorParams.x, TEST_LOCATION );
+  DALI_TEST_EQUALS( testBox.y, stage.GetSize().height - glScissorParams.y - testBox.height, TEST_LOCATION ); // GL Coordinates are from bottom left
+  DALI_TEST_EQUALS( testBox.width, glScissorParams.width, TEST_LOCATION );
+  DALI_TEST_EQUALS( testBox.height, glScissorParams.height, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLayerBehaviour(void)
+{
+  TestApplication application;
+  Layer layer = Layer::New();
+
+  DALI_TEST_EQUALS( layer.GetBehavior(), Dali::Layer::LAYER_2D, TEST_LOCATION );
+  layer.SetBehavior( Dali::Layer::LAYER_3D );
+  DALI_TEST_EQUALS( layer.GetBehavior(), Dali::Layer::LAYER_3D, TEST_LOCATION );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp b/automated-tests/src/dali/utc-Dali-LocklessBuffer.cpp
new file mode 100644 (file)
index 0000000..46f1dc2
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/lockless-buffer.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+static bool ReadTest(Integration::LocklessBuffer& buf, const unsigned char exp[], size_t size)
+{
+  const unsigned char *res = buf.Read();
+  for (size_t i=0; i<size; ++i, ++res)
+  {
+    if(*res != exp[i])
+    {
+      tet_printf("FAIL: expected 0x%X result 0x%X\n", (int)exp[i], (int)*res);
+      return false;
+    }
+  }
+  return true;
+}
+} // anonymous namespace
+
+
+// Simple write - read test
+int UtcDaliLocklessBufferWriteRead01(void)
+{
+  Integration::LocklessBuffer buf(10);
+  unsigned char data[10];
+
+  for( unsigned char i=0; i<10; ++i )
+  {
+    data[i]=i;
+  }
+
+  buf.Write( &data[0], 10 );
+
+  if( ReadTest( buf, data, 10 ) )
+  {
+    tet_result(TET_PASS);
+  }
+  else
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+// test multiple writes, one read
+int UtcDaliLocklessBufferMultipleWrites01(void)
+{
+  Integration::LocklessBuffer buf(10);
+  unsigned char data[10];
+
+  for( unsigned char i=0; i<10; ++i )
+  {
+    data[i]=i;
+  }
+
+  // Write to a buffer
+  buf.Write( &data[0], 10 );
+
+  for (unsigned char i=0; i<10; ++i)
+  {
+      data[i]=i+4;
+  }
+
+  // No reads from buffer, so will overwrite contents of same buffer
+  buf.Write( &data[0], 10 );
+
+  if( ReadTest(buf, data, 10) )
+  {
+    tet_result(TET_PASS);
+  }
+  else
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
+
+// Simple API test
+int UtcDaliLocklessBufferGetSize01(void)
+{
+  Integration::LocklessBuffer buf(10);
+  unsigned int size = buf.GetSize();
+  if( size == 10 )
+  {
+    tet_result(TET_PASS);
+  }
+  else
+  {
+    tet_result(TET_FAIL);
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-LongPressGesture.cpp b/automated-tests/src/dali/utc-Dali-LongPressGesture.cpp
new file mode 100644 (file)
index 0000000..b870366
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_long_press_gesture_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_long_press_gesture_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+// Positive test case for a method
+int UtcDaliLongPressGestureConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  LongPressGesture gesture( Gesture::Started );
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::LongPress, gesture.type, TEST_LOCATION);
+
+  // Test Copy constructor
+  gesture.numberOfTouches = 5u;
+
+  LongPressGesture gesture2(gesture);
+  DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::LongPress, gesture2.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureAssignment(void)
+{
+  // Test Assignment operator
+  LongPressGesture gesture( Gesture::Started );
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::LongPress, gesture.type, TEST_LOCATION);
+
+  gesture.numberOfTouches = 5u;
+
+  LongPressGesture gesture2( Gesture::Finished );
+  DALI_TEST_EQUALS(Gesture::Finished, gesture2.state, TEST_LOCATION);
+  gesture2 = gesture;
+  DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::LongPress, gesture2.type, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDynamicAllocation(void)
+{
+  LongPressGesture* gesture = new LongPressGesture( Gesture::Started );
+  DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::LongPress, gesture->type, TEST_LOCATION);
+  delete gesture;
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-LongPressGestureDetector.cpp
new file mode 100644 (file)
index 0000000..6c7ba81
--- /dev/null
@@ -0,0 +1,1454 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/long-press-gesture-event.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+#include <test-touch-utils.h>
+
+using namespace Dali;
+
+void utc_dali_long_press_gesture_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_long_press_gesture_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled( false ),
+    voidFunctorCalled( false ),
+    receivedGesture( Gesture::Clear ),
+    pressedActor()
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+    voidFunctorCalled = false;
+
+    receivedGesture.numberOfTouches = 0u;
+    receivedGesture.screenPoint = Vector2(0.0f, 0.0f);
+    receivedGesture.localPoint = Vector2(0.0f, 0.0f);
+
+    pressedActor.Reset();
+  }
+
+  bool functorCalled;
+  bool voidFunctorCalled;
+  LongPressGesture receivedGesture;
+  Actor pressedActor;
+};
+
+// Functor that sets the data when called
+struct GestureReceivedFunctor
+{
+  GestureReceivedFunctor(SignalData& data) : signalData(data) { }
+
+  void operator()(Actor actor, const LongPressGesture& longPress)
+  {
+    signalData.functorCalled = true;
+    signalData.receivedGesture = longPress;
+    signalData.pressedActor = actor;
+  }
+
+  void operator()()
+  {
+    signalData.voidFunctorCalled = true;
+  }
+
+  SignalData& signalData;
+};
+
+// Functor that removes the gestured actor from stage
+struct UnstageActorFunctor : public GestureReceivedFunctor
+{
+  UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage )
+  : GestureReceivedFunctor( data ),
+    stateToUnstage( stateToUnstage )
+  {
+  }
+
+  void operator()( Actor actor, const LongPressGesture& longPress )
+  {
+    GestureReceivedFunctor::operator()( actor, longPress );
+
+    if ( longPress.state == stateToUnstage )
+    {
+      Stage::GetCurrent().Remove( actor );
+    }
+  }
+
+  Gesture::State& stateToUnstage;
+};
+
+// Functor for receiving a touch event
+struct TouchEventFunctor
+{
+  bool operator()(Actor actor, const TouchEvent& touch)
+  {
+    //For line coverage
+    unsigned int points = touch.GetPointCount();
+    if( points > 0)
+    {
+      const TouchPoint& touchPoint = touch.GetPoint(0);
+      tet_printf("Touch Point state = %d\n", touchPoint.state);
+    }
+    return false;
+  }
+};
+
+// Generate a LongPressGestureEvent to send to Core
+Integration::LongPressGestureEvent GenerateLongPress(
+    Gesture::State state,
+    unsigned int numberOfTouches,
+    Vector2 point)
+{
+  Integration::LongPressGestureEvent longPress( state );
+
+  longPress.numberOfTouches = numberOfTouches;
+  longPress.point = point;
+
+  return longPress;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+// Positive test case for a method
+int UtcDaliLongPressGestureDetectorConstructorP(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector;
+  DALI_TEST_CHECK(!detector);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDetectorCopyConstructorP(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();;
+
+  LongPressGestureDetector copy( detector );
+  DALI_TEST_CHECK( detector );
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDetectorAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector;
+  detector = LongPressGestureDetector::New();;
+
+  LongPressGestureDetector copy;
+  copy = detector;
+  DALI_TEST_CHECK( detector );
+
+  DALI_TEST_CHECK( detector == copy );
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDetectorNew(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  DALI_TEST_CHECK(detector);
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  LongPressGestureDetector detector2 = LongPressGestureDetector::New(5u);
+  DALI_TEST_CHECK(detector2);
+  DALI_TEST_EQUALS(5u, detector2.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(5u, detector2.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  LongPressGestureDetector detector3 = LongPressGestureDetector::New(5u, 7u);
+  DALI_TEST_CHECK(detector2);
+  DALI_TEST_EQUALS(5u, detector3.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(7u, detector3.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  //Scoped test to test destructor
+  {
+    LongPressGestureDetector detector4 = LongPressGestureDetector::New();
+    DALI_TEST_CHECK(detector4);
+  }
+
+  // Attach an actor and emit a touch event on the actor to ensure complete line coverage
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  detector.Attach(actor);
+
+  TouchEventFunctor touchFunctor;
+  actor.TouchedSignal().Connect(&application, touchFunctor);
+
+  Integration::TouchEvent touchEvent(1);
+  TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f);
+  touchEvent.AddPoint(point);
+  application.ProcessEvent(touchEvent);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // For line coverage, Initialise default constructor
+  TouchEvent touchEvent2;
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDetectorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::LongPressGestureDetector::DownCast()");
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+
+  BaseHandle object(detector);
+
+  LongPressGestureDetector detector2 = LongPressGestureDetector::DownCast(object);
+  DALI_TEST_CHECK(detector2);
+
+  LongPressGestureDetector detector3 = DownCast< LongPressGestureDetector >(object);
+  DALI_TEST_CHECK(detector3);
+
+  BaseHandle unInitializedObject;
+  LongPressGestureDetector detector4 = LongPressGestureDetector::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!detector4);
+
+  LongPressGestureDetector detector5 = DownCast< LongPressGestureDetector >(unInitializedObject);
+  DALI_TEST_CHECK(!detector5);
+
+  GestureDetector detector6 = LongPressGestureDetector::New();
+  LongPressGestureDetector detector7 = LongPressGestureDetector::DownCast(detector6);
+  DALI_TEST_CHECK(detector7);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSetTouchesRequired01(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+
+  unsigned int touches = 3;
+
+  DALI_TEST_CHECK(touches != detector.GetMinimumTouchesRequired());
+  DALI_TEST_CHECK(touches != detector.GetMaximumTouchesRequired());
+
+  detector.SetTouchesRequired(touches);
+
+  DALI_TEST_EQUALS(touches, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(touches, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  // Attach an actor and change the required touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  TestGestureManager& gestureManager = application.GetGestureManager();
+  gestureManager.Initialize();
+
+  detector.SetTouchesRequired(4);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Create a second gesture detector that requires even less maximum touches
+  LongPressGestureDetector secondDetector = LongPressGestureDetector::New();
+  secondDetector.Attach(actor);
+
+  // Gesture detection should have been updated
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSetTouchesRequired02(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+
+  unsigned int min = 3;
+  unsigned int max = 5;
+
+  DALI_TEST_CHECK(min != detector.GetMinimumTouchesRequired());
+  DALI_TEST_CHECK(max != detector.GetMaximumTouchesRequired());
+
+  detector.SetTouchesRequired(min, max);
+
+  DALI_TEST_EQUALS(min, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(max, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  // Attach an actor and change the maximum touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  TestGestureManager& gestureManager = application.GetGestureManager();
+  gestureManager.Initialize();
+
+  detector.SetTouchesRequired(4, 5);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Create a second gesture detector that requires even less maximum touches
+  LongPressGestureDetector secondDetector = LongPressGestureDetector::New();
+  secondDetector.Attach(actor);
+
+  // Gesture detection should have been updated
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureGetMinimumTouchesRequired(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureGetMaximumTouchesRequired(void)
+{
+  TestApplication application;
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionNegative(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a long press outside actor's area
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, Vector2(112.0f, 112.0f ) ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started,  1u, Vector2(112.0f, 112.0f ) ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, Vector2(112.0f, 112.0f ) ) );
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionPositive(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a long press inside actor's area
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished,  1u, Vector2(50.0f, 50.0f)));
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionDetach(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start long press within the actor's area
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(20.0f, 20.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 20.0f)));
+
+  // repeat the long press within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f)));
+
+  // Detach actor
+  detector.DetachAll();
+
+  // Ensure we are no longer signalled
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionActorDestroyedDuringLongPress(void)
+{
+  TestApplication application;
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Actor lifetime is scoped
+  {
+    Actor actor = Actor::New();
+    actor.SetSize(100.0f, 100.0f);
+    actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    Stage::GetCurrent().Add(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+
+    detector.Attach(actor);
+
+    // Start long press within the actor's area
+    application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 20.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(20.0f, 20.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+    // Remove the actor from stage and reset the data
+    Stage::GetCurrent().Remove(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+  }
+
+  // Actor should now have been destroyed
+
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionRotatedActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a long press
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(5.0f, 5.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION);
+
+  // Rotate actor again and render
+  actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do another long press, should still receive event
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(5.0f, 5.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION);
+
+  // Rotate actor again and render
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::YAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do a long press, inside where the actor used to be, Should not receive the event
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(70.0f, 70.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(70.0f, 70.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(70.0f, 70.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionChildHit(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  // Set child to completely cover parent.
+  // Change rotation of child to be different from parent so that we can check if our local coordinate
+  // conversion of the parent actor is correct.
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  parent.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(parent);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do long press - hits child area but parent should still receive it
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, parent == data.pressedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION);
+
+  // Attach child and generate same touch points
+  // (Also proves that you can detach and then re-attach another actor)
+  detector.Attach(child);
+  detector.Detach(parent);
+
+  // Do an entire long press, only check finished value
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(51.0f, 51.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(51.0f, 51.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(51.0f, 51.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, child == data.pressedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(51.0f, 51.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionAttachDetachMany(void)
+{
+  TestApplication application;
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetX(100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(first);
+  detector.Attach(second);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // LongPress within second actor's area
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.pressedActor, TEST_LOCATION);
+
+  // LongPress within first actor's area
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, first == data.pressedActor, TEST_LOCATION);
+
+  // Detach the second actor
+  detector.Detach(second);
+
+  // second actor shouldn't receive event
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // first actor should continue receiving event
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionActorBecomesUntouchable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // LongPress in actor's area
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Actor becomes invisible - actor should not receive the next long press
+  actor.SetVisible(false);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // LongPress in the same area, shouldn't receive event
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionMultipleGestureDetectors(void)
+{
+  TestApplication application;
+  Dali::TestGestureManager& gestureManager = application.GetGestureManager();
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  second.SetX(100.0f);
+  first.Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector firstDetector = LongPressGestureDetector::New();
+  firstDetector.Attach(first);
+  firstDetector.DetectedSignal().Connect(&application, functor);
+
+  // secondDetector is scoped
+  {
+    // Reset gestureManager statistics
+    gestureManager.Initialize();
+
+    LongPressGestureDetector secondDetector = LongPressGestureDetector::New();
+    secondDetector.SetTouchesRequired(2);
+    secondDetector.Attach(second);
+    secondDetector.DetectedSignal().Connect(&application, functor);
+
+    DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+    // LongPress within second actor's area
+    application.ProcessEvent(GenerateLongPress(Gesture::Possible, 2u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Started,  2u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Finished, 2u, Vector2(150.0f, 10.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, second == data.pressedActor, TEST_LOCATION);
+
+    // LongPress continues as single touch gesture - we should not receive any gesture
+    data.Reset();
+    application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(150.0f, 10.0f)));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Single touch long press starts - first actor should receive gesture
+    data.Reset();
+    application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Started,  1u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, first == data.pressedActor, TEST_LOCATION);
+
+    // long press changes to double-touch - we shouldn't receive event
+    data.Reset();
+    application.ProcessEvent(GenerateLongPress(Gesture::Possible, 2u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Started, 2u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateLongPress(Gesture::Finished, 2u, Vector2(50.0f, 10.0f)));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Reset gesture manager statistics
+    gestureManager.Initialize();
+  }
+
+  // secondDetector has now been deleted.  Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionMultipleDetectorsOnActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to one detector
+  SignalData firstData;
+  GestureReceivedFunctor firstFunctor(firstData);
+  LongPressGestureDetector firstDetector = LongPressGestureDetector::New();
+  firstDetector.Attach(actor);
+  firstDetector.DetectedSignal().Connect(&application, firstFunctor);
+
+  // Attach actor to another detector
+  SignalData secondData;
+  GestureReceivedFunctor secondFunctor(secondData);
+  LongPressGestureDetector secondDetector = LongPressGestureDetector::New();
+  secondDetector.Attach(actor);
+  secondDetector.DetectedSignal().Connect(&application, secondFunctor);
+
+  // LongPress in actor's area - both detector's functors should be called
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSignalReceptionDifferentPossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // LongPress possible in actor's area.
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor somewhere else
+  actor.SetPosition( 100.0f, 100.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the long press.
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // LongPress possible in empty area.
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor in to the long press position.
+  actor.SetPosition( 0.0f, 0.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the long press.
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Normal long press in actor's area for completeness.
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureEmitIncorrectStateClear(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Clear state
+  try
+  {
+    application.ProcessEvent(GenerateLongPress(Gesture::Clear, 1u, Vector2(50.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureEmitIncorrectStateContinuing(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Continuing state
+  try
+  {
+    application.ProcessEvent(GenerateLongPress(Gesture::Continuing, 1u, Vector2(50.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureRepeatedState(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Two possibles
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // ... Send some finished states, still no signal
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Send two Started states, should be signalled
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Send two cancelled states, should not be signalled
+  application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGesturePossibleCancelled(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Send a possible followed by a cancel, we should not be signalled
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateLongPress(Gesture::Cancelled, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureDetachAfterStarted(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit initial signal
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Detach actor
+  detector.Detach(actor);
+
+  // Emit Finished, no signal
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureActorUnstaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit signals
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re-add actor to stage
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Change state to Gesture::Continuing to remove
+  stateToUnstage = Gesture::Finished;
+
+  // Emit signals
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully.
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureActorStagedAndDestroyed(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Create and add a second actor so that GestureDetector destruction does not come into play.
+  Actor dummyActor( Actor::New() );
+  dummyActor.SetSize( 100.0f, 100.0f );
+  dummyActor.SetPosition( 100.0f, 100.0f );
+  dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(dummyActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.Attach(dummyActor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Here we are testing a Started actor which is removed in the Started callback, but then added back
+  // before we get a finished state.  As we were removed from the stage, even if we're at the same
+  // position, we should still not be signalled.
+
+  // Emit signals
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re add to the stage, we should not be signalled
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Here we delete an actor in started, we should not receive any subsequent signalling.
+
+  // Emit signals
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Delete actor as well
+  actor.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a long press inside actor's area
+  Vector2 screenCoords( 50.0f, 50.0f );
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureBehindTouchableSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set system-overlay actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set stage actor to receive the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(stageActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start long press within the two actors' area
+  Vector2 screenCoords( 50.0f, 50.0f );
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureTouchBehindGesturedSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set stage actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  stageActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set system-overlay actor to have the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(systemOverlayActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start long press within the two actors' area
+  Vector2 screenCoords( 50.0f, 50.0f );
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliLongPressGestureLayerConsumesTouch(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a detector
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+  LongPressGestureDetector detector = LongPressGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Add a layer to overlap the actor
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseToTop();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+
+  // Emit signals, should receive
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) );
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Set layer to consume all touch
+  layer.SetTouchConsumed( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit the same signals again, should not receive
+  application.ProcessEvent( GenerateLongPress( Gesture::Possible, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Started, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateLongPress( Gesture::Finished, 1u, screenCoords ) );
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-MathUtils.cpp b/automated-tests/src/dali/utc-Dali-MathUtils.cpp
new file mode 100644 (file)
index 0000000..d8a5b4e
--- /dev/null
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_math_utils_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_math_utils_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliMathUtilsIsPowerOfTwo(void)
+{
+  Dali::TestApplication testApp;
+  DALI_TEST_EQUALS(IsPowerOfTwo(0), false, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(IsPowerOfTwo(1), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(2), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(3), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(4), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(5), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(6), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(7), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(8), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(255), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(256), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(257), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(511), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(512), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(513), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(768), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(1023), false, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(1024), true, TEST_LOCATION);
+  DALI_TEST_EQUALS(IsPowerOfTwo(1025), false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMathUtilsNextPowerOfTwoP(void)
+{
+  Dali::TestApplication testApp;
+
+  DALI_TEST_EQUALS(NextPowerOfTwo(0), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(1), 1u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(2), 2u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(3), 4u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(4), 4u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(5), 8u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(6), 8u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(7), 8u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(8), 8u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(255), 256u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(256), 256u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(257), 512u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(511), 512u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(512), 512u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(513), 1024u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(768), 1024u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(1023), 1024u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(1024), 1024u, TEST_LOCATION);
+  DALI_TEST_EQUALS(NextPowerOfTwo(1025), 2048u, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMathUtilsNextPowerOfTwoN(void)
+{
+  Dali::TestApplication testApp;
+
+  try
+  {
+    NextPowerOfTwo( (1u << (sizeof(unsigned) * 8 - 1)) + 1);
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "Return type cannot represent the next power of two greater than the argument.", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliMathUtilsClampP(void)
+{
+  Dali::TestApplication testApp;
+
+  //floats
+  DALI_TEST_EQUALS(Clamp(-1.0f, 0.0f, 1.0f), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Clamp(0.0f, -1.0f, 1.0f), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Clamp(1.0f, 0.0f, 1.0f), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Clamp(2.0f, 0.0f, 1.0f), 1.0f, TEST_LOCATION);
+
+  // integers
+  DALI_TEST_EQUALS(Clamp(-10, 0, 10), 0, TEST_LOCATION);
+  DALI_TEST_EQUALS(Clamp(0, -10, 10), 0, TEST_LOCATION);
+  DALI_TEST_EQUALS(Clamp(20, 0, 10), 10, TEST_LOCATION);
+
+  float value=-10.0f, min=-2.0f, max=4.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, min, 0.001, TEST_LOCATION);
+
+  value = 10.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, max, 0.001, TEST_LOCATION);
+
+  value = 3.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, 3.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMathUtilsClampInPlaceP(void)
+{
+  Dali::TestApplication testApp;
+
+  float value=-10.0f, min=-2.0f, max=4.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, min, 0.001, TEST_LOCATION);
+
+  value = 10.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, max, 0.001, TEST_LOCATION);
+
+  value = 3.0f;
+  ClampInPlace(value, min, max);
+  DALI_TEST_EQUALS(value, 3.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMathUtilsLerpP(void)
+{
+  Dali::TestApplication testApp;
+
+  float offset=0.0f, low=-2.0f, high=4.0f;
+  DALI_TEST_EQUALS(Lerp(offset, low, high), low, 0.001, TEST_LOCATION);
+  offset = 1.0f;
+  DALI_TEST_EQUALS(Lerp(offset, low, high), high, 0.001, TEST_LOCATION);
+  offset = 0.5f;
+  DALI_TEST_EQUALS(Lerp(offset, low, high), 1.0f, 0.001, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMathUtilsGetRangedEpsilonP(void)
+{
+  Dali::TestApplication testApp;
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.099f),  Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.099f,  0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 0.5f),  Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.99f, 0.5f),  Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.99f, 0.98f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(1.05f, 0.99f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(1.99f, 1.05f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(2.0f,  1.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.05f, 2.0f),  Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(1.0f,  3.0f),  Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 0.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 1.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 9.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(9.99f, 10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(19.99f, 10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(20.0f, 10.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(20.0f, 30.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(80.0f, 90.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(180.0f, 190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(185.0f, 190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(199.0f, 199.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(200.0f, 190.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.005f, 1999.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(2000.0f, 190.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(0.005f, 19999.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(1e07f, 0.99e09f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.099f),  Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.099f, - 0.02f), Dali::Math::MACHINE_EPSILON_0, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -0.5f),  Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.99f, -0.5f),  Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.99f, -0.98f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-1.05f, -0.99f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-1.99f, -1.05f), Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(-2.0f, - 1.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.05f, -2.0f),  Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-1.0f, - 3.0f),  Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -0.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -1.5f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -9.99f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-9.99f, -10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-19.99f, -10.0f), Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(-20.0f, -10.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-20.0f, -30.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-80.0f, -90.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-180.0f, -190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-185.0f, -190.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-199.0f, -199.0f), Dali::Math::MACHINE_EPSILON_100, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(-200.0f, -190.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.005f, -1999.0f), Dali::Math::MACHINE_EPSILON_1000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-2000.0f, -190.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+  DALI_TEST_EQUALS(GetRangedEpsilon(-0.005f, -19999.0f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(GetRangedEpsilon(-1e07f, -0.99e09f), Dali::Math::MACHINE_EPSILON_10000, TEST_LOCATION);
+
+
+  END_TEST;
+}
+
+int UtcDaliMathUtilsWrapInDomainP(void)
+{
+  Dali::TestApplication testApp;
+
+  DALI_TEST_EQUALS(WrapInDomain(0.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(-5.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(5.0f, 0.0f, 0.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(0.0f, 0.0f, 10.0f), 0.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(-5.0f, 0.0f, 10.0f), 5.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(5.0f, 0.0f, 10.0f), 5.0f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(-2.5f, 0.0f, 10.0f), 7.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(2.5f, 0.0f, 10.0f), 2.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(2.5f, 0.0f, 1.0f), 0.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(2.5f, -2.0f, -1.0f), -1.5f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(-2.9f, -2.0f, -1.0f), -1.9f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(WrapInDomain(-1.1f, -2.0f, -1.0f), -1.1f, Dali::Math::MACHINE_EPSILON_1, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMathUtilsShortestDistanceInDomainP(void)
+{
+  Dali::TestApplication testApp;
+
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(1.0f, 8.0f, 0.0f, 10.0f), -3.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(5.0f, 8.0f, 0.0f, 10.0f), 3.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(5.0f, 8.0f, 4.0f, 9.0f), -2.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(8.0f, 5.0f, 4.0f, 9.0f), 2.0f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(0.65f, 0.1f, -1.0f, 1.0f), -0.55f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(0.95f, -0.9f, -1.0f, 1.0f), 0.15f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  DALI_TEST_EQUALS(ShortestDistanceInDomain(0.0f, -0.9f, -1.0f, 1.0f), -0.9f, Dali::Math::MACHINE_EPSILON_10, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMathUtilsEqualsZeroP(void)
+{
+  float v=0.0f;
+
+  DALI_TEST_CHECK(EqualsZero(v));
+
+  v  = Math::PI;
+  v -= (Math::PI_2 * 2.0f);
+  DALI_TEST_CHECK(EqualsZero(v));
+
+  END_TEST;
+}
+
+int UtcDaliMathUtilsEquals01P(void)
+{
+  float w=100.0f;
+  float x=w+1e-8f;
+  DALI_TEST_CHECK( Equals(w, x, GetRangedEpsilon( w, x )) );
+  END_TEST;
+}
+
+int UtcDaliMathUtilsEquals02P(void)
+{
+  float w=100.0f;
+  float x=w+1e-8f;
+  DALI_TEST_CHECK( Equals(w, x) );
+  END_TEST;
+}
+
+int UtcDaliMathUtilsRoundP(void)
+{
+  Dali::TestApplication testApp;
+
+  DALI_TEST_EQUALS(Round(1.00001, 4), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Round(0.99999f, 4), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Round(-1.00001, 4), -1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Round(-0.99999f, 4), -1.0f, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Matrix.cpp b/automated-tests/src/dali/utc-Dali-Matrix.cpp
new file mode 100644 (file)
index 0000000..cd2525f
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+void utc_dali_matrix_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_matrix_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliMatrixConstructor01P(void)
+{
+  Matrix m2(false);
+
+  bool initialised = true;
+  {
+    float* els = m2.AsFloat();
+    for(size_t idx=0; idx<16; ++idx, ++els)
+    {
+      if(*els != 0.0f)
+        initialised = false;
+    }
+  }
+
+  DALI_TEST_EQUALS(initialised, false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMatrixConstructor02P(void)
+{
+  float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f};
+  Matrix m(r);
+
+  float* els = m.AsFloat();
+  float* init = r;
+  bool initialised = true;
+  for(size_t idx=0; idx<16; ++idx, ++els, ++init)
+  {
+    if(*els != *init)
+      initialised = false;
+  }
+  DALI_TEST_EQUALS(initialised, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMatrixConstructor03P(void)
+{
+  float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f};
+
+  Matrix ma(r);
+  Matrix mb(ma);
+
+  float* els = ma.AsFloat();
+  float* init = mb.AsFloat();
+  bool initialised = true;
+  for(size_t idx=0; idx<16; ++idx, ++els, ++init)
+  {
+    if(*els != *init)
+      initialised = false;
+  }
+  DALI_TEST_EQUALS(initialised, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliMatrixConstructor04P(void)
+{
+  Quaternion q(Quaternion::IDENTITY);
+  Matrix m(q);
+  DALI_TEST_EQUALS(Matrix(Matrix::IDENTITY), m, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixAssignP(void)
+{
+  Matrix a(Matrix::IDENTITY);
+  Matrix b = a;
+  DALI_TEST_EQUALS(a, b, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixAssign02P(void)
+{
+  Matrix a(Matrix::IDENTITY);
+  a = a; // self assign does the do nothing branch
+  DALI_TEST_EQUALS(Matrix(Matrix::IDENTITY), a, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetIdentityP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+  m.SetIdentity();
+
+  DALI_TEST_EQUALS(m, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetIdentityAndScaleP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+  m.SetIdentityAndScale(Vector3(4.0f, 4.0f, 4.0f));
+
+  float els2[] = { 4.0f, 0.0f, 0.0f, 0.0f,
+                   0.0f, 4.0f, 0.0f, 0.0f,
+                   0.0f, 0.0f, 4.0f, 0.0f,
+                   0.0f, 0.0f, 0.0f, 1.0f };
+  Matrix r(els2);
+
+  DALI_TEST_EQUALS(m, r, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixInvertTransformP(void)
+{
+  for (int i=0;i<1000;++i)
+  {
+    float f = i;
+    Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f));
+    axis.Normalize();
+    Vector3 center(f, cosf(f) * 100.0f, cosf(f*0.5f) * 50.0f);
+
+    Matrix m0;
+    m0.SetIdentity();
+    m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center );
+
+    Matrix m1;
+    m0.InvertTransform(m1);
+
+    Matrix m2( false );
+    Matrix::Multiply( m2, m0, m1 );
+
+    DALI_TEST_EQUALS(m2, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixInvertTransformN(void)
+{
+  std::string exceptionString( "EqualsZero( mMatrix[3] ) && EqualsZero( mMatrix[7] ) && EqualsZero( mMatrix[11] ) && Equals( mMatrix[15], 1.0f" );
+  try
+  {
+    float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                    4.0f,  5.0f,  6.0f,  7.0f,
+                    8.0f,  9.0f, 10.0f, 11.0f,
+                    12.0f, 13.0f, 14.0f, 15.0f };
+    Matrix m(els);
+
+    Matrix it;
+    m.InvertTransform(it);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION );
+  }
+
+  try
+  {
+    float els[] = { 0.0f,  1.0f,  2.0f,  0.0f,
+                    4.0f,  5.0f,  6.0f,  7.0f,
+                    8.0f,  9.0f, 10.0f, 11.0f,
+                    12.0f, 13.0f, 14.0f, 15.0f };
+    Matrix m(els);
+
+    Matrix it;
+    m.InvertTransform(it);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION );
+  }
+
+  try
+  {
+    float els[] = { 0.0f,  1.0f,  2.0f,  0.0f,
+                    4.0f,  5.0f,  6.0f,  0.0f,
+                    8.0f,  9.0f, 10.0f, 11.0f,
+                    12.0f, 13.0f, 14.0f, 15.0f };
+    Matrix m(els);
+
+    Matrix it;
+    m.InvertTransform(it);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION );
+  }
+
+  try
+  {
+    float els[] = { 0.0f,  1.0f,  2.0f,  0.0f,
+                    4.0f,  5.0f,  6.0f,  0.0f,
+                    8.0f,  9.0f, 10.0f,  0.0f,
+                    12.0f, 13.0f, 14.0f, 15.0f };
+    Matrix m(els);
+
+    Matrix it;
+    m.InvertTransform(it);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, exceptionString, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixInvert01P(void)
+{
+  // We're going to invert a whole load of different matrices to make sure we don't
+  // fail on particular orientations.
+  for (int i=0;i<1000;++i)
+  {
+    float f = i;
+    Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f));
+    axis.Normalize();
+    Vector3 center(f, cosf(f) * 100.0f, cosf(f*0.5f) * 50.0f);
+
+    Matrix m0;
+    m0.SetIdentity();
+    m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center );
+
+    Matrix m1(m0);
+    m1.Invert();
+
+    Matrix m2( false );
+    Matrix::Multiply( m2, m0, m1 );
+
+    DALI_TEST_EQUALS(m2, Matrix::IDENTITY, 0.001f, TEST_LOCATION);
+
+    m1.Invert();    // doube invert - should be back to m0
+
+    DALI_TEST_EQUALS(m0, m1, 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixInvert02P(void)
+{
+  Matrix m1 = Matrix::IDENTITY;
+  m1.SetXAxis(Vector3(0.0f, 0.0f, 0.0f));
+  DALI_TEST_EQUALS(m1.Invert(), false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixTransposeP(void)
+{
+  float floats[] =
+  {   0.0f,  1.0f,  2.0f,  3.0f,
+      4.0f,  5.0f,  6.0f,  7.0f,
+      8.0f,  9.0f, 10.0f,  11.0f,
+     12.0f, 13.0f, 14.0f,  15.0f
+  };
+
+  Matrix m(floats);
+  m.Transpose();
+
+  bool success = true;
+
+  for (int x=0;x<4;++x)
+  {
+    for (int y=0;y<4;++y)
+    {
+      success &= (m.AsFloat()[x+y*4] == floats[x*4+y]);
+    }
+  }
+
+  DALI_TEST_CHECK(success);
+  END_TEST;
+}
+
+int UtcDaliMatrixGetXAxisP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+
+  DALI_TEST_CHECK(m.GetXAxis() == Vector3(0.0f,  1.0f,  2.0f));
+  END_TEST;
+}
+
+int UtcDaliMatrixGetYAxisP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+
+  DALI_TEST_CHECK(m.GetYAxis() == Vector3(4.0f,  5.0f,  6.0f));
+  END_TEST;
+}
+
+int UtcDaliMatrixGetZAxisP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+
+  DALI_TEST_CHECK(m.GetZAxis() == Vector3(8.0f,  9.0f, 10.0f));
+  END_TEST;
+}
+
+int UtcDaliMatrixSetXAxisP(void)
+{
+  Matrix m;
+  Vector3 v(2.0f, 3.0f, 4.0f);
+  m.SetXAxis(v);
+
+  DALI_TEST_CHECK(m.GetXAxis() == v);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetYAxisP(void)
+{
+  Matrix m;
+  Vector3 v(2.0f, 3.0f, 4.0f);
+  m.SetYAxis(v);
+
+  DALI_TEST_CHECK(m.GetYAxis() == v);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetZAxisP(void)
+{
+  Matrix m;
+  Vector3 v(2.0f, 3.0f, 4.0f);
+  m.SetZAxis(v);
+
+  DALI_TEST_CHECK(m.GetZAxis() == v);
+  END_TEST;
+}
+
+int UtcDaliMatrixGetTranslationP(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+
+  DALI_TEST_EQUALS(m.GetTranslation(), Vector4(12.0f, 13.0f, 14.0f, 15.0f), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixGetTranslation3P(void)
+{
+  float els[] = { 0.0f,  1.0f,  2.0f,  3.0f,
+                  4.0f,  5.0f,  6.0f,  7.0f,
+                  8.0f,  9.0f, 10.0f, 11.0f,
+                  12.0f, 13.0f, 14.0f, 15.0f };
+  Matrix m(els);
+
+  DALI_TEST_EQUALS(m.GetTranslation3(), Vector3(12.0f, 13.0f, 14.0f), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetTranslationP(void)
+{
+  Matrix m;
+  Vector4 v(2.0f, 3.0f, 4.0f, 5.0f);
+  m.SetTranslation(v);
+
+  DALI_TEST_CHECK(m.GetTranslation() == v);
+  END_TEST;
+}
+
+int UtcDaliMatrixSetTranslation3P(void)
+{
+  Matrix m;
+  Vector3 v(2.0f, 3.0f, 4.0f);
+  m.SetTranslation(v);
+
+  DALI_TEST_CHECK(m.GetTranslation3() == v);
+  END_TEST;
+}
+
+int UtcDaliMatrixOrthoNormalize0P(void)
+{
+  // OrthoNormalise fixes floating point errors from matrix rotations
+  Matrix m;
+  m.SetIdentity();
+
+  for (int i=0;i<1000;++i)
+  {
+    float f = i;
+    Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f));
+    axis.Normalize();
+
+    m.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), Vector3::ZERO );
+    m.OrthoNormalize();
+  }
+
+  bool success = true;
+  success &= fabsf(m.GetXAxis().Dot(m.GetYAxis())) < 0.001f;
+  success &= fabsf(m.GetYAxis().Dot(m.GetXAxis())) < 0.001f;
+  success &= fabsf(m.GetZAxis().Dot(m.GetYAxis())) < 0.001f;
+
+  success &= fabsf(m.GetXAxis().Length() - 1.0f) < 0.001f;
+  success &= fabsf(m.GetYAxis().Length() - 1.0f) < 0.001f;
+  success &= fabsf(m.GetZAxis().Length() - 1.0f) < 0.001f;
+
+  DALI_TEST_CHECK(success);
+  END_TEST;
+}
+
+int UtcDaliMatrixOrthoNormalize1P(void)
+{
+  // OrthoNormalize is not flipping the axes and is maintaining the translation
+  for (int i=0;i<1000;++i)
+  {
+    float f = i;
+    Vector3 axis(cosf(f*0.001f), cosf(f*0.02f), cosf(f*0.03f));
+    axis.Normalize();
+    Vector3 center(10.0f, 15.0f, 5.0f);
+
+    Matrix m0;
+    m0.SetIdentity();
+    m0.SetTransformComponents( Vector3::ONE, Quaternion(Radian(1.0f), axis), center );
+
+    Matrix m1(m0);
+    m1.OrthoNormalize();
+
+    DALI_TEST_EQUALS(m0.GetXAxis(), m1.GetXAxis(), 0.001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(m0.GetYAxis(), m1.GetYAxis(), 0.001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(m0.GetZAxis(), m1.GetZAxis(), 0.001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(m0.GetTranslation(), m1.GetTranslation(), 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixConstAsFloatP(void)
+{
+  float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f};
+  const Matrix m(r);
+
+  const float* els = m.AsFloat();
+  const float* init = r;
+  bool initialised = true;
+  for(size_t idx=0; idx<16; ++idx, ++els, ++init)
+  {
+    if(*els != *init)
+      initialised = false;
+  }
+  DALI_TEST_EQUALS(initialised, true, TEST_LOCATION);
+
+
+  END_TEST;
+}
+
+int UtcDaliMatrixAsFloatP(void)
+{
+  float r[] = { 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f, 1.0f, 2.0f, 3.0f, 4.0f};
+  Matrix m(r);
+
+  float* els = m.AsFloat();
+  float* init = r;
+  bool initialised = true;
+  for(size_t idx=0; idx<16; ++idx, ++els, ++init)
+  {
+    if(*els != *init)
+      initialised = false;
+  }
+  DALI_TEST_EQUALS(initialised, true, TEST_LOCATION);
+
+
+  END_TEST;
+}
+
+int UtcDaliMatrixMultiplyP(void)
+{
+  Matrix m1 = Matrix::IDENTITY;
+
+  float els[] = { 1.0f, 0.0f,    0.0f,   0.0f,
+                  0.0f, 0.707f, 0.707f, 0.0f,
+                  0.0f, -0.707f,  0.707f, 0.0f,
+                  0.0f, 0.0f,    0.0f,   1.0f };
+  Matrix result(els);
+
+  Quaternion q(Radian(Degree(45.0f)), Vector3::XAXIS);
+  Matrix m2(false);
+  Matrix::Multiply(m2, m1, q);
+
+  DALI_TEST_EQUALS(m2, result, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixOperatorMultiply01P(void)
+{
+  Vector4 v1(2.0f, 5.0f, 4.0f, 0.0f);
+
+  float els[] = {2.0f, 0.0f, 0.0f, 0.0f,
+                 0.0f, 3.0f, 0.0f, 0.0f,
+                 0.0f, 0.0f, 4.0f, 0.0f,
+                 0.0f, 0.0f, 0.0f, 1.0f };
+  Matrix m1(els);
+
+  Vector4 v2 = m1 * v1;
+  Vector4 r1(4.0f, 15.0f, 16.0f, 0.0f);
+  DALI_TEST_EQUALS(v2, r1, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixOperatorMultiply02P(void)
+{
+  TestApplication application;
+
+  Vector3 position ( 30.f, 40.f, 50.f);
+
+  Matrix m1(false);
+  m1.SetIdentity();
+  m1.SetTranslation(-position);
+
+  Vector4 positionV4(position);
+  positionV4.w=1.0f;
+  Vector4 output = m1 * positionV4;
+
+  output.w = 0.0f;
+  DALI_TEST_EQUALS(output, Vector4::ZERO, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixOperatorEqualsP(void)
+{
+  Matrix m1 = Matrix::IDENTITY;
+
+  float els[] = { 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
+  Matrix r2(els);
+  DALI_TEST_EQUALS(m1 == r2, true, TEST_LOCATION);
+
+  float *f = m1.AsFloat();
+  for(size_t i=0; i<16; i++)
+  {
+    f[15-i] = 1.2f;
+    DALI_TEST_EQUALS(m1 == r2, false, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixOperatorNotEqualsP(void)
+{
+  Matrix m1 = Matrix::IDENTITY;
+  float els[] = {2.0f, 0.0f, 0.0f, 0.0f,
+                 0.0f, 3.0f, 0.0f, 0.0f,
+                 0.0f, 0.0f, 4.0f, 0.0f,
+                 0.0f, 0.0f, 0.0f, 1.0f };
+  Matrix r1(els);
+
+  DALI_TEST_CHECK(m1 != r1);
+  DALI_TEST_CHECK(!(m1 != m1));
+  END_TEST;
+}
+
+int UtcDaliMatrixSetTransformComponents01P(void)
+{
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward(x, y, z);
+        vForward.Normalize();
+
+        for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f)
+        {
+          Quaternion rotation1(Radian(Degree(angle)), vForward);
+
+          Matrix m1(rotation1);
+          Matrix result1(false);
+          Vector3 vForward3(vForward.x, vForward.y, vForward.z);
+          result1.SetTransformComponents( Vector3::ONE, Quaternion(Radian(Degree(angle)), vForward3), Vector3::ZERO );
+
+          DALI_TEST_EQUALS(m1, result1, 0.001, TEST_LOCATION);
+
+          Matrix m2(false);
+          m2.SetTransformComponents(vForward, Quaternion::IDENTITY, Vector3::ZERO);
+
+          Matrix result2a(Matrix::IDENTITY);
+          result2a.SetXAxis(result2a.GetXAxis() * vForward[0]);
+          result2a.SetYAxis(result2a.GetYAxis() * vForward[1]);
+          result2a.SetZAxis(result2a.GetZAxis() * vForward[2]);
+
+          DALI_TEST_EQUALS(m2, result2a, 0.001, TEST_LOCATION);
+
+          Matrix m3(false);
+          m3.SetTransformComponents(vForward, rotation1, Vector3::ZERO);
+
+          Matrix result3(Matrix::IDENTITY);
+          result3.SetXAxis(result3.GetXAxis() * vForward[0]);
+          result3.SetYAxis(result3.GetYAxis() * vForward[1]);
+          result3.SetZAxis(result3.GetZAxis() * vForward[2]);
+
+          Matrix::Multiply(result3, result3, m1);
+          DALI_TEST_EQUALS(m3, result3, 0.001, TEST_LOCATION);
+        }
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixSetInverseTransformComponent01P(void)
+{
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward(x, y, z);
+        vForward.Normalize();
+
+        {
+          Quaternion rotation1(Quaternion::IDENTITY); // test no rotation branch
+          Vector3 scale1(2.0f, 3.0f, 4.0f);
+          Vector3 position1(1.0f, 2.0f, 3.0f);
+
+          Matrix m1(false);
+          m1.SetTransformComponents(scale1, rotation1, position1);
+
+          Matrix m2(false);
+          m2.SetInverseTransformComponents(scale1, rotation1, position1);
+
+          Matrix result;
+          Matrix::Multiply(result, m1, m2);
+
+          DALI_TEST_EQUALS(result, Matrix::IDENTITY, 0.001, TEST_LOCATION);
+        }
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixSetInverseTransformComponent02P(void)
+{
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward(x, y, z);
+        vForward.Normalize();
+
+        for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f)
+        {
+          Quaternion rotation1(Radian(Degree(angle)), vForward);
+          Matrix rotationMatrix(rotation1);   // TEST RELIES ON THIS METHOD WORKING!!!
+
+          Vector3 position1(5.0f, -6.0f, 7.0f);
+
+          Matrix m1(false);
+          m1.SetTransformComponents( Vector3::ONE, rotation1, position1 );
+
+          Matrix m2(false);
+          m2.SetInverseTransformComponents( rotationMatrix.GetXAxis(),
+                                            rotationMatrix.GetYAxis(),
+                                            rotationMatrix.GetZAxis(),
+                                            position1 );
+
+          Matrix result;
+          Matrix::Multiply(result, m1, m2);
+
+          DALI_TEST_EQUALS(result, Matrix::IDENTITY, 0.001, TEST_LOCATION);
+        }
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixGetTransformComponents01P(void)
+{
+  Matrix m2(Matrix::IDENTITY.AsFloat());
+  Vector3 pos2;
+  Vector3 scale2;
+  Quaternion q2;
+  m2.GetTransformComponents(pos2, q2, scale2);
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), pos2, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3(1.0f, 1.0f, 1.0f), scale2, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(Quaternion(), q2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliMatrixGetTransformComponents02P(void)
+{
+  // Create an arbitrary vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward(x, y, z);
+        vForward.Normalize();
+
+        for( float angle = 5.0f; angle <= 360.0f; angle += 15.0f)
+        {
+          Quaternion rotation1(Radian(Degree(angle)), vForward);
+          Vector3 scale1(2.0f, 3.0f, 4.0f);
+          Vector3 position1(1.0f, 2.0f, 3.0f);
+
+          Matrix m1(false);
+          m1.SetTransformComponents(scale1, rotation1, position1);
+
+          Vector3 position2;
+          Quaternion rotation2;
+          Vector3 scale2;
+          m1.GetTransformComponents(position2, rotation2, scale2);
+
+          DALI_TEST_EQUALS(position1, position2, 0.001, TEST_LOCATION);
+          DALI_TEST_EQUALS(scale1, scale2, 0.001, TEST_LOCATION);
+          DALI_TEST_EQUALS(rotation1, rotation2, 0.001, TEST_LOCATION);
+        }
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrixGetTransformComponents03P(void)
+{
+  Matrix m2; // zero branch
+  Vector3 pos2;
+  Vector3 scale2;
+  Quaternion q2;
+  m2.GetTransformComponents(pos2, q2, scale2);
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), pos2, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3(0.0f, 0.0f, 0.0f), scale2, 0.001, TEST_LOCATION);
+  // DALI_TEST_EQUALS(Quaternion(), q2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrixOStreamOperator(void)
+{
+  std::ostringstream oss;
+
+  Matrix matrix;
+  matrix.SetIdentity();
+
+  oss << matrix;
+
+  std::string expectedOutput = "[ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Matrix3.cpp b/automated-tests/src/dali/utc-Dali-Matrix3.cpp
new file mode 100644 (file)
index 0000000..c96859d
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+
+using namespace Dali;
+
+void utc_dali_matrix3_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_matrix3_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+Matrix3 m1(
+  -18.6f, 1.88e-09f, -6.85e-09f,
+  0.0f,13.2f, 13.2f,
+  -1.36e-08f,13.2f, -13.2f);
+
+Matrix3 m2(
+  -18.6f,6.91e-06f, 6.76e-06f,
+  8.04e-09f,13.2f, 13.2f,
+  3.01e-06f,13.2f, -13.2f);
+
+Matrix3 m3(
+  6.24f,-12.4f, -12.4f,
+  -17.6f,-4.46f, -4.37f,
+  -0.0641f,13.2f, -13.2f);
+
+Matrix3 m4(
+  -16.3f,6.42f, 6.38f,
+  9.05f,11.6f, 11.4f,
+  -0.0371f,13.1f, -13.3f);
+
+Matrix3 m5(
+  -2.43f,13.2f, 12.9f,
+  18.5f,1.92f, 1.51f,
+  -0.257f,13.0f, -13.4f);
+
+Matrix3 m6(
+  -2.43f,  -13.2f,   -200.9f,
+  18.5f,     1.92f,    1.51f,
+   0.257f,  13.0f,    13.4f);
+
+
+Matrix3 i1(
+  -0.05,  -0.00,   0.00,
+  -0.00,   0.04,   0.04,
+   0.00,   0.04,  -0.04);
+
+Matrix3 i2(
+  -0.05,   0.00,  -0.00,
+   0.00,   0.04,   0.04,
+   0.00,   0.04,  -0.04);
+
+Matrix3 i3(
+   0.02,  -0.05,  -0.00,
+  -0.04,  -0.01,   0.04,
+  -0.04,  -0.01,  -0.04);
+
+Matrix3 i4(
+  -0.05,   0.03,  -0.00,
+   0.02,   0.03,   0.04,
+   0.02,   0.03,  -0.04);
+
+Matrix3 i5(
+  -0.01,   0.05,  -0.00,
+   0.04,   0.01,   0.04,
+   0.04,   0.00,  -0.04);
+
+
+
+Matrix3 t1(
+  -18.6f, 0.0f, -1.36e-08f,
+  1.88e-09f,13.2f, 13.2f,
+  -6.85e-09f,13.2f, -13.2f);
+
+Matrix3 t2(
+  -18.6f,8.04e-09f, 3.01e-06f,
+  6.91e-06f,13.2f, 13.2f,
+  6.76e-06f,13.2f, -13.2f);
+
+Matrix3 t3(
+  6.24f,-17.6f, -0.0641f,
+  -12.4f,-4.46f, 13.2f,
+  -12.4f, -4.37f, -13.2f);
+
+Matrix3 t4(
+  -16.3f,9.05f, -0.0371f,
+  6.42f, 11.6f, 13.1f,
+  6.38f,11.4f, -13.3f);
+
+Matrix3 t5(
+  -2.43f,18.5f, -0.257f,
+  13.2f, 1.92f, 13.0f,
+  12.9f, 1.51f, -13.4f);
+
+
+
+Matrix3* matrices[5] = { &m1, &m2, &m3, &m4, &m5 };
+Matrix3* inverseMatrices[5] = { &i1, &i2, &i3, &i4, &i5 };
+Matrix3* transposeMatrices[5] = { &t1, &t2, &t3, &t4, &t5 };
+
+} // anonymous namespace
+
+int UtcDaliMatrix3FromMatrix(void)
+{
+  float els0[] = { 0.0f,  1.0f,  2.0f, 3.0f,
+                   4.0f,  5.0f,  6.0f, 7.0f,
+                   8.0f,  9.0f, 10.0f, 11.0f,
+                   12.0f, 13.0f, 14.0f, 15.0f};
+  Matrix m0(els0);
+  Matrix3 m1(0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+
+  Matrix3 m2(m0);
+
+  DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrix3OperatorAssign01(void)
+{
+  float els0[] = { 0.0f,  1.0f,  2.0f, 3.0f,
+                   4.0f,  5.0f,  6.0f, 7.0f,
+                   8.0f,  9.0f, 10.0f, 11.0f,
+                   12.0f, 13.0f, 14.0f, 15.0f};
+  Matrix m0(els0);
+
+  Matrix3 m1(0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+
+  Matrix3 m2;
+  m2 = m0;
+  m2 = m2; // Test branch
+
+  DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliMatrix3OperatorAssign02(void)
+{
+  Matrix3 m0(0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+
+  Matrix3 m1(0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+
+  Matrix3 m2;
+  m2 = m0;
+
+  DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+
+// AsFloat
+int UtcDaliMatrix3AsFloat(void)
+{
+  float values[] = {0.0f,  1.0f,  2.0f,
+                    4.0f,  5.0f,  6.0f,
+                    8.0f,  9.0f, 10.0f };
+
+  Matrix3 m1(values[0], values[1], values[2], values[3],values[4], values[5], values[6], values[7],values[8]);
+
+  for (int i=0;i<9;++i)
+  {
+    DALI_TEST_EQUALS(m1.AsFloat()[i], values[i],       TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+
+// Invert works
+int UtcDaliMatrix3Invert(void)
+{
+  // We're going to invert a whole load of different matrices to make sure we don't
+  // fail on particular orientations.
+  for (int i=0;i<5;++i)
+  {
+    Matrix3 m = *matrices[i];
+    Matrix3 inverseResult1 = *inverseMatrices[i];
+
+    // Convert to Mat4, perform inverse, and convert back to Mat3
+    float* mf = m.AsFloat();
+    float els[] = { mf[0], mf[1], mf[2], 0.0f,
+                    mf[3], mf[4], mf[5], 0.0f,
+                    mf[6], mf[7], mf[8], 0.0f,
+                    0.0f,  0.0f,  0.0f,  1.0f };
+    Matrix mat4(els);
+    mat4.Invert();
+    Matrix3 inverseResult2 = mat4;
+
+    Matrix3 mInv = m;
+    mInv.Invert();
+
+    DALI_TEST_EQUALS(mInv, inverseResult1, 0.01f, TEST_LOCATION);
+    DALI_TEST_EQUALS(mInv, inverseResult2, 0.01f, TEST_LOCATION);
+
+    Matrix3 m2 = mInv;
+    m2.Invert();    // double invert - should be back to m
+
+    DALI_TEST_EQUALS(m, m2, 0.01f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrix3Transpose(void)
+{
+  for (int i=0;i<5;++i)
+  {
+    Matrix3 m0    = *matrices[i];
+    Matrix3 trans = *transposeMatrices[i];
+
+    Matrix3 m1 = m0;
+    m1.Transpose();
+
+    DALI_TEST_EQUALS(m1, trans, 0.001f, TEST_LOCATION);
+
+    Matrix3 m2 = m1;
+    m2.Transpose();
+
+    DALI_TEST_EQUALS(m0, m2, 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+// SetIdentity
+int UtcDaliMatrix3SetIdentity(void)
+{
+  Matrix3 m( 0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+  m.SetIdentity();
+
+  DALI_TEST_EQUALS(m, Matrix3::IDENTITY, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliMatrix3Scale(void)
+{
+  Matrix3 m1( 0.0f,  1.0f,  2.0f,
+             4.0f,  5.0f,  6.0f,
+             8.0f,  9.0f, 10.0f);
+
+  Matrix3 m2( 0.0f,  3.0f,  6.0f,
+             12.0f,  15.0f, 18.0f,
+             24.0f,  27.0f, 30.0f);
+
+  m1.Scale(3.0f);
+
+  DALI_TEST_EQUALS(m1, m2, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrix3Magnitude(void)
+{
+  Matrix3 m1( 0.0f,  1.0f,  -2.0f,
+              3.0f,  -4.0f,  5.0f,
+              -6.0f,  7.0f,  8.0f);
+
+  DALI_TEST_EQUALS(Matrix3::IDENTITY.Magnitude(), 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(m1.Magnitude(), 12.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+
+
+int UtcDaliMatrix3ScaleInverseTranspose(void)
+{
+  Matrix3* matrices[6] = { &m1, &m2, &m3, &m4, &m5, &m6 };
+
+
+  for (int i=0;i<6;++i)
+  {
+    Matrix3 m0    = *matrices[i];
+
+    Matrix3 m1 = m0;
+    m1.Invert();
+    m1.Transpose();
+    m1.Scale(3.0f/(m1.Magnitude()));
+
+    Matrix3 m2 = m0;
+    m2.ScaledInverseTranspose();
+
+    DALI_TEST_EQUALS(m1, m2, 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliMatrix3OStreamOperator(void)
+{
+  std::ostringstream oss;
+
+  Matrix3 matrix( 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f );
+
+  oss << matrix;
+
+  std::string expectedOutput = "[ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrix3Multiply(void)
+{
+  Matrix3 m1( 0.0f,  3.0f,  6.0f,
+             12.0f,  15.0f, 18.0f,
+             24.0f,  27.0f, 30.0f);
+
+  Matrix3 m2( 0.0f,  1.0f,  0.0f,
+             -1.0f,  0.0f,  0.0f,
+              0.0f,  0.0f,  1.0f);
+
+  Matrix3 m3( -3.0f,  0.0f,  6.0f,
+             -15.0f, 12.0f, 18.0f,
+             -27.0f, 24.0f, 30.0f);
+
+  Matrix3 result;
+  Matrix3::Multiply(result, m1, m2);
+
+  DALI_TEST_EQUALS(m3, result, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliMatrix3EqualityOperator(void)
+{
+  Matrix3 m1( 0.0f,  3.0f,  6.0f,
+              12.0f,  15.0f, 18.0f,
+              24.0f,  27.0f, 30.0f);
+
+  Matrix3 m2( 0.0f,  3.0f,  6.0f,
+             12.0f,  15.0f, 18.0f,
+             24.0f,  27.0f, 30.0f);
+
+  DALI_TEST_CHECK(m1 == m2);
+  END_TEST;
+}
+
+int UtcDaliMatrix3InequalityOperator(void)
+{
+  Matrix3 m1( 1.0f,  0.0f,  0.0f,
+              0.0f,  1.0f,  0.0f,
+              0.0f,  0.0f,  1.0f);
+
+  Matrix3 m2( 0.0f,  3.0f,  6.0f,
+             12.0f,  15.0f, 18.0f,
+             24.0f,  27.0f, 30.0f);
+
+  DALI_TEST_CHECK(m1 != m2);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-MeshMaterial.cpp b/automated-tests/src/dali/utc-Dali-MeshMaterial.cpp
new file mode 100644 (file)
index 0000000..67eeb02
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+#include <mesh-builder.h>
+
+void mesh_material_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void mesh_material_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+namespace
+{
+
+Material ConstructMaterial( const std::string& vertexShader,
+                            const std::string& fragmentShader,
+                            float opacity )
+{
+  Shader shader = Shader::New( vertexShader, fragmentShader );
+  Material customMaterial = Material::New(shader);
+  Vector4 color = Color::WHITE;
+  color.a = opacity;
+  customMaterial.SetProperty(Material::Property::COLOR, color);
+  return customMaterial;
+}
+
+void TestBlending( TestApplication& application, Material material, float actorOpacity, BlendingMode::Type blendingMode, bool expectedBlend )
+{
+  // Generate geometry & renderers
+  //Mesh mesh = Mesh::New(meshData);
+
+  application.SendNotification();
+  application.Render(0);
+  application.Render();
+  application.SendNotification();
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  //material.SetBlendMode(blendingMode);
+  actor.SetOpacity(actorOpacity);
+
+  TraceCallStack& cullFaceTrace = application.GetGlAbstraction().GetCullFaceTrace();
+  cullFaceTrace.Enable(true);
+  application.SendNotification();
+  application.Render();
+  //DALI_TEST_EQUALS( BlendEnabled( cullFaceTrace ), expectedBlend, TEST_LOCATION );
+}
+
+} // anonymous namespace
+
+
+/**
+ * Test cases
+ *
+ * Check construction of mesh objects
+ * Check downcast of mesh objects (+ve & -ve)
+ * Check staging of mesh objects
+ *
+ * Check staging of some mesh objects but not all
+ * Create geometry with no verts - ensure it asserts
+ * Create an element based geometry with no indices - ensure it asserts
+ * Create a renderer without a material - ensure nothing renders
+ * Create a render with a material, ensure the material can be changed
+ * Create a render with a material&Sampler, ensure the sampler can be changed
+ * Create a render with a material, sampler, ensure the sampler's texture can be changed
+ * Create a render with a material, sampler, ensure that removing the sampler works
+ *
+ * Blend tests:
+ * 1 Set Material with translucent color, actor color opaque, Set Use image alpha to true
+ *   Expect blending
+ * 2 Set material to translucent, set use image alpha to false, set actor opacity to 1.0f
+ *   Expect no blending
+ * 3 Set material to opaque, set use image alpha to true, set actor opacity to 1.0f
+ *   Expect no blending
+ * 4 Set material to have image with alpha, set use image alpha to true, set actor opacity to 1.0f
+ *   Expect blending
+ * 5 Set material to have image with alpha, set use image alpha to false, set actor opacity to 1.0f
+ *   Expect no blending
+ * 6 Set material to have image without alpha, set use image alpha to true, set actor opacity to 1.0f
+ *   Expect no blending
+ * 7 Set material to have framebuffer with alpha, set use image alpha to true, set actor opacity to 1.0f
+ *   Expect blending
+ * 8 Set material to have image with alpha, set use image alpha to false, set actor opacity to 0.5f
+ *   Expect blending
+ * 9 Set material to have image with no alpha, set material opacity to 0.5, set use image alpha to true, set actor opacity to 1.0f
+ *   Expect blending
+ *
+ * Check defaults of renderer
+ *
+ * Bounding box of geometry?
+ *
+ * Check rendered vertex buffer is the right size for the initial property buffer
+ *
+ * Check PropertyBuffer set via SetData can be read thru property system
+ * Check PropertyBuffer property setters / getters
+ * Check vertex PropertyBuffer set via properties renders as expected
+ * Check Index propertyBuffer set via properties renders as expected
+ *
+ * Check geometry type renders correctly as the matching GL draw call and type
+ *
+ * Check attributes change when rendering different actors with different
+ * vertex formats (utc-Dali-Context.cpp)
+ *
+ * utc-Dali-Material.cpp
+ * Check material color affects output - see shader uniform
+ *
+ * Check material sampler's image load/release policies affect rendering correctly.
+ */
diff --git a/automated-tests/src/dali/utc-Dali-NativeImage.cpp b/automated-tests/src/dali/utc-Dali-NativeImage.cpp
new file mode 100644 (file)
index 0000000..1f080a7
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <test-native-image.h>
+#include <test-intrusive-ptr.h>
+
+using namespace Dali;
+
+void utc_dali_native_image_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_native_image_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+IntrusivePtr<TestNativeImage> Creator()
+{
+  return TestNativeImage::New(10,10);
+}
+
+int UtcDaliIntrusivePtrTestNativeImage(void)
+{
+  UtcCoverageIntrusivePtr<TestNativeImage> pointer;
+
+  pointer.Check(Creator);
+
+  END_TEST;
+}
+
+int UtcDaliNativeImageNew(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliNativeImageNew - NativeImage::New(NativeImageInterface&)");
+
+  // invoke default handle constructor
+  NativeImage image;
+  TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16);
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = NativeImage::New(*(nativeImage.Get()));
+
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+int UtcDaliNativeImageCopyConstructor(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliNativeImageCopyConstructor - NativeImage::NativeImage( const NativeImage& )");
+
+  NativeImage image1;
+  DALI_TEST_CHECK( !image1 );
+
+  TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16);
+  image1 = NativeImage::New(*(nativeImage.Get()));
+  NativeImage image2( image1 );
+
+  DALI_TEST_CHECK( image2 );
+  DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliNativeImageDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Image::DownCast()");
+
+  TestNativeImagePointer nativeImage = TestNativeImage::New(16, 16);
+  NativeImage image = NativeImage::New(*(nativeImage.Get()));
+
+  BaseHandle object(image);
+
+  NativeImage image2 = NativeImage::DownCast(object);
+  DALI_TEST_CHECK(image2);
+
+  NativeImage image3 = DownCast< NativeImage >(object);
+  DALI_TEST_CHECK(image3);
+
+  BaseHandle unInitializedObject;
+  NativeImage image4 = NativeImage::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!image4);
+
+  NativeImage image5 = DownCast< NativeImage >(unInitializedObject);
+  DALI_TEST_CHECK(!image5);
+
+  Image image6 = NativeImage::New(*(nativeImage.Get()));
+  NativeImage image7 = NativeImage::DownCast(image6);
+  DALI_TEST_CHECK(image7);
+  END_TEST;
+}
+
+int UtcDaliNativeImageCreateGlTextureN(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" );
+
+  NativeImage image;
+  try
+  {
+    image.CreateGlTexture();
+    tet_printf( "Assertion test failed - no Exception\n" );
+    tet_result( TET_FAIL );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "image &&", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliNativeImageCreateGlTextureP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" );
+
+  TestNativeImagePointer imageInterface = TestNativeImage::New( 16, 16 );
+  NativeImage image = NativeImage::New( *(imageInterface.Get()) );
+  DALI_TEST_CHECK( image );
+
+  image.CreateGlTexture();
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_EQUALS( imageInterface->mExtensionCreateCalls, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( imageInterface->mTargetTextureCalls, 1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliNativeImageContextLoss(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::NativeImage behaviour through a context lost/regained cycle." );
+
+  // Build an image that is expected to have a GL texture created for it and
+  // recreated in a GL context recovery:
+  TestNativeImagePointer eagerImageInterface = TestNativeImage::New( 16, 16 );
+  NativeImage eagerImage = NativeImage::New( *(eagerImageInterface.Get()) );
+  DALI_TEST_CHECK( eagerImage );
+
+  // Build a regular lazy-allocated image for comparison:
+  TestNativeImagePointer lazyImageInterface = TestNativeImage::New( 16, 16 );
+  NativeImage lazyImage = NativeImage::New( *(lazyImageInterface.Get()) );
+  DALI_TEST_CHECK( lazyImage );
+
+  eagerImage.CreateGlTexture();
+
+  application.SendNotification();
+  application.Render(16);
+
+  // Cycle through a context loss and regain, asserting that the texture is
+  // not reallocated if it already existed before the cycle and is never allocated
+  // throughout the cycle if of the regular lazy kind:
+
+  // Call render thread context destroyed / created functions:
+  application.ResetContext();
+
+  // Call event thread function:
+  application.GetCore().RecoverFromContextLoss();
+
+  // Run update/render loop
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_EQUALS( eagerImageInterface->mExtensionCreateCalls, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( eagerImageInterface->mTargetTextureCalls, 1, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( lazyImageInterface->mExtensionCreateCalls, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( lazyImageInterface->mTargetTextureCalls, 0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliNativeImageExtensionP(void)
+{
+  TestApplication application;
+  tet_infoline( "Testing Dali::NativeImage::GenerateGlTexture()" );
+
+  TestNativeImagePointer testNativeImage = TestNativeImage::New( 16, 16 );
+  DALI_TEST_CHECK( testNativeImage );
+
+  DALI_TEST_CHECK( NULL == testNativeImage->GetExtension() );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-NinePatchImages.cpp b/automated-tests/src/dali/utc-Dali-NinePatchImages.cpp
new file mode 100644 (file)
index 0000000..eea7054
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace {
+
+Integration::Bitmap* CreateBitmap( unsigned int imageHeight, unsigned int imageWidth, unsigned int initialColor, Pixel::Format pixelFormat )
+{
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( pixelFormat,  imageWidth,imageHeight,imageWidth,imageHeight );
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+
+  memset( pixbuffer,  initialColor , imageHeight*imageWidth*bytesPerPixel);
+
+  return bitmap;
+}
+
+void InitialiseRegionsToZeroAlpha( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, Pixel::Format pixelFormat  )
+{
+  PixelBuffer* pixbuffer = image->GetBuffer();
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+
+  for ( unsigned int row = 0; row < imageWidth; ++row )
+  {
+    unsigned int pixelOffset = (row*bytesPerPixel);
+    pixbuffer[pixelOffset+3] = 0x00;
+    pixelOffset += ( imageHeight-1 ) * imageWidth * bytesPerPixel;
+    pixbuffer[pixelOffset+3] = 0x00;
+  }
+
+  for ( unsigned int column = 0; column < imageHeight; ++column )
+  {
+    unsigned int pixelOffset = (column*imageWidth*bytesPerPixel);
+    pixbuffer[pixelOffset+3] = 0x00;
+    pixelOffset += (imageWidth-1)*bytesPerPixel;
+    pixbuffer[pixelOffset+3] = 0x00;
+  }
+}
+
+void AddStretchRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredStretchBorder , Pixel::Format pixelFormat )
+{
+  PixelBuffer* pixbuffer = image->GetBuffer();
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+
+  for ( unsigned int column = requiredStretchBorder.x; column < imageWidth - requiredStretchBorder.z; ++column )
+  {
+    unsigned int pixelOffset = (column*bytesPerPixel);
+    pixbuffer[pixelOffset] = 0x00;
+    pixbuffer[pixelOffset+1] = 0x00;
+    pixbuffer[pixelOffset+2] = 0x00;
+    pixbuffer[pixelOffset+3] = 0xFF;
+  }
+
+  for ( unsigned int row = requiredStretchBorder.y; row < imageHeight - requiredStretchBorder.w; ++row )
+  {
+    unsigned int pixelOffset = (row*imageWidth*bytesPerPixel);
+    pixbuffer[pixelOffset] = 0x00;
+    pixbuffer[pixelOffset+1] = 0x00;
+    pixbuffer[pixelOffset+2] = 0x00;
+    pixbuffer[pixelOffset+3] = 0xFF;
+  }
+}
+
+void AddChildRegionsToImage( Integration::Bitmap* image, unsigned int imageWidth, unsigned int imageHeight, const Vector4& requiredChildRegion, Pixel::Format pixelFormat )
+{
+  PixelBuffer* pixbuffer = image->GetBuffer();
+  unsigned int bytesPerPixel = GetBytesPerPixel(  pixelFormat );
+
+  Integration::Bitmap::PackedPixelsProfile* srcProfile = image->GetPackedPixelsProfile();
+  unsigned int bufferStride = srcProfile->GetBufferStride();
+
+  // Add bottom child region
+  for ( unsigned int column = requiredChildRegion.x; column < imageWidth - requiredChildRegion.z; ++column )
+  {
+    unsigned int pixelOffset = (column*bytesPerPixel);
+    pixelOffset += ( imageHeight-1 ) * bufferStride;
+    pixbuffer[pixelOffset] = 0x00;
+    pixbuffer[pixelOffset+1] = 0x00;
+    pixbuffer[pixelOffset+2] = 0x00;
+    pixbuffer[pixelOffset+3] = 0xFF;
+  }
+
+  // Add right child region
+  for ( unsigned int row = requiredChildRegion.y; row < imageHeight - requiredChildRegion.w; ++row )
+  {
+    unsigned int pixelOffset = row*bufferStride + (imageWidth-1)*bytesPerPixel;
+    pixbuffer[pixelOffset] = 0x00;
+    pixbuffer[pixelOffset+1] = 0x00;
+    pixbuffer[pixelOffset+2] = 0x00;
+    pixbuffer[pixelOffset+3] = 0xFF;
+  }
+}
+
+NinePatchImage CustomizeNinePatch( TestApplication& application,
+                                   unsigned int ninePatchImageWidth,
+                                   unsigned int ninePatchImageHeight,
+                                   const Vector4& requiredStretchBorder,
+                                   bool addChildRegion = false,
+                                   Vector4 requiredChildRegion = Vector4::ZERO )
+{
+  TestPlatformAbstraction& platform = application.GetPlatform();
+
+  Pixel::Format pixelFormat = Pixel::RGBA8888;
+
+  tet_infoline("Create Bitmap");
+  platform.SetClosestImageSize(Vector2( ninePatchImageWidth, ninePatchImageHeight));
+  Integration::Bitmap* bitmap = CreateBitmap( ninePatchImageWidth, ninePatchImageHeight, 0xFF, pixelFormat );
+
+  tet_infoline("Clear border regions");
+  InitialiseRegionsToZeroAlpha( bitmap, ninePatchImageWidth, ninePatchImageHeight, pixelFormat );
+
+  tet_infoline("Add Stretch regions to Bitmap");
+  AddStretchRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, pixelFormat );
+
+  if( addChildRegion )
+  {
+    tet_infoline("Add Child regions to Bitmap");
+    AddChildRegionsToImage( bitmap, ninePatchImageWidth, ninePatchImageHeight, requiredChildRegion, pixelFormat );
+  }
+
+  tet_infoline("Getting resource");
+  Integration::ResourcePointer resourcePtr(bitmap);
+  platform.SetResourceLoaded( 0, Dali::Integration::ResourceBitmap, resourcePtr );
+
+  Image image = ResourceImage::New( "blah.#.png" );
+
+  tet_infoline("Assign image to ImageActor");
+  ImageActor imageActor = ImageActor::New( image );
+  Stage::GetCurrent().Add( imageActor );
+
+  tet_infoline("Downcast Image to a nine-patch image\n");
+  NinePatchImage ninePatchImage = NinePatchImage::DownCast( image );
+
+  return ninePatchImage;
+
+}
+
+} // namespace
+
+int UtcDaliNinePatchImageNew(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliNinePatchImageNew - NinePatchImage::New(const std::string&)");
+
+  // invoke default handle constructor
+  NinePatchImage image;
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = NinePatchImage::New("blah.#.png");
+
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+int UtcDaliNinePatchImageDowncast(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliNinePatchImageDowncast - NinePatchImage::DownCast(BaseHandle)");
+
+  NinePatchImage image = NinePatchImage::New("blah.#.png");
+
+  BaseHandle object(image);
+
+  NinePatchImage image2 = NinePatchImage::DownCast(object);
+  DALI_TEST_CHECK(image2);
+
+  NinePatchImage image3 = DownCast< NinePatchImage >(object);
+  DALI_TEST_CHECK(image3);
+
+  BaseHandle unInitializedObject;
+  NinePatchImage image4 = NinePatchImage::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!image4);
+
+  NinePatchImage image5 = DownCast< NinePatchImage >(unInitializedObject);
+  DALI_TEST_CHECK(!image5);
+
+  Image image6 = NinePatchImage::New("blah.#.png");
+  NinePatchImage image7 = NinePatchImage::DownCast(image6);
+  DALI_TEST_CHECK(image7);
+  END_TEST;
+}
+
+int UtcDaliNinePatchImageCopyConstructor(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliNinePatchImageCopyConstructor - NinePatchImage::NinePatchImage( const NinePatchImage& )");
+
+  NinePatchImage image1;
+  DALI_TEST_CHECK( !image1 );
+
+  image1 = NinePatchImage::New("blah.#.png");
+  NinePatchImage image2( image1 );
+
+  DALI_TEST_CHECK( image2 );
+  DALI_TEST_EQUALS( image1, image2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliNinePatchImageGetStrechBorders(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliNinePatchImageGetStrechBorders - NinePatchImage::GetStretchBorders()");
+
+  /* Stretch region left(2) top(2) right (2) bottom (2)
+    *    ss
+    *  OOOOOO
+    *  OOOOOOc
+    * sOOooOOc
+    * sOOooOOc
+    *  OOOOOOc
+    *  OOOOOO
+    *   cccc
+    */
+
+   const unsigned int ninePatchImageHeight = 8;
+   const unsigned int ninePatchImageWidth = 8;
+   const Vector4 requiredStretchBorder( 3, 3, 3, 3);
+
+   NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder  );
+   DALI_TEST_CHECK( ninePatchImage );
+
+   if ( ninePatchImage )
+   {
+     tet_infoline("Get Stretch regions from NinePatch");
+     Vector4 stretchBorders = ninePatchImage.GetStretchBorders();
+     tet_printf("stretchBorders left(%f) right(%f) top(%f) bottom(%f)\n", stretchBorders.x, stretchBorders.z, stretchBorders.y, stretchBorders.w );
+     DALI_TEST_CHECK( stretchBorders == requiredStretchBorder );
+   }
+   else
+   {
+     tet_infoline("Image not NinePatch");
+     test_return_value = TET_FAIL;
+   }
+
+  END_TEST;
+}
+
+int UtcDaliNinePatchImageGetChildRectangle(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliNinePatchImageGetChildRectangle - NinePatchImage::GetChildRectangle()");
+
+  /* Child region x(2) y(2) width (4) height (4)
+   *
+   *    ss
+   *  OOOOOO
+   *  OOOOOOc
+   * sOOooOOc
+   * sOOooOOc
+   *  OOOOOOc
+   *  OOOOOO
+   *   cccc
+   */
+
+  const unsigned int ninePatchImageHeight = 8;
+  const unsigned int ninePatchImageWidth = 8;
+  const Vector4 requiredChildRegion( 2, 2, 2, 2 );
+  const Vector4 requiredStretchBorder( 3, 3, 3, 3);
+
+  NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder, true, requiredChildRegion );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  if ( ninePatchImage )
+  {
+    tet_infoline("Get Child regions from NinePatch");
+    Rect<int> childRectangle = ninePatchImage.GetChildRectangle();
+    tet_printf("childRectange x(%d) y(%d) width(%d) height(%d)\n", childRectangle.x, childRectangle.y, childRectangle.width, childRectangle.height );
+    Rect<int> childRegion(requiredChildRegion.x, requiredChildRegion.y, ninePatchImageWidth - requiredChildRegion.x - requiredChildRegion.z, ninePatchImageHeight - requiredChildRegion.y - requiredChildRegion.w );
+    DALI_TEST_CHECK( childRegion == childRectangle );
+  }
+  else
+  {
+    tet_infoline("Image not NinePatch");
+    test_return_value = TET_FAIL;
+  }
+
+  END_TEST;
+}
+
+int UtcDaliNinePatchImageCreateCroppedBufferImage(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliNinePatchImageCreateCroppedBufferImage - NinePatchImage::CreateCroppedBufferImage()");
+
+  const unsigned int ninePatchImageHeight = 8;
+  const unsigned int ninePatchImageWidth = 8;
+  const Vector4 requiredStretchBorder( 1,1,1,1);
+
+  NinePatchImage ninePatchImage = CustomizeNinePatch( application,ninePatchImageWidth, ninePatchImageHeight, requiredStretchBorder  );
+  DALI_TEST_CHECK( ninePatchImage );
+
+  if ( ninePatchImage )
+  {
+    BufferImage newImage = ninePatchImage.CreateCroppedBufferImage();
+    DALI_TEST_CHECK( newImage );
+
+    DALI_TEST_EQUALS( newImage.GetPixelFormat(), Pixel::RGBA8888, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( newImage.GetBufferSize(), 144u/* 36*4 */, TEST_LOCATION );
+  }
+  else
+  {
+    tet_infoline("Image not NinePatch");
+    test_return_value = TET_FAIL;
+  }
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp b/automated-tests/src/dali/utc-Dali-ObjectRegistry.cpp
new file mode 100644 (file)
index 0000000..d49b266
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali-test-suite-utils.h>
+#include <dali/public-api/dali-core.h>
+
+using namespace Dali;
+
+namespace
+{
+
+// Functors to test whether Object created/destroyed signal is emitted for different types of Objects
+
+struct TestObjectDestroyedCallback
+{
+  TestObjectDestroyedCallback(bool& signalReceived, Dali::RefObject*& objectPointer)
+  : mSignalVerified(signalReceived),
+    mObjectPointer(objectPointer)
+  {
+  }
+
+  void operator()(const Dali::RefObject* objectPointer)
+  {
+    tet_infoline("Verifying TestObjectDestroyedCallback()");
+
+    if(objectPointer == mObjectPointer)
+    {
+      mSignalVerified = true;
+    }
+  }
+
+  bool& mSignalVerified;
+  Dali::RefObject*& mObjectPointer;
+};
+
+struct TestActorCallback
+{
+  TestActorCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestActorCallback()");
+    Actor actor = Actor::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+
+  bool& mSignalVerified;
+};
+
+struct TestCameraActorCallback
+{
+  TestCameraActorCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestCameraActorCallback()");
+    CameraActor actor = CameraActor::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+  bool& mSignalVerified;
+};
+
+struct TestImageActorCallback
+{
+  TestImageActorCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestImageActorCallback()");
+    ImageActor actor = ImageActor::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+  bool& mSignalVerified;
+};
+
+struct TestLayerCallback
+{
+  TestLayerCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestLayerCallback()");
+    Layer actor = Layer::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+  bool& mSignalVerified;
+};
+
+struct TestAnimationCallback
+{
+  TestAnimationCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestAnimationCallback()");
+    Animation actor = Animation::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+  bool& mSignalVerified;
+};
+
+struct TestShaderEffectCallback
+{
+  TestShaderEffectCallback(bool& signalReceived)
+  : mSignalVerified(signalReceived)
+  {
+  }
+  void operator()(BaseHandle object)
+  {
+    tet_infoline("Verifying TestShaderEffectCallback()");
+    ShaderEffect actor = ShaderEffect::DownCast(object);
+    if(actor)
+    {
+      mSignalVerified = true;
+    }
+  }
+  bool& mSignalVerified;
+};
+
+
+} // anonymous namespace
+
+
+
+
+int UtcDaliObjectRegistryGet(void)
+{
+  TestApplication application;
+
+  ObjectRegistry registry; //  like this for ctor code coverage
+  registry= Stage::GetCurrent().GetObjectRegistry();
+
+  DALI_TEST_CHECK( registry );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistryCopyConstructor(void)
+{
+  TestApplication application;
+
+  ObjectRegistry myRegistry;
+  ObjectRegistry anotherRegistry( myRegistry );
+
+  DALI_TEST_EQUALS( myRegistry, anotherRegistry, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalActorCreated(void)
+{
+  tet_infoline("Testing GetObjectRegistry()");
+  TestApplication application;
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+  DALI_TEST_CHECK( registry );
+
+  bool verified = false;
+  TestActorCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    Actor actor = Actor::New();
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = actor.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalCameraCreated(void)
+{
+  TestApplication application;
+
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+
+  bool verified = false;
+  TestCameraActorCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    CameraActor actor = CameraActor::New();
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = actor.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalImageActorCreated(void)
+{
+  TestApplication application;
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+
+  static const char* TestImageFilename = "icon_wrt.png";
+  Image image = ResourceImage::New(TestImageFilename);
+
+  bool verified = false;
+  TestImageActorCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    ImageActor actor = ImageActor::New(image);
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = actor.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalLayerCreated(void)
+{
+  TestApplication application;
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+
+  bool verified = false;
+  TestLayerCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    Layer actor = Layer::New();
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = actor.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalAnimationCreated(void)
+{
+  TestApplication application;
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+
+  bool verified = false;
+  TestAnimationCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    Animation animation = Animation::New(1.0f);
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = animation.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
+
+int UtcDaliObjectRegistrySignalShaderEffectCreated(void)
+{
+  TestApplication application;
+  ObjectRegistry registry = Stage::GetCurrent().GetObjectRegistry();
+
+  static const char* VertexSource =
+  "void main()\n"
+  "{\n"
+  "  gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);\n"
+  "  vTexCoord = aTexCoord;\n"
+  "}\n";
+
+  static const char* FragmentSource =
+  "void main()\n"
+  "{\n"
+  "  gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n"
+  "}\n";
+
+  bool verified = false;
+  TestShaderEffectCallback test(verified);
+
+  Dali::RefObject* objectPointer = NULL;
+  TestObjectDestroyedCallback test2(verified, objectPointer);
+
+  registry.ObjectCreatedSignal().Connect(&application, test);
+  registry.ObjectDestroyedSignal().Connect(&application, test2);
+
+  {
+    ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+    DALI_TEST_CHECK( test.mSignalVerified );
+
+    verified = false;
+    objectPointer = effect.GetObjectPtr();
+  }
+  DALI_TEST_CHECK( test.mSignalVerified );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PanGesture.cpp b/automated-tests/src/dali/utc-Dali-PanGesture.cpp
new file mode 100644 (file)
index 0000000..b830f9d
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_pan_gesture_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pan_gesture_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+
+int UtcDaliPanGestureConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  PanGesture gesture;
+  DALI_TEST_EQUALS(Gesture::Clear, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION);
+
+  PanGesture gesture2(Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Started, gesture2.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture2.type, TEST_LOCATION);
+
+  PanGesture gesture3(Gesture::Continuing);
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture3.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture3.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture3.type, TEST_LOCATION);
+
+  PanGesture gesture4(Gesture::Finished);
+  DALI_TEST_EQUALS(Gesture::Finished, gesture4.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture4.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture4.type, TEST_LOCATION);
+
+  // Test copy constructor
+  gesture4.numberOfTouches = 3u;
+
+  PanGesture pan(gesture4);
+  DALI_TEST_EQUALS(Gesture::Finished, pan.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(3u, pan.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, pan.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureAssignment(void)
+{
+  // Test Assignment operator
+  PanGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION);
+
+  PanGesture gesture2(Gesture::Continuing);
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture2.type, TEST_LOCATION);
+
+  gesture2.numberOfTouches = 3u;
+
+  gesture = gesture2;
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(3u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetSpeed(void)
+{
+  PanGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(0.0f, gesture.GetSpeed(), TEST_LOCATION);
+
+  gesture.velocity = Vector2(3.0f, -4.0f);
+
+  DALI_TEST_EQUALS(5.0f, gesture.GetSpeed(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetDistance(void)
+{
+  PanGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(0.0f, gesture.GetDistance(), TEST_LOCATION);
+
+  gesture.displacement = Vector2(-30.0f, -40.0f);
+
+  DALI_TEST_EQUALS(50.0f, gesture.GetDistance(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetScreenSpeed(void)
+{
+  PanGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(0.0f, gesture.GetScreenSpeed(), TEST_LOCATION);
+
+  gesture.screenVelocity = Vector2(3.0f, -4.0f);
+
+  DALI_TEST_EQUALS(5.0f, gesture.GetScreenSpeed(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetScreenDistance(void)
+{
+  PanGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(0.0f, gesture.GetScreenDistance(), TEST_LOCATION);
+
+  gesture.screenDisplacement = Vector2(-30.0f, -40.0f);
+
+  DALI_TEST_EQUALS(50.0f, gesture.GetScreenDistance(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureDynamicAllocation(void)
+{
+  PanGesture* gesture = new PanGesture( Gesture::Started );
+  DALI_TEST_EQUALS(Gesture::Started, gesture->state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pan, gesture->type, TEST_LOCATION);
+  delete gesture;
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PanGestureDetector.cpp
new file mode 100644 (file)
index 0000000..4943ce6
--- /dev/null
@@ -0,0 +1,2517 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <cmath>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali/integration-api/profiling.h>
+#include <dali/integration-api/input-options.h>
+#include <dali-test-suite-utils.h>
+#include <test-touch-utils.h>
+
+using namespace Dali;
+
+void utc_dali_pan_gesture_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pan_gesture_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+const int PAN_EVENT_TIME_DELTA = 8;
+const int PAN_GESTURE_UPDATE_COUNT = 50;
+
+// Stores data that is populated in the callback and will be read by the test cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled(false),
+    voidFunctorCalled(false),
+    receivedGesture(Gesture::Clear)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+    voidFunctorCalled = false;
+
+    receivedGesture.state = Gesture::Clear;
+    receivedGesture.velocity = Vector2(0.0f, 0.0f);
+    receivedGesture.displacement = Vector2(0.0f, 0.0f);
+    receivedGesture.position = Vector2(0.0f, 0.0f);
+    receivedGesture.screenPosition = Vector2(0.0f, 0.0f);
+    receivedGesture.numberOfTouches = 0;
+
+    pannedActor.Reset();
+  }
+
+  bool functorCalled;
+  bool voidFunctorCalled;
+  PanGesture receivedGesture;
+  Actor pannedActor;
+};
+
+// Functor that sets the data when called
+struct GestureReceivedFunctor
+{
+  GestureReceivedFunctor(SignalData& data) : signalData(data) { }
+
+  void operator()(Actor actor, const PanGesture& pan)
+  {
+    signalData.functorCalled = true;
+    signalData.receivedGesture = pan;
+    signalData.pannedActor = actor;
+  }
+
+  void operator()()
+  {
+    signalData.voidFunctorCalled = true;
+  }
+
+  SignalData& signalData;
+};
+
+// Functor that removes the gestured actor from stage
+struct UnstageActorFunctor : public GestureReceivedFunctor
+{
+  UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage )
+  : GestureReceivedFunctor( data ),
+    stateToUnstage( stateToUnstage )
+  {
+  }
+
+  void operator()( Actor actor, const PanGesture& pan )
+  {
+    GestureReceivedFunctor::operator()( actor, pan );
+
+    if ( pan.state == stateToUnstage )
+    {
+      Stage::GetCurrent().Remove( actor );
+    }
+  }
+
+  Gesture::State& stateToUnstage;
+};
+
+// Functor for receiving a touch event
+struct TouchEventFunctor
+{
+  bool operator()(Actor actor, const TouchEvent& touch)
+  {
+    return false;
+  }
+};
+
+// Data for constraints
+struct ConstraintData
+{
+  ConstraintData()
+  : called(false)
+  {
+  }
+
+  Vector2 screenPosition;
+  Vector2 screenDisplacement;
+  Vector2 screenVelocity;
+  Vector2 localPosition;
+  Vector2 localDisplacement;
+  Vector2 localVelocity;
+  bool called;
+
+  void Reset()
+  {
+    screenPosition = screenDisplacement = screenVelocity = localPosition = localDisplacement = localVelocity = Vector2::ZERO;
+    called = false;
+  }
+};
+
+// Constraint used with panning properties
+struct PanConstraint
+{
+  PanConstraint( ConstraintData& data ) : constraintData(data) { }
+
+  void operator()( Vector3& current, const PropertyInputContainer& inputs )
+  {
+    constraintData.screenPosition = inputs[0]->GetVector2();
+    constraintData.screenDisplacement = inputs[1]->GetVector2();
+    constraintData.screenVelocity = inputs[2]->GetVector2();
+    constraintData.localPosition = inputs[3]->GetVector2();
+    constraintData.localDisplacement = inputs[4]->GetVector2();
+    constraintData.localVelocity = inputs[5]->GetVector2();
+    constraintData.called = true;
+    current = Vector3::ZERO;
+  }
+
+  ConstraintData& constraintData;
+};
+
+// Generate a PanGestureEvent to send to Core
+Integration::PanGestureEvent GeneratePan(
+    Gesture::State state,
+    Vector2 previousPosition,
+    Vector2 currentPosition,
+    unsigned long timeDelta,
+    unsigned int numberOfTouches = 1,
+    unsigned int time = 1u)
+{
+  Integration::PanGestureEvent pan(state);
+
+  pan.previousPosition = previousPosition;
+  pan.currentPosition = currentPosition;
+  pan.timeDelta = timeDelta;
+  pan.numberOfTouches = numberOfTouches;
+  pan.time = time;
+
+  return pan;
+}
+
+// Generate a PanGesture
+PanGesture GeneratePan( unsigned int time,
+                        Gesture::State state,
+                        Vector2 screenPosition,
+                        Vector2 localPosition,
+                        Vector2 screenDisplacement = Vector2::ONE,
+                        Vector2 localDisplacement = Vector2::ONE,
+                        Vector2 screenVelocity = Vector2::ONE,
+                        Vector2 localVelocity = Vector2::ONE,
+                        unsigned int numberOfTouches = 1 )
+{
+  PanGesture pan( state );
+
+  pan.time = time;
+
+  pan.screenPosition = screenPosition;
+  pan.position = localPosition;
+
+  pan.screenDisplacement = screenDisplacement;
+  pan.displacement = localDisplacement;
+
+  pan.screenVelocity = screenVelocity;
+  pan.velocity = localVelocity;
+
+  pan.numberOfTouches = numberOfTouches;
+
+  return pan;
+}
+
+/**
+ * Helper to generate PanGestureEvent
+ *
+ * @param[in] application Application instance
+ * @param[in] state The Gesture State
+ * @param[in] pos The current position of touch.
+ */
+static void SendPan(TestApplication& application, Gesture::State state, const Vector2& pos)
+{
+  static Vector2 last;
+  static int LastTime = 0;
+
+  if( (state == Gesture::Started) ||
+      (state == Gesture::Possible) )
+  {
+    last.x = pos.x;
+    last.y = pos.y;
+  }
+
+  application.ProcessEvent(GeneratePan(state, last, pos, PAN_EVENT_TIME_DELTA));
+
+  last.x = pos.x;
+  last.y = pos.y;
+  LastTime += PAN_EVENT_TIME_DELTA;
+}
+
+static Vector2 PerformSwipeGestureSwipe(TestApplication& application, Vector2 start, Vector2 direction, int frames, bool finish = true)
+{
+  // Now do a pan starting from (start) and heading (direction)
+  Vector2 pos(start);
+  SendPan(application, Gesture::Possible, pos);
+  SendPan(application, Gesture::Started, pos);
+  application.SendNotification();
+  application.Render();
+
+  for(int i = 0;i<frames;i++)
+  {
+    pos += direction; // Move in this direction
+    SendPan(application, Gesture::Continuing, pos);
+    application.SendNotification();
+    application.Render();
+  }
+
+  if(finish)
+  {
+    SendPan(application, Gesture::Finished, pos);
+    application.SendNotification();
+    application.Render();
+  }
+
+  return pos;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Positive test case for a method
+int UtcDaliPanGestureDetectorConstructor(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector;
+  DALI_TEST_CHECK(!detector);
+  END_TEST;
+}
+
+int UtcDaliPanGestureDetectorCopyConstructorP(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();;
+
+  PanGestureDetector copy( detector );
+  DALI_TEST_CHECK( detector );
+  END_TEST;
+}
+
+int UtcDaliPanGestureDetectorAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();;
+
+  PanGestureDetector assign;
+  assign = detector;
+  DALI_TEST_CHECK( detector );
+
+  DALI_TEST_CHECK( detector == assign );
+  END_TEST;
+}
+
+// Negative test case for a method
+int UtcDaliPanGestureDetectorNew(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  DALI_TEST_CHECK(detector);
+
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  // Attach an actor and emit a touch event on the actor to ensure complete line coverage
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  detector.Attach(actor);
+
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Integration::TouchEvent touchEvent(1);
+  TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f);
+  touchEvent.AddPoint(point);
+  application.ProcessEvent(touchEvent);
+  END_TEST;
+}
+
+int UtcDaliPanGestureDetectorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::GestureDetector::DownCast()");
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  BaseHandle object(detector);
+
+  PanGestureDetector detector2 = PanGestureDetector::DownCast(object);
+  DALI_TEST_CHECK(detector2);
+
+  PanGestureDetector detector3 = DownCast< PanGestureDetector >(object);
+  DALI_TEST_CHECK(detector3);
+
+  BaseHandle unInitializedObject;
+  PanGestureDetector detector4 = PanGestureDetector::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!detector4);
+
+  PanGestureDetector detector5 = DownCast< PanGestureDetector >(unInitializedObject);
+  DALI_TEST_CHECK(!detector5);
+
+  GestureDetector detector6 = PanGestureDetector::New();
+  PanGestureDetector detector7 = PanGestureDetector::DownCast(detector6);
+  DALI_TEST_CHECK(detector7);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSetMinimumTouchesRequired(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  unsigned int min = 2;
+
+  DALI_TEST_CHECK(min != detector.GetMinimumTouchesRequired());
+
+  detector.SetMinimumTouchesRequired(min);
+
+  DALI_TEST_EQUALS(min, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+
+  // Attach an actor and change the minimum touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  TestGestureManager& gestureManager = application.GetGestureManager();
+  gestureManager.Initialize();
+
+  detector.SetMinimumTouchesRequired(3);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Create a second gesture detector that requires even less minimum touches
+  PanGestureDetector secondDetector = PanGestureDetector::New();
+  secondDetector.Attach(actor);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSetMaximumTouchesRequired(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  unsigned int max = 3;
+
+  DALI_TEST_CHECK(max != detector.GetMaximumTouchesRequired());
+
+  detector.SetMaximumTouchesRequired(max);
+
+  DALI_TEST_EQUALS(max, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+
+  // Attach an actor and change the maximum touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  TestGestureManager& gestureManager = application.GetGestureManager();
+  gestureManager.Initialize();
+
+  detector.SetMaximumTouchesRequired(4);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Create a second gesture detector that requires even less maximum touches
+  PanGestureDetector secondDetector = PanGestureDetector::New();
+  secondDetector.Attach(actor);
+
+  // Gesture detection should NOT have been updated
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetMinimumTouchesRequired(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTouchesRequired(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetMaximumTouchesRequired(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTouchesRequired(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionNegative(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a pan outside actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(110.0f, 110.0f), Vector2(112.0f, 112.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(110.0f, 110.0f), Vector2(112.0f, 112.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Continue pan into actor's area - we should still not receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(112.0f, 112.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Stop panning - we should still not receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 20.0f), Vector2(12.0f, 12.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionDownMotionLeave(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(0.0f, -10.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(0.0f, -1.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+
+  // Pan Gesture leaves actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(320.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(300.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(30.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(300.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(30.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+
+  // Gesture ends - we would receive a finished state
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(320.0f, 10.0f), Vector2(310.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionDownMotionUp(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(0.0f, -10.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(0.0f, -1.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+
+  // Gesture ends within actor's area - we would receive a finished state
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-10.0f, 0.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-1.0f, 0.0f), data.receivedGesture.velocity, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.GetDistance(), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(1.0f, data.receivedGesture.GetSpeed(), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionCancelled(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+
+  // The gesture is cancelled
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Cancelled, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionDetach(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Detach actor
+  detector.DetachAll();
+
+  // Ensure we are no longer signalled
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionDetachWhilePanning(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Detach actor during the pan, we should not receive the next event
+  detector.DetachAll();
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionActorDestroyedWhilePanning(void)
+{
+  TestApplication application;
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Attach a temporary actor to stop detector being removed from PanGestureProcessor when main actor
+  // is destroyed.
+  Actor tempActor = Actor::New();
+  tempActor.SetSize(100.0f, 100.0f);
+  tempActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(tempActor);
+  detector.Attach(tempActor);
+
+  // Actor lifetime is scoped
+  {
+    Actor actor = Actor::New();
+    actor.SetSize(100.0f, 100.0f);
+    actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    Stage::GetCurrent().Add(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+
+    detector.Attach(actor);
+
+    // Start pan within the actor's area
+    application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+    application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+    // Continue the pan within the actor's area - we should still receive the signal
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+    // Remove the actor from stage and reset the data
+    Stage::GetCurrent().Remove(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+  }
+
+  // Actor should now have been destroyed
+
+  // Gesture ends within the area where the actor used to be
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionRotatedActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do an entire pan, only check finished value
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(8.0f, -5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative
+
+  // Rotate actor again and render a couple of times
+  actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do an entire pan, only check finished value
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-5.0f, -8.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative
+
+  // Rotate actor again and render a couple of times
+  actor.SetOrientation(Dali::Degree(270.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do an entire pan, only check finished value
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(-8.0f, 5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionChildHit(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  // Set child to completely cover parent.
+  // Change rotation of child to be different from parent so that we can check if our local coordinate
+  // conversion of the parent actor is correct.
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  parent.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(parent);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do an entire pan, only check finished value - hits child area but parent should still receive it
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, parent == data.pannedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(5.0f, 8.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative
+
+  // Attach child and generate same touch points to yield a different displacement
+  // (Also proves that you can detach and then re-attach another actor)
+  detector.Attach(child);
+  detector.Detach(parent);
+
+  // Do an entire pan, only check finished value
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(11.0f, 12.0f), Vector2(22.0f, 12.0f), 10));
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(22.0f, 12.0f), Vector2(27.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, child == data.pannedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(8.0f, -5.0f), data.receivedGesture.displacement, 0.01f, TEST_LOCATION); // Actor relative
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionAttachDetachMany(void)
+{
+  TestApplication application;
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetX(100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(first);
+  detector.Attach(second);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within second actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(110.0f, 20.0f), Vector2(120.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(110.0f, 20.0f), Vector2(120.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION);
+
+  // Pan moves into first actor's area - second actor should receive the pan
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(120.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION);
+
+  // Detach the second actor during the pan, we should not receive the next event
+  detector.Detach(second);
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionActorBecomesUntouchable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan in actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Pan continues within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Actor become invisible - actor should not receive the next pan
+  actor.SetVisible(false);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 10.0f), Vector2(10.0f, 10.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionMultipleGestureDetectors(void)
+{
+  TestApplication application;
+  Dali::TestGestureManager& gestureManager = application.GetGestureManager();
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  first.Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector firstDetector = PanGestureDetector::New();
+  firstDetector.Attach(first);
+  firstDetector.DetectedSignal().Connect(&application, functor);
+
+  // secondDetector is scoped
+  {
+    // Reset gestureManager statistics
+    gestureManager.Initialize();
+
+    PanGestureDetector secondDetector = PanGestureDetector::New();
+    secondDetector.SetMinimumTouchesRequired(2);
+    secondDetector.SetMaximumTouchesRequired(2);
+    secondDetector.Attach(second);
+    secondDetector.DetectedSignal().Connect(&application, functor);
+
+    DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+    // Start pan within second actor's area
+    application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10, 2));
+    application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10, 2));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION);
+
+    // Two touch pan changes to single touch - we should receive a finished state
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, second == data.pannedActor, TEST_LOCATION);
+
+    // Pan continues as single touch gesture - we should not receive any gesture
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(30.0f, 10.0f), 10));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Pan ends - still no signal
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(30.0f, 10.0f), Vector2(30.0f, 20.0f), 10));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Single touch pan starts - first actor should be panned
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+    application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, first == data.pannedActor, TEST_LOCATION);
+
+    // Pan changes to double-touch - we should receive a finished state
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10, 2));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, first == data.pannedActor, TEST_LOCATION);
+
+    // Pan continues as double touch gesture - we should not receive any gesture
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 10.0f), Vector2(30.0f, 10.0f), 10));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Pan ends - still no signal
+    data.Reset();
+    application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(30.0f, 10.0f), Vector2(30.0f, 20.0f), 10));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Reset gesture manager statistics
+    gestureManager.Initialize();
+  }
+
+  // secondDetector has now been deleted.  Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionMultipleDetectorsOnActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  Actor actor2 = Actor::New();
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(actor2);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to one detector
+  SignalData firstData;
+  GestureReceivedFunctor firstFunctor(firstData);
+  PanGestureDetector firstDetector = PanGestureDetector::New();
+  firstDetector.Attach(actor);
+  firstDetector.DetectedSignal().Connect(&application, firstFunctor);
+
+  // Attach actor to another detector
+  SignalData secondData;
+  GestureReceivedFunctor secondFunctor(secondData);
+  PanGestureDetector secondDetector = PanGestureDetector::New();
+  secondDetector.Attach(actor);
+  secondDetector.DetectedSignal().Connect(&application, secondFunctor);
+
+  // Add second actor to second detector, when we remove the actor, this will make sure that this
+  // gesture detector is not removed from the GestureDetectorProcessor.  In this scenario, the
+  // functor should still not be called (which is what we're also testing).
+  secondDetector.Attach(actor2);
+
+  // Pan in actor's area - both detector's functors should be called
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Pan continues in actor's area - both detector's functors should be called
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Detach actor from firstDetector and emit pan on actor, only secondDetector's functor should be called.
+  firstDetector.Detach(actor);
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // New pan on actor, only secondDetector has actor attached
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Detach actor from secondDetector
+  secondDetector.Detach(actor);
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(false, secondData.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionMultipleStarted(void)
+{
+  // Should handle two started events gracefully.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Start pan in actor's area
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Send another start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Add a child actor to overlap actor and send another start in actor's area
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  actor.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Send another possible and start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Send another start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionEnsureCorrectSignalling(void)
+{
+  TestApplication application;
+
+  Actor actor1 = Actor::New();
+  actor1.SetSize(100.0f, 100.0f);
+  actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor1);
+  SignalData data1;
+  GestureReceivedFunctor functor1(data1);
+  PanGestureDetector detector1 = PanGestureDetector::New();
+  detector1.Attach(actor1);
+  detector1.DetectedSignal().Connect(&application, functor1);
+
+  Actor actor2 = Actor::New();
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  actor2.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(actor2);
+  SignalData data2;
+  GestureReceivedFunctor functor2(data2);
+  PanGestureDetector detector2 = PanGestureDetector::New();
+  detector2.Attach(actor2);
+  detector2.DetectedSignal().Connect(&application, functor2);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Start pan in actor1's area, only data1 should be set
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data1.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSignalReceptionDifferentPossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Gesture possible in actor's area.
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor somewhere else
+  actor.SetPosition( 100.0f, 100.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the long press.
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // LongPress possible in empty area.
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor in to the long press position.
+  actor.SetPosition( 0.0f, 0.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the long press.
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Normal long press in actor's area for completeness.
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureEmitIncorrectState(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Clear state
+  try
+  {
+    application.ProcessEvent(GeneratePan(Gesture::Clear, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPanGestureActorUnstaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit signals
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re-add actor to stage
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Change state to Gesture::Continuing to remove
+  stateToUnstage = Gesture::Continuing;
+
+  // Emit signals
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re-add actor to stage
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Change state to Gesture::Finished to remove
+  stateToUnstage = Gesture::Finished;
+
+  // Emit signals
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully.
+  END_TEST;
+}
+
+int UtcDaliPanGestureActorStagedAndDestroyed(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Create and add a second actor so that GestureDetector destruction does not come into play.
+  Actor dummyActor( Actor::New() );
+  dummyActor.SetSize( 100.0f, 100.0f );
+  dummyActor.SetPosition( 100.0f, 100.0f );
+  dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(dummyActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.Attach(dummyActor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Here we are testing a Started actor which is removed in the Started callback, but then added back
+  // before we get a continuing state.  As we were removed from the stage, even if we're at the same
+  // position, we should still not be signalled.
+
+  // Emit signals
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re add to the stage, we should not be signalled
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Here we delete an actor in started, we should not receive any subsequent signalling.
+
+  // Emit signals
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Delete actor as well
+  actor.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GeneratePan(Gesture::Continuing, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoordsStart( 10.0f, 20.0f );
+  Vector2 screenCoordsEnd( 20.0f, 20.0f );
+
+  // Start pan within the actor's area
+  application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPanGestureBehindTouchableSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set system-overlay actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set stage actor to receive the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(stageActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoordsStart( 10.0f, 20.0f );
+  Vector2 screenCoordsEnd( 20.0f, 20.0f );
+
+  // Start pan within the two actors' area
+  application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Finished, screenCoordsStart, screenCoordsEnd, 10 ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoordsStart ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPanGestureTouchBehindGesturedSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set stage actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  stageActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set system-overlay actor to have the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach(systemOverlayActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoordsStart( 10.0f, 20.0f );
+  Vector2 screenCoordsEnd( 20.0f, 20.0f );
+
+  // Start pan within the two actors' area
+  application.ProcessEvent( GeneratePan( Gesture::Possible, screenCoordsStart, screenCoordsEnd, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started, screenCoordsStart, screenCoordsEnd, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Finished, screenCoordsStart, screenCoordsEnd, 10 ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoordsStart ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPanGestureAngleHandling(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION );
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_LEFT, Radian( Math::PI * 0.25 ) );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 1u, TEST_LOCATION );
+  bool found = false;
+  for( size_t i = 0; i < detector.GetAngleCount(); i++)
+  {
+    if( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_LEFT )
+    {
+      tet_result( TET_PASS );
+      found = true;
+      break;
+    }
+  }
+
+  if(!found )
+  {
+    tet_printf("%s, angle not added\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Radian( Math::PI * 0.25 ) );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION );
+
+  // Remove something not in the container.
+  detector.RemoveAngle( PanGestureDetector::DIRECTION_UP );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION );
+
+  detector.RemoveAngle( PanGestureDetector::DIRECTION_RIGHT );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 1u, TEST_LOCATION );
+  for ( size_t i = 0; i < detector.GetAngleCount(); i++)
+  {
+    if ( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_RIGHT )
+    {
+      tet_printf("%s, angle not removed\n", TEST_LOCATION );
+      tet_result( TET_FAIL );
+      break;
+    }
+  }
+
+  detector.ClearAngles();
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPanGestureGetAngle(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0, TEST_LOCATION );
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_LEFT );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 1, TEST_LOCATION );
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 2, TEST_LOCATION );
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_UP );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 3, TEST_LOCATION );
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_DOWN );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 4, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( detector.GetAngle(0).first,  PanGestureDetector::DIRECTION_LEFT, TEST_LOCATION );
+  DALI_TEST_EQUALS( detector.GetAngle(1).first,  PanGestureDetector::DIRECTION_RIGHT, TEST_LOCATION );
+  DALI_TEST_EQUALS( detector.GetAngle(2).first,  PanGestureDetector::DIRECTION_UP, TEST_LOCATION );
+  DALI_TEST_EQUALS( detector.GetAngle(3).first,  PanGestureDetector::DIRECTION_DOWN, TEST_LOCATION );
+
+  END_TEST;
+}
+
+inline float RadiansToDegrees( float radian )
+{
+  return radian * 180.0f / Math::PI;
+}
+
+int UtcDaliPanGestureAngleOutOfRange(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION );
+
+  //
+  // Angle
+  //
+
+  detector.AddAngle( Degree(180.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-180.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(190.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-170.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(-190.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(170.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(350.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-10.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(-350.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(370.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( Degree(-370.0f) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).first, Radian( Degree(-10.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  //
+  // Threshold
+  //
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 0.0f ) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(0.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( -10.0f ) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(10.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( -181.0f ) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(180.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+
+  detector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 181.0f ) );
+  DALI_TEST_EQUALS( detector.GetAngle(0).second, Radian( Degree(180.0f) ), 0.000001, TEST_LOCATION );
+  detector.ClearAngles();
+  END_TEST;
+}
+
+int UtcDaliPanGestureAngleProcessing(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(child);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Parent detector only requires up pans
+  PanGestureDetector parentDetector = PanGestureDetector::New();
+  parentDetector.Attach( parent );
+  parentDetector.AddAngle( PanGestureDetector::DIRECTION_UP, Degree( 30.0f ) );
+  SignalData parentData;
+  GestureReceivedFunctor parentFunctor(parentData);
+  parentDetector.DetectedSignal().Connect(&application, parentFunctor);
+
+  // Child detector only requires right pans
+  PanGestureDetector childDetector = PanGestureDetector::New();
+  childDetector.Attach( child );
+  childDetector.AddAngle( PanGestureDetector::DIRECTION_RIGHT, Degree( 30.0f ) );
+  SignalData childData;
+  GestureReceivedFunctor childFunctor(childData);
+  childDetector.DetectedSignal().Connect(&application, childFunctor);
+
+  // Generate an Up pan gesture, only parent should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10 ) );
+  DALI_TEST_EQUALS( true,  parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Right pan gesture, only child should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(30.0f, 20.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true,  childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Down pan gesture, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(20.0f, 30.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Left pan gesture, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGestureDirectionHandling(void)
+{
+  TestApplication application;
+
+  PanGestureDetector detector = PanGestureDetector::New();
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION );
+
+  detector.AddDirection( PanGestureDetector::DIRECTION_LEFT, Radian( Math::PI * 0.25 ) );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION );
+  bool found = false;
+  for ( size_t i = 0; detector.GetAngleCount(); i++)
+  {
+    if ( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_LEFT )
+    {
+      tet_result( TET_PASS );
+      found = true;
+      break;
+    }
+
+  }
+
+  if (!found )
+  {
+    tet_printf("%s, angle not added\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+
+  found = false;
+  for( size_t i = 0; i < detector.GetAngleCount(); i++)
+  {
+    if( detector.GetAngle(i).first == PanGestureDetector::DIRECTION_RIGHT )
+    {
+      tet_result( TET_PASS );
+      found = true;
+      break;
+    }
+  }
+
+  if(!found )
+  {
+    tet_printf("%s, angle not added\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+
+  // Remove something not in the container.
+  detector.RemoveDirection( PanGestureDetector::DIRECTION_UP );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 2u, TEST_LOCATION );
+
+  detector.RemoveDirection( PanGestureDetector::DIRECTION_RIGHT );
+  DALI_TEST_EQUALS( detector.GetAngleCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPanGestureDirectionProcessing(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(child);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Parent detector only requires vertical panning
+  PanGestureDetector parentDetector = PanGestureDetector::New();
+  parentDetector.Attach( parent );
+  parentDetector.AddDirection( PanGestureDetector::DIRECTION_VERTICAL, Degree( 30.0f ) );
+  SignalData parentData;
+  GestureReceivedFunctor parentFunctor(parentData);
+  parentDetector.DetectedSignal().Connect(&application, parentFunctor);
+
+  // Child detector only requires horizontal panning
+  PanGestureDetector childDetector = PanGestureDetector::New();
+  childDetector.Attach( child );
+  childDetector.AddDirection( PanGestureDetector::DIRECTION_HORIZONTAL, Degree( 30.0f ) );
+  SignalData childData;
+  GestureReceivedFunctor childFunctor(childData);
+  childDetector.DetectedSignal().Connect(&application, childFunctor);
+
+  // Generate an Up pan gesture, only parent should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(20.0f, 10.0f), 10 ) );
+  DALI_TEST_EQUALS( true,  parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Right pan gesture, only child should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(30.0f, 20.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true,  childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Down pan gesture, only parent should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(20.0f, 30.0f), 10 ) );
+  DALI_TEST_EQUALS( true,  parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a Left pan gesture, only child should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(10.0f, 20.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true,  childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a pan at -45 degrees, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(10.0f, 30.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a pan at 45 degrees, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(30.0f, 30.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a pan at 135 degrees, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(10.0f, 30.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+
+  // Generate a pan at -135 degrees, no one should receive it.
+  application.ProcessEvent( GeneratePan( Gesture::Possible, Vector2(20.0f, 20.0f), Vector2(20.0f, 20.0f), 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  Vector2(20.0f, 20.0f), Vector2(10.0f, 10.0f), 10 ) );
+  DALI_TEST_EQUALS( false, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, childData.functorCalled,  TEST_LOCATION );
+  application.ProcessEvent( GeneratePan( Gesture::Finished,  Vector2(20.0f, 30.0f), Vector2(20.0f, 20.0f), 10 ) );
+  parentData.Reset();
+  childData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGestureNoPredictionNoSmoothing(void)
+{
+  TestApplication application;
+  Integration::SetPanGesturePredictionMode(0);
+  Integration::SetPanGestureSmoothingMode(0);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 direction(Vector2::XAXIS * -5.0f);
+  Vector2 startPosition( 1.0f, 1.0f );
+  PerformSwipeGestureSwipe(application, startPosition, direction, PAN_GESTURE_UPDATE_COUNT, true);
+  DALI_TEST_EQUALS( true,  data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenPosition, startPosition + (direction * PAN_GESTURE_UPDATE_COUNT), 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,  startPosition + (direction * PAN_GESTURE_UPDATE_COUNT), 0.1f, TEST_LOCATION );
+
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGestureNoPredictionSmoothing(void)
+{
+  TestApplication application;
+  Integration::SetPanGesturePredictionMode(0);
+  Integration::SetPanGestureSmoothingMode(1);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 direction(Vector2::XAXIS * -5.0f);
+  Vector2 previousPosition( 20.0f, 20.0f );
+  Vector2 currentPosition( 20.0f, 10.0f );
+  PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true);
+  DALI_TEST_EQUALS( true,  data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  // Take into account resampling done when prediction is off.
+  DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * (PAN_GESTURE_UPDATE_COUNT - 0.25f)), 0.15f, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,  Vector2(1.0f, 1.0f) + (direction * (PAN_GESTURE_UPDATE_COUNT - 0.25f)), 0.15f, TEST_LOCATION );
+
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGesturePredictionNoSmoothing(void)
+{
+  TestApplication application;
+  Integration::SetPanGesturePredictionMode(1);
+  Integration::SetPanGestureSmoothingMode(0);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 direction(Vector2::XAXIS * -1.0f);
+  Vector2 previousPosition( 20.0f, 20.0f );
+  Vector2 currentPosition( 20.0f, 10.0f );
+  PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true);
+  DALI_TEST_EQUALS( true,  data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,  Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION );
+
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGesturePredictionSmoothing(void)
+{
+  TestApplication application;
+  Integration::SetPanGesturePredictionMode(1);
+  Integration::SetPanGestureSmoothingMode(1);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 direction(Vector2::XAXIS * -1.0f);
+  Vector2 previousPosition( 20.0f, 20.0f );
+  Vector2 currentPosition( 20.0f, 10.0f );
+  PerformSwipeGestureSwipe(application, Vector2(1.0f, 1.0f), direction, PAN_GESTURE_UPDATE_COUNT, true);
+  DALI_TEST_EQUALS( true,  data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenPosition, Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,  Vector2(1.0f, 1.0f) + (direction * PAN_GESTURE_UPDATE_COUNT), 10.0f, TEST_LOCATION );
+
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGestureSetProperties(void)
+{
+  TestApplication application;
+  TestRenderController& renderController( application.GetRenderController() );
+  Integration::SetPanGesturePredictionMode(0);
+  Integration::SetPanGestureSmoothingMode(0);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  renderController.Initialize();
+  DALI_TEST_EQUALS( renderController.WasCalled( TestRenderController::RequestUpdateFunc ), false, TEST_LOCATION );
+
+  Vector2 screenPosition( 20.0f, 20.0f );
+  Vector2 screenDisplacement( 1.0f, 1.0f );
+  Vector2 screenVelocity( 1.3f, 4.0f );
+  Vector2 localPosition( 21.0f, 21.0f );
+  Vector2 localDisplacement( 0.5f, 0.5f );
+  Vector2 localVelocity( 1.5f, 2.5f );
+
+  PanGestureDetector::SetPanGestureProperties( GeneratePan( 1u, Gesture::Started, screenPosition, localPosition, screenDisplacement, localDisplacement, screenVelocity, localVelocity ) );
+  DALI_TEST_EQUALS( renderController.WasCalled( TestRenderController::RequestUpdateFunc ), true, TEST_LOCATION );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenPosition,     screenPosition,     TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,      localPosition,      TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenDisplacement, screenDisplacement, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localDisplacement,  localDisplacement,  TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenVelocity,     screenVelocity,     TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localVelocity,      localVelocity,      TEST_LOCATION );
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGestureSetPropertiesAlreadyPanning(void)
+{
+  TestApplication application;
+  Integration::SetPanGesturePredictionMode(0);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  Property::Index property = actor.RegisterProperty( "Dummy Property", Vector3::ZERO );
+
+  ConstraintData constraintData;
+  Constraint constraint = Constraint::New<Vector3>( actor, property, PanConstraint( constraintData ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::SCREEN_VELOCITY ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_POSITION ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_DISPLACEMENT ) );
+  constraint.AddSource( Source( detector, PanGestureDetector::Property::LOCAL_VELOCITY ) );
+  constraint.Apply();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 previousPosition( 20.0f, 20.0f );
+  Vector2 currentPosition( 20.0f, 10.0f );
+  application.ProcessEvent( GeneratePan( Gesture::Possible, previousPosition, previousPosition, 10 ) );
+  application.ProcessEvent( GeneratePan( Gesture::Started,  previousPosition, currentPosition, 10 ) );
+  DALI_TEST_EQUALS( true,  data.functorCalled, TEST_LOCATION );
+
+  Vector2 screenPosition( 100.0f, 20.0f );
+  Vector2 localPosition( 110.0f, 110.0f );
+
+  PanGestureDetector::SetPanGestureProperties( GeneratePan( 1u, Gesture::Started, screenPosition, localPosition ) );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( constraintData.called, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.screenPosition, currentPosition, 0.1, TEST_LOCATION );
+  DALI_TEST_EQUALS( constraintData.localPosition,  currentPosition, 0.1f, TEST_LOCATION );
+  constraintData.Reset();
+  END_TEST;
+}
+
+int UtcDaliPanGesturePropertyIndices(void)
+{
+  TestApplication application;
+  PanGestureDetector detector = PanGestureDetector::New();
+
+  Property::IndexContainer indices;
+  detector.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() );
+  DALI_TEST_EQUALS( indices.Size(), detector.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPanGestureLayerConsumesTouch(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Add a layer to overlap the actor
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseToTop();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit signals, should receive
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Set layer to consume all touch
+  layer.SetTouchConsumed( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit the same signals again, should not receive
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliPanGestureNoTimeDiff(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a pan detector
+  PanGestureDetector detector = PanGestureDetector::New();
+  detector.Attach( actor );
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit signals, should receive
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 0));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_CHECK( !std::isinf( data.receivedGesture.velocity.x ) );
+  DALI_TEST_CHECK( !std::isinf( data.receivedGesture.velocity.y ) );
+  DALI_TEST_CHECK( !std::isinf( data.receivedGesture.screenVelocity.x ) );
+  DALI_TEST_CHECK( !std::isinf( data.receivedGesture.screenVelocity.y ) );
+  data.Reset();
+
+  data.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Path.cpp b/automated-tests/src/dali/utc-Dali-Path.cpp
new file mode 100644 (file)
index 0000000..8dc471c
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Internal;
+
+namespace
+{
+// Knots fed into Allegro, which generates control points
+static void SetupPath( Dali::Path& path)
+{
+  path.AddPoint(Vector3( 30.0,  80.0, 0.0));
+  path.AddPoint(Vector3( 70.0, 120.0, 0.0));
+  path.AddPoint(Vector3(100.0, 100.0, 0.0));
+
+  //Control points for first segment
+  path.AddControlPoint( Vector3( 39.0,  90.0, 0.0) );
+  path.AddControlPoint(Vector3( 56.0, 119.0, 0.0) );
+
+  //Control points for second segment
+  path.AddControlPoint(Vector3( 78.0, 120.0, 0.0) );
+  path.AddControlPoint(Vector3( 93.0, 104.0, 0.0) );
+}
+
+} // anonymous namespace
+
+int utcDaliPathGetPoint(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0));
+  path.AddPoint(Vector3(120.0,  70.0, 0.0));
+  path.AddPoint(Vector3(190.0, 250.0, 0.0));
+  path.AddPoint(Vector3(260.0, 260.0, 0.0));
+  path.AddPoint(Vector3(330.0, 220.0, 0.0));
+  path.AddPoint(Vector3(400.0,  50.0, 0.0));
+
+  DALI_TEST_EQUALS(path.GetPoint(0), Vector3( 50.0,  50.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(1), Vector3(120.0,  70.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(2), Vector3(190.0, 250.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(3), Vector3(260.0, 260.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(4), Vector3(330.0, 220.0, 0.0), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetPoint(5), Vector3(400.0,  50.0, 0.0), TEST_LOCATION);
+  END_TEST;
+}
+
+int utcDaliPathGetPoint02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0f));
+
+  try
+  {
+    path.GetPoint(1);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetPoint03(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+
+  try
+  {
+    path.GetPoint(0);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "index < mPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddControlPoint( Vector3(0.0f, 0.0f, 0.0) );
+  path.AddControlPoint( Vector3(108.0f, 57.0f, 0.0) );
+
+  DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3(0.0f, 0.0f, 0.0f), TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(108.0f, 57.0f, 0.0f), TEST_LOCATION);
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints01(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddControlPoint(Vector3(0.0f, 0.0f, 0.0) );
+  path.AddControlPoint(Vector3(108.0f, 57.0f, 0.0) );
+
+  try
+  {
+    path.GetControlPoint(5);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGetControlPoints02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  try
+  {
+    path.GetControlPoint(0);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "index < mControlPoint.Size()", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints01(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0));
+  path.AddPoint(Vector3(120.0,  70.0, 0.0));
+  path.AddPoint(Vector3(190.0, 250.0, 0.0));
+  path.AddPoint(Vector3(260.0, 260.0, 0.0));
+  path.AddPoint(Vector3(330.0, 220.0, 0.0));
+  path.AddPoint(Vector3(400.0,  50.0, 0.0));
+
+  path.GenerateControlPoints(0.25);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(0), Vector3( 68.0,  55.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(1), Vector3(107.0,  58.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(2), Vector3(156.0, 102.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(3), Vector3(152.0, 220.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(4), Vector3(204.0, 261.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(5), Vector3(243.0, 263.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(6), Vector3(280.0, 256.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(7), Vector3(317.0, 235.0, 0.0), 1.0, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(path.GetControlPoint(8), Vector3(360.0, 185.0, 0.0), 1.0, TEST_LOCATION);
+  DALI_TEST_EQUALS(path.GetControlPoint(9), Vector3(383.0,  93.0, 0.0), 1.0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int utcDaliPathGetPointCount(void)
+{
+  TestApplication application;
+  Dali::Path path = Dali::Path::New();
+
+  DALI_TEST_EQUALS(path.GetPointCount(), 0u, TEST_LOCATION);
+
+  path.AddPoint(Vector3( 50.0,  50.0, 0.0));
+  path.AddPoint(Vector3(120.0,  70.0, 0.0));
+  path.AddPoint(Vector3(190.0, 250.0, 0.0));
+  path.AddPoint(Vector3(260.0, 260.0, 0.0));
+
+  DALI_TEST_EQUALS(path.GetPointCount(), 4u, TEST_LOCATION);
+
+  path.AddPoint(Vector3(330.0, 220.0, 0.0));
+  path.AddPoint(Vector3(400.0,  50.0, 0.0));
+
+  DALI_TEST_EQUALS(path.GetPointCount(), 6u, TEST_LOCATION);
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints02(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  try
+  {
+    path.GenerateControlPoints(0.25);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int utcDaliPathGenerateControlPoints03(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  path.AddPoint(Vector3(400.0,  50.0, 0.0f));
+  try
+  {
+    path.GenerateControlPoints(0.25);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "numSegments > 0", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliPathSample01(void)
+{
+  TestApplication application;
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  //t = 0
+  Vector3 position, tangent;
+  path.Sample(0.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  //t = 0.25
+  path.Sample(0.25f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  48.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  // t = 0.5
+  path.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  70.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  1.0f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.0f, 0.1f, TEST_LOCATION);
+
+
+  //t = 0.75
+  path.Sample(0.75f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  85.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.7f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.6f, 0.1f, TEST_LOCATION);
+
+  // t = 1
+  path.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.8f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.4f, 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliPathDownCast(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  Handle handle = path;
+  SetupPath(path);
+
+  Dali::Path path2 = Dali::Path::DownCast(handle);
+  DALI_TEST_CHECK(path2);
+
+  //t = 0
+  Vector3 position, tangent;
+  path2.Sample(0.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  //t = 0.25
+  path2.Sample(0.25f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  48.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  // t = 0.5
+  path2.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  70.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  1.0f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.0f, 0.1f, TEST_LOCATION);
+
+
+  //t = 0.75
+  path2.Sample(0.75f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  85.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.7f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.6f, 0.1f, TEST_LOCATION);
+
+  // t = 1
+  path2.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.8f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.4f, 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliPathAssignment(void)
+{
+  TestApplication application;
+
+  Dali::Path path = Dali::Path::New();
+  SetupPath(path);
+
+  Dali::Path path2;
+  path2 = path;
+  DALI_TEST_CHECK(path2);
+
+  //t = 0
+  Vector3 position, tangent;
+  path2.Sample(0.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 30.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 80.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  //t = 0.25
+  path2.Sample(0.25f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  48.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 102.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.6f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.7f, 0.1f, TEST_LOCATION);
+
+  // t = 0.5
+  path2.Sample(0.5f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  70.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 120.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  1.0f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  0.0f, 0.1f, TEST_LOCATION);
+
+
+  //t = 0.75
+  path2.Sample(0.75f, position, tangent );
+  DALI_TEST_EQUALS(position.x,  85.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 112.0f, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.7f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.6f, 0.1f, TEST_LOCATION);
+
+  // t = 1
+  path2.Sample(1.0f, position, tangent );
+  DALI_TEST_EQUALS(position.x, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(position.y, 100.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.x,  0.8f, 0.1f, TEST_LOCATION);
+  DALI_TEST_EQUALS(tangent.y,  -0.4f, 0.1f, TEST_LOCATION);
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PinchGesture.cpp b/automated-tests/src/dali/utc-Dali-PinchGesture.cpp
new file mode 100644 (file)
index 0000000..3058f1f
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_pinch_gesture_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pinch_gesture_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+// Positive test case for a method
+int UtcDaliPinchGestureConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  PinchGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION);
+
+  PinchGesture gesture2(Gesture::Continuing);
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture2.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture2.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture2.type, TEST_LOCATION);
+
+  PinchGesture gesture3(Gesture::Finished);
+  DALI_TEST_EQUALS(Gesture::Finished, gesture3.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture3.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture3.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture3.type, TEST_LOCATION);
+
+  // Test copy constructor
+  gesture3.scale = 3.0f;
+  gesture3.speed = 5.0f;
+
+  PinchGesture pinch(gesture3);
+  DALI_TEST_EQUALS(Gesture::Finished, pinch.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(3.0f, pinch.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, pinch.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, pinch.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureAssignment(void)
+{
+  // Test Assignment operator
+  PinchGesture gesture(Gesture::Started);
+  DALI_TEST_EQUALS(Gesture::Started, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION);
+
+  PinchGesture gesture2(Gesture::Continuing);
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture2.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture2.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture2.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture2.type, TEST_LOCATION);
+
+  gesture2.scale = 3.0f;
+  gesture2.speed = 5.0f;
+
+  gesture = gesture2;
+  DALI_TEST_EQUALS(Gesture::Continuing, gesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(3.0f, gesture.scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, gesture.speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDynamicAllocation(void)
+{
+  PinchGesture* gesture = new PinchGesture( Gesture::Started );
+  DALI_TEST_EQUALS(Gesture::Started, gesture->state, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture->scale, TEST_LOCATION);
+  DALI_TEST_EQUALS(0.0f, gesture->speed, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Pinch, gesture->type, TEST_LOCATION);
+  delete gesture;
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-PinchGestureDetector.cpp
new file mode 100644 (file)
index 0000000..5fb8b27
--- /dev/null
@@ -0,0 +1,1379 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/pinch-gesture-event.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+#include <test-touch-utils.h>
+
+using namespace Dali;
+
+void utc_dali_pinch_gesture_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pinch_gesture_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled(false),
+    voidFunctorCalled(false),
+    receivedGesture(Gesture::Started)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+    voidFunctorCalled = false;
+
+    receivedGesture.state = Gesture::Started;
+    receivedGesture.scale = 0.0f;
+    receivedGesture.speed = 0.0f;
+    receivedGesture.screenCenterPoint = Vector2(0.0f, 0.0f);
+    receivedGesture.localCenterPoint = Vector2(0.0f, 0.0f);
+
+    pinchedActor.Reset();
+  }
+
+  bool functorCalled;
+  bool voidFunctorCalled;
+  PinchGesture receivedGesture;
+  Actor pinchedActor;
+};
+
+// Functor that sets the data when called
+struct GestureReceivedFunctor
+{
+  GestureReceivedFunctor(SignalData& data) : signalData(data) { }
+
+  void operator()(Actor actor, const PinchGesture& pinch)
+  {
+    signalData.functorCalled = true;
+    signalData.receivedGesture = pinch;
+    signalData.pinchedActor = actor;
+  }
+
+  void operator()()
+  {
+    signalData.voidFunctorCalled = true;
+  }
+
+  SignalData& signalData;
+};
+
+// Functor that removes the gestured actor from stage
+struct UnstageActorFunctor : public GestureReceivedFunctor
+{
+  UnstageActorFunctor( SignalData& data, Gesture::State& stateToUnstage )
+  : GestureReceivedFunctor( data ),
+    stateToUnstage( stateToUnstage )
+  {
+  }
+
+  void operator()( Actor actor, const PinchGesture& pinch )
+  {
+    GestureReceivedFunctor::operator()( actor, pinch );
+
+    if ( pinch.state == stateToUnstage )
+    {
+      Stage::GetCurrent().Remove( actor );
+    }
+  }
+
+  Gesture::State& stateToUnstage;
+};
+
+// Functor for receiving a touch event
+struct TouchEventFunctor
+{
+  bool operator()(Actor actor, const TouchEvent& touch)
+  {
+    return false;
+  }
+};
+
+// Generate a PinchGestureEvent to send to Core
+Integration::PinchGestureEvent GeneratePinch(
+    Gesture::State state,
+    float scale,
+    float speed,
+    Vector2 centerpoint)
+{
+  Integration::PinchGestureEvent pinch(state);
+
+  pinch.scale = scale;
+  pinch.speed = speed;
+  pinch.centerPoint = centerpoint;
+
+  return pinch;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliPinchGestureDetectorConstructor(void)
+{
+  TestApplication application;
+
+  PinchGestureDetector detector;
+  DALI_TEST_CHECK(!detector);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDetectorCopyConstructorP(void)
+{
+  TestApplication application;
+
+  PinchGestureDetector detector = PinchGestureDetector::New();;
+
+  PinchGestureDetector copy( detector );
+  DALI_TEST_CHECK( detector );
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDetectorAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  PinchGestureDetector detector = PinchGestureDetector::New();;
+
+  PinchGestureDetector assign;
+  assign = detector;
+  DALI_TEST_CHECK( detector );
+
+  DALI_TEST_CHECK( detector == assign );
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDetectorNew(void)
+{
+  TestApplication application;
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+
+  DALI_TEST_CHECK(detector);
+
+  // Attach an actor and emit a touch event on the actor to ensure complete line coverage
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  detector.Attach(actor);
+
+  Integration::TouchEvent touchEvent(1);
+  TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f);
+  touchEvent.AddPoint(point);
+  application.ProcessEvent(touchEvent);
+
+  TouchPoint point2(1, TouchPoint::Down, 20.0f, 20.0f, 20.0f, 20.0f);
+  touchEvent.AddPoint(point2);
+  application.ProcessEvent(touchEvent);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDetectorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::PinchGestureDetector::DownCast()");
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+
+  BaseHandle object(detector);
+
+  PinchGestureDetector detector2 = PinchGestureDetector::DownCast(object);
+  DALI_TEST_CHECK(detector2);
+
+  PinchGestureDetector detector3 = DownCast< PinchGestureDetector >(object);
+  DALI_TEST_CHECK(detector3);
+
+  BaseHandle unInitializedObject;
+  PinchGestureDetector detector4 = PinchGestureDetector::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!detector4);
+
+  PinchGestureDetector detector5 = DownCast< PinchGestureDetector >(unInitializedObject);
+  DALI_TEST_CHECK(!detector5);
+
+  GestureDetector detector6 = PinchGestureDetector::New();
+  PinchGestureDetector detector7 = PinchGestureDetector::DownCast(detector6);
+  DALI_TEST_CHECK(detector7);
+  END_TEST;
+}
+
+// Negative test case for a method
+int UtcDaliPinchGestureSignalReceptionNegative(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do a pinch outside actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 45.0f, Vector2(112.0f, 112.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Continue pinch into actor's area - we should still not receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 4.5f, 95.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Stop pinching - we should still not receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(12.0f, 12.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionDownMotionLeave(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pan within the actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Continue the pan within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 90.0f, Vector2(21.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(90.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(21.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Pan Gesture leaves actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 15.5f, Vector2(320.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(15.5f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(320.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Gesture ends - we would receive a finished state
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 15.2f, 12.1f, Vector2(310.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(15.2f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(12.1f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(310.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionDownMotionUp(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch within the actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Continue the pinch within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(25.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Gesture ends within actor's area - we would receive a finished state
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(25.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(20.0f, 20.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionCancelled(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch within the actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+
+
+  // Continue the pinch within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+
+  // The gesture is cancelled
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Cancelled, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Cancelled, data.receivedGesture.state, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionDetach(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch within the actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+
+
+  // Continue the pinch within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Finished, data.receivedGesture.state, TEST_LOCATION);
+
+  // Detach actor
+  detector.DetachAll();
+
+  // Ensure we are no longer signalled
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionDetachWhilePinching(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch within the actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+
+  // Continue the pinch within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+
+  // Detach actor during the pinch, we should not receive the next event
+  detector.DetachAll();
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionActorDestroyedWhilePinching(void)
+{
+  TestApplication application;
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Attach a temporary actor to stop detector being removed from PinchGestureProcessor when main actor
+  // is destroyed.
+  Actor tempActor = Actor::New();
+  tempActor.SetSize(100.0f, 100.0f);
+  tempActor.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(tempActor);
+  detector.Attach(tempActor);
+
+  // Actor lifetime is scoped
+  {
+    Actor actor = Actor::New();
+    actor.SetSize(100.0f, 100.0f);
+    actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    Stage::GetCurrent().Add(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+
+    detector.Attach(actor);
+
+    // Start pinch within the actor's area
+    application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(Gesture::Started, data.receivedGesture.state, TEST_LOCATION);
+
+    // Continue the pinch within the actor's area - we should still receive the signal
+    data.Reset();
+    application.ProcessEvent(GeneratePinch(Gesture::Continuing, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(Gesture::Continuing, data.receivedGesture.state, TEST_LOCATION);
+
+    // Remove the actor from stage and reset the data
+    Stage::GetCurrent().Remove(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+  }
+
+  // Actor should now have been destroyed
+
+  // Gesture ends within the area where the actor used to be
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 25.0f, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionRotatedActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify a couple of times
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do an entire pinch, only check finished value
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Rotate actor again and render and notify
+  actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do an entire pinch, only check finished value
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Rotate actor again and render and notify
+  actor.SetOrientation(Dali::Degree(270.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do an entire pinch, only check finished value
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(10.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionChildHit(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  // Set child to completely cover parent.
+  // Change rotation of child to be different from parent so that we can check if our local coordinate
+  // conversion of the parent actor is correct.
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  parent.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(parent);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do an entire pan, only check finished value - hits child area but parent should still receive it
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, parent == data.pinchedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+
+  // Attach child and generate same touch points to yield same results
+  // (Also proves that you can detach and then re-attach another actor)
+  detector.Attach(child);
+  detector.Detach(parent);
+
+  // Do an entire pan, only check finished value
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, child == data.pinchedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(5.0f, data.receivedGesture.scale, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(50.0f, data.receivedGesture.speed, 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(10.0f, 10.0f), data.receivedGesture.screenCenterPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionAttachDetachMany(void)
+{
+  TestApplication application;
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetX(100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(first);
+  detector.Attach(second);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch within second actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.pinchedActor, TEST_LOCATION);
+
+  // Pinch moves into first actor's area - second actor should receive the pinch
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.pinchedActor, TEST_LOCATION);
+
+  // Detach the second actor during the pinch, we should not receive the next event
+  detector.Detach(second);
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionActorBecomesUntouchable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start pinch in actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Pan continues within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 5.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Actor become invisible - actor should not receive the next pinch
+  actor.SetVisible(false);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Gesture ends within actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 5.0f, 50.0f, Vector2(10.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionMultipleDetectorsOnActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  Actor actor2 = Actor::New();
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(actor2);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to one detector
+  SignalData firstData;
+  GestureReceivedFunctor firstFunctor(firstData);
+  PinchGestureDetector firstDetector = PinchGestureDetector::New();
+  firstDetector.Attach(actor);
+  firstDetector.DetectedSignal().Connect(&application, firstFunctor);
+
+  // Attach actor to another detector
+  SignalData secondData;
+  GestureReceivedFunctor secondFunctor(secondData);
+  PinchGestureDetector secondDetector = PinchGestureDetector::New();
+  secondDetector.Attach(actor);
+  secondDetector.DetectedSignal().Connect(&application, secondFunctor);
+
+  // Add second actor to second detector, when we remove the actor, this will make sure that this
+  // gesture detector is not removed from the GestureDetectorProcessor.  In this scenario, the
+  // functor should still not be called (which is what we're also testing).
+  secondDetector.Attach(actor2);
+
+  // Pinch in actor's area - both detector's functors should be called
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Pinch continues in actor's area - both detector's functors should be called
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Detach actor from firstDetector and emit pinch on actor, only secondDetector's functor should be called.
+  firstDetector.Detach(actor);
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // New pinch on actor, only secondDetector has actor attached
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+
+  // Detach actor from secondDetector
+  secondDetector.Detach(actor);
+  firstData.Reset();
+  secondData.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(false, secondData.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionMultipleStarted(void)
+{
+  // Should handle two started events gracefully.
+
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Start pan in actor's area
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Send another start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Add a child actor to overlap actor and send another start in actor's area
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  actor.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Send another start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Send another start in actor's area
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSignalReceptionEnsureCorrectSignalling(void)
+{
+  TestApplication application;
+
+  Actor actor1 = Actor::New();
+  actor1.SetSize(100.0f, 100.0f);
+  actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor1);
+  SignalData data1;
+  GestureReceivedFunctor functor1(data1);
+  PinchGestureDetector detector1 = PinchGestureDetector::New();
+  detector1.Attach(actor1);
+  detector1.DetectedSignal().Connect(&application, functor1);
+
+  Actor actor2 = Actor::New();
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::BOTTOM_RIGHT);
+  actor2.SetParentOrigin(ParentOrigin::BOTTOM_RIGHT);
+  Stage::GetCurrent().Add(actor2);
+  SignalData data2;
+  GestureReceivedFunctor functor2(data2);
+  PinchGestureDetector detector2 = PinchGestureDetector::New();
+  detector2.Attach(actor2);
+  detector2.DetectedSignal().Connect(&application, functor2);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Start pan in actor1's area, only data1 should be set
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data1.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(false, data2.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureEmitIncorrectStateClear(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Clear state
+  try
+  {
+    application.ProcessEvent(GeneratePinch(Gesture::Clear, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPinchGestureEmitIncorrectStatePossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Possible state
+  try
+  {
+    application.ProcessEvent(GeneratePinch(Gesture::Possible, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPinchGestureActorUnstaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit signals
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re-add actor to stage
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Change state to Gesture::Continuing to remove
+  stateToUnstage = Gesture::Continuing;
+
+  // Emit signals
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re-add actor to stage
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Change state to Gesture::Continuing to remove
+  stateToUnstage = Gesture::Finished;
+
+  // Emit signals
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  tet_result( TET_PASS ); // If we get here then we have handled actor stage removal gracefully.
+  END_TEST;
+}
+
+int UtcDaliPinchGestureActorStagedAndDestroyed(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Create and add a second actor so that GestureDetector destruction does not come into play.
+  Actor dummyActor( Actor::New() );
+  dummyActor.SetSize( 100.0f, 100.0f );
+  dummyActor.SetPosition( 100.0f, 100.0f );
+  dummyActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(dummyActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // State to remove actor in.
+  Gesture::State stateToUnstage( Gesture::Started );
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data, stateToUnstage );
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.Attach(dummyActor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Here we are testing a Started actor which is removed in the Started callback, but then added back
+  // before we get a continuing state.  As we were removed from the stage, even if we're at the same
+  // position, we should still not be signalled.
+
+  // Emit signals
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Re add to the stage, we should not be signalled
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Here we delete an actor in started, we should not receive any subsequent signalling.
+
+  // Emit signals
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Delete actor as well
+  actor.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Continue signal emission
+  application.ProcessEvent(GeneratePinch(Gesture::Continuing, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GeneratePinch(Gesture::Finished, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+  float scale ( 10.0f );
+  float speed ( 50.0f );
+
+  // Start pan within the actor's area
+  application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPinchGestureBehindTouchableSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set system-overlay actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set stage actor to receive the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(stageActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+  float scale ( 10.0f );
+  float speed ( 50.0f );
+
+  // Start pinch within the two actors' area
+  application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+  application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPinchGestureTouchBehindGesturedSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set stage actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  stageActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set system-overlay actor to have the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(systemOverlayActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+  float scale ( 10.0f );
+  float speed ( 50.0f );
+
+  // Start pinch within the two actors' area
+  application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+  application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPinchGestureLayerConsumesTouch(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a detector
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+  PinchGestureDetector detector = PinchGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Add a layer to overlap the actor
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseToTop();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+  float scale ( 10.0f );
+  float speed ( 50.0f );
+
+  // Emit signals, should receive
+  application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+  application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Set layer to consume all touch
+  layer.SetTouchConsumed( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit the same signals again, should not receive
+  application.ProcessEvent( GeneratePinch( Gesture::Started, scale, speed, screenCoords ) );
+  application.ProcessEvent( GeneratePinch( Gesture::Finished, scale, speed, screenCoords ) );
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Pixel.cpp b/automated-tests/src/dali/utc-Dali-Pixel.cpp
new file mode 100644 (file)
index 0000000..78a3436
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using std::max;
+using namespace Dali;
+
+
+static const float ROTATION_EPSILON = 0.0001f;
+
+void utc_dali_pixel_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_pixel_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+static void TestPixelEnumSize(const int size)
+{
+  DALI_TEST_CHECK( (static_cast<int>( Pixel::LAST_VALID_PIXEL_FORMAT ) - static_cast<int>( Pixel::FIRST_VALID_PIXEL_FORMAT ) + 1 ) == size &&
+      "The Pixel::Format enum may have had new formats added. Expand the test cases to include them.");
+}
+
+int UtcDaliPixelHasAlpha(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliPixelHasAlpha");
+
+  TestPixelEnumSize( 26 );
+
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::L8) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB565) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB888) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGB8888) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGR8888) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGR565) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_R11_EAC) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SIGNED_R11_EAC) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RG11_EAC) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SIGNED_RG11_EAC) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB8_ETC2) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_SRGB8_ETC2) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB8_ETC1) == false);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1) == false);
+
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::A8) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::LA88) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA5551) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA4444) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::RGBA8888) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA8888) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA5551) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha(Pixel::BGRA4444) == true);
+  DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ) == true );
+  DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 ) == true );
+  DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_RGBA8_ETC2_EAC ) == true );
+  DALI_TEST_CHECK( Pixel::HasAlpha( Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) == true );
+
+  END_TEST;
+}
+
+int UtcDaliPixelHasAlphaN(void)
+{
+  DALI_TEST_EQUALS( Pixel::HasAlpha( Pixel::Format( 123123123123 ) ), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPixelGetBytesPerPixel(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliPixelGetBytesPerPixel");
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::L8) == 1);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::A8) == 1);
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::LA88) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB565) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA5551) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA4444) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGR565) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA5551) == 2);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA4444) == 2);
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB888) == 3);
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGB8888) == 4);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGR8888) == 4);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::RGBA8888) == 4);
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::BGRA8888) == 4);
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::L8) == 1);
+
+  DALI_TEST_CHECK( Pixel::GetBytesPerPixel(Pixel::COMPRESSED_R11_EAC) == 0);
+
+  END_TEST;
+}
+
+int UtcDaliPixelGetBytesPerPixelN(void)
+{
+  DALI_TEST_EQUALS( Pixel::GetBytesPerPixel( Pixel::Format( 123123123123 ) ), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPixelGetAlphaOffsetAndMask(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliPixelGetAlphaOffsetAndMask");
+
+  int byteOffset = 0;
+  int bitMask = 0;
+
+  // Be sure that the number of cases tested below is correct:
+  TestPixelEnumSize( 26 );
+
+  Pixel::GetAlphaOffsetAndMask(Pixel::L8, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::A8, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0xff);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGB888, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGB565, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGB8888, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::BGR8888, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::LA88, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0xff);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGBA4444, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x0f);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGBA5551, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x01);
+  Pixel::GetAlphaOffsetAndMask(Pixel::RGBA8888, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 3 && bitMask == 0xff);
+  Pixel::GetAlphaOffsetAndMask(Pixel::BGRA8888, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 3 && bitMask == 0xff);
+  Pixel::GetAlphaOffsetAndMask(Pixel::BGR565, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::BGRA4444, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x0f);
+  Pixel::GetAlphaOffsetAndMask(Pixel::BGRA5551, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 1 && bitMask == 0x01);
+
+  // Compressed formats with no meaningful result:
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_R11_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SIGNED_R11_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RG11_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SIGNED_RG11_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_ETC2, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_ETC2, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_ETC1, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB_PVRTC_4BPPV1, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_RGBA8_ETC2_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  Pixel::GetAlphaOffsetAndMask(Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, byteOffset, bitMask);
+  DALI_TEST_CHECK( byteOffset == 0 && bitMask == 0);
+  END_TEST;
+}
+
+int UtcDaliPixelGetAlphaOffsetAndMaskN(void)
+{
+  int byteOffset = 200;
+  int bitMask = 200;
+  Pixel::GetAlphaOffsetAndMask( Pixel::Format( 123123123123 ), byteOffset, bitMask );
+  DALI_TEST_CHECK( byteOffset == 200 );
+  DALI_TEST_CHECK( bitMask == 200 );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PropertyArray.cpp b/automated-tests/src/dali/utc-Dali-PropertyArray.cpp
new file mode 100644 (file)
index 0000000..f55004b
--- /dev/null
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_property_array_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_property_array_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliPropertyArrayPushBackP(void)
+{
+  Property::Array array;
+
+  DALI_TEST_CHECK( 0 == array.Size() );
+
+  array.PushBack( 1 );
+
+  DALI_TEST_CHECK( 1 == array.Size() );
+
+  DALI_TEST_CHECK( array[0].Get<int>() == 1 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayCapacityP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( 3 == array.Capacity() );
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayReserveP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( 3 == array.Capacity() );
+  DALI_TEST_CHECK( 0 == array.Size() );
+
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+  END_TEST;
+}
+
+int UtcDaliPropertyArraySizeP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( 0 == array.Capacity() );
+  DALI_TEST_CHECK( 0 == array.Size() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( 3 == array.Capacity() );
+  DALI_TEST_CHECK( 0 == array.Size() );
+
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+
+  DALI_TEST_CHECK( 3 == array.Size() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayCountP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( 0 == array.Capacity() );
+  DALI_TEST_CHECK( 0 == array.Count() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( 3 == array.Capacity() );
+  DALI_TEST_CHECK( 0 == array.Count() );
+
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+
+  DALI_TEST_CHECK( 3 == array.Count() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayEmptyP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+
+  DALI_TEST_CHECK( !array.Empty() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayClearP(void)
+{
+  Property::Array array;
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.Reserve(3);
+
+  DALI_TEST_CHECK( array.Empty() );
+
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+
+  DALI_TEST_CHECK( !array.Empty() );
+
+  array.Clear();
+
+  DALI_TEST_CHECK( array.Empty() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayIndexOperatorP(void)
+{
+  Property::Array array;
+
+  array.Reserve(3);
+  array.PushBack( 1 );
+  array.PushBack( "world" );
+  array.PushBack( 3 );
+
+  DALI_TEST_CHECK( array[0].Get<int>() == 1 );
+  DALI_TEST_CHECK( array[1].Get<std::string>() == "world" );
+  DALI_TEST_CHECK( array[2].Get<int>() == 3 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayConstIndexOperatorP(void)
+{
+  Property::Array anArray;
+
+  anArray.Reserve(3);
+  anArray.PushBack( 1 );
+  anArray.PushBack( "world" );
+  anArray.PushBack( 3 );
+
+  const Property::Array array(anArray);
+
+  DALI_TEST_CHECK( array[0].Get<int>() == 1 );
+  DALI_TEST_CHECK( array[1].Get<std::string>() == "world" );
+  DALI_TEST_CHECK( array[2].Get<int>() == 3 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayAssignmentOperatorP(void)
+{
+  Property::Array anArray;
+
+  anArray.Reserve(3);
+  anArray.PushBack( 1 );
+  anArray.PushBack( "world" );
+  anArray.PushBack( 3 );
+
+  Property::Array array = anArray;
+
+  DALI_TEST_CHECK( array[0].Get<int>() == 1 );
+  DALI_TEST_CHECK( array[1].Get<std::string>() == "world" );
+  DALI_TEST_CHECK( array[2].Get<int>() == 3 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyArrayResize(void)
+{
+  Property::Array array;
+
+  array.Resize(3);
+  DALI_TEST_CHECK( array.Count() == 3 );
+
+  array.Resize(5);
+  DALI_TEST_CHECK( array.Count() == 5 );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PropertyMap.cpp b/automated-tests/src/dali/utc-Dali-PropertyMap.cpp
new file mode 100644 (file)
index 0000000..4867179
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_property_map_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_property_map_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliPropertyMapPopulate(void)
+{
+  Property::Map map;
+  DALI_TEST_CHECK( map.Empty() );
+
+  map[ "hello" ] = 1;
+  map[ "world" ] = "world";
+  map[ "world" ] = 3; // same item as line above
+  DALI_TEST_CHECK( !map.Empty() ); // Should no longer be empty
+  DALI_TEST_CHECK( map.Count() == 2 ); // Should only have two items, not three!!
+  DALI_TEST_CHECK( map["hello"].Get<int>() == 1 );
+  DALI_TEST_CHECK( map["world"].Get<int>() == 3 );
+
+  map.Clear();
+  DALI_TEST_CHECK( map.Empty() );
+  END_TEST;
+}
+
+int UtcDaliPropertyMapCopyAndAssignment(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  Property::Map assignedMap;
+  assignedMap[ "foo" ] = 3;
+  DALI_TEST_CHECK( assignedMap.Count() == 1 );
+  assignedMap = map;
+  DALI_TEST_CHECK( assignedMap.Count() == 2 );
+
+  Property::Map copiedMap( map );
+  DALI_TEST_CHECK( copiedMap.Count() == 2 );
+
+  // Self assignment
+  DALI_TEST_CHECK( map.Count() == 2 );
+  map = map;
+  DALI_TEST_CHECK( map.Count() == 2 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapConstOperator(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+  DALI_TEST_CHECK( map.Count() == 2 );
+
+  const Property::Map& constMap( map );
+  DALI_TEST_CHECK( constMap[ "world" ].Get<int>() == 2 );
+  DALI_TEST_CHECK( constMap.Count() == 2 ); // Ensure count hasn't gone up
+
+  // Invalid Key
+  try
+  {
+    constMap[ "invalid-key" ];
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Invalid Key\"", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapGetValue(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  Property::Value& value = map.GetValue( 0 );
+  DALI_TEST_CHECK( value.Get<int>() == 1 );
+  value = 10; // Allows the actual changing of the value as we have a ref
+  DALI_TEST_CHECK( map[ "hello" ].Get<int>() == 10 );
+
+  // Out of bounds
+  try
+  {
+    map.GetValue( 2 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapGetKey(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  DALI_TEST_CHECK( map.GetKey( 0 ) == "hello" );
+  DALI_TEST_CHECK( map.GetKey( 1 ) == "world" );
+
+  // Out of bounds
+  try
+  {
+    map.GetKey( 2 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapGetPair(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  DALI_TEST_CHECK( map.GetPair( 0 ).first == "hello" );
+  DALI_TEST_CHECK( map.GetPair( 0 ).second.Get< int >() == 1 );
+  DALI_TEST_CHECK( map.GetPair( 1 ).first == "world" );
+  DALI_TEST_CHECK( map.GetPair( 1 ).second.Get< int >() == 2 );
+
+  // Out of bounds
+  try
+  {
+    map.GetPair( 2 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "position", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapFind(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  Property::Value* value = NULL;
+
+  value = map.Find( "hello" );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK( value->Get<int>() == 1 );
+
+  value = map.Find( "world" );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_CHECK( value->Get<int>() == 2 );
+
+  value = map.Find( "invalid-key" );
+  DALI_TEST_CHECK( !value );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapInsertP(void)
+{
+  Property::Map map;
+  DALI_TEST_EQUALS( 0, map.Count(), TEST_LOCATION );
+  map.Insert( "foo", "bar");
+  DALI_TEST_EQUALS( 1, map.Count(), TEST_LOCATION );
+  Property::Value* value = map.Find( "foo" );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_EQUALS( "bar", value->Get<std::string>(), TEST_LOCATION );
+  map.Insert( std::string("foo2"), "testing" );
+  DALI_TEST_EQUALS( 2, map.Count(), TEST_LOCATION );
+  value = map.Find( "foo2" );
+  DALI_TEST_CHECK( value );
+  DALI_TEST_EQUALS( "testing", value->Get<std::string>(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyMapMerge(void)
+{
+  Property::Map map;
+  map[ "hello" ] = 1;
+  map[ "world" ] = 2;
+
+  DALI_TEST_CHECK( map.Count() == 2 );
+
+  // Create another map with the same keys but different values
+  Property::Map map2;
+  map[ "hello" ] = 3;
+  map[ "world" ] = 4;
+
+  // Merge map2 into map1, count should still be 2, map values should be from map2
+  map.Merge( map2 );
+  DALI_TEST_CHECK( map.Count() == 2 );
+  DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 );
+  DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 );
+
+  // Create another map with different keys
+  Property::Map map3;
+  map3[ "foo" ] = 5;
+  map3[ "bar" ] = 6;
+
+  // Merge map3 into map1, count should increase, existing values should match previous and new values should match map3
+  map.Merge( map3 );
+  DALI_TEST_CHECK( map.Count() == 4 );
+  DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 );
+  DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 );
+  DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 );
+  DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 );
+
+  // Create an empty map and attempt to merge, should be successful, nothing should change
+  Property::Map map4;
+  DALI_TEST_CHECK( map4.Empty() );
+  map.Merge( map4 );
+  DALI_TEST_CHECK( map4.Empty() );
+  DALI_TEST_CHECK( map.Count() == 4 );
+  DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 );
+  DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 );
+  DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 );
+  DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 );
+
+  // Merge map into map4, map4 should be the same as map now.
+  map4.Merge( map );
+  DALI_TEST_CHECK( map4.Count() == 4 );
+  DALI_TEST_CHECK( map4[ "hello" ].Get< int >() == 3 );
+  DALI_TEST_CHECK( map4[ "world"].Get< int >() == 4 );
+  DALI_TEST_CHECK( map4[ "foo"].Get< int >() == 5 );
+  DALI_TEST_CHECK( map4[ "bar"].Get< int >() == 6 );
+
+  // Attempt to merge into itself, should be successful, nothing should change
+  map.Merge( map );
+  DALI_TEST_CHECK( map.Count() == 4 );
+  DALI_TEST_CHECK( map[ "hello" ].Get< int >() == 3 );
+  DALI_TEST_CHECK( map[ "world"].Get< int >() == 4 );
+  DALI_TEST_CHECK( map[ "foo"].Get< int >() == 5 );
+  DALI_TEST_CHECK( map[ "bar"].Get< int >() == 6 );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PropertyNotification.cpp b/automated-tests/src/dali/utc-Dali-PropertyNotification.cpp
new file mode 100644 (file)
index 0000000..690e6c4
--- /dev/null
@@ -0,0 +1,879 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_property_notification_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_property_notification_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace {
+
+static bool gCallBackCalled;
+
+static void TestCallback(PropertyNotification& source)
+{
+  gCallBackCalled = true;
+}
+
+const int RENDER_FRAME_INTERVAL(16);                           ///< Duration of each frame in ms. (at approx 60FPS)
+const int DEFAULT_WAIT_PERIOD(100);                            ///< Default waiting period for check.
+
+
+class TestClass : public ConnectionTracker
+{
+public:
+
+  TestClass()
+  {
+  }
+
+  ~TestClass()
+  {
+  }
+
+  void Initialize()
+  {
+    mActor = Actor::New();
+    Stage::GetCurrent().Add( mActor );
+    mNotification = mActor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(100.0f) );
+    mNotification.NotifySignal().Connect( this, &TestClass::OnPropertyNotify );
+  }
+
+  void RemovePropertyNotification()
+  {
+    mActor.RemovePropertyNotification( mNotification );
+  }
+
+  void RemovePropertyNotifications()
+  {
+    mActor.RemovePropertyNotifications();
+  }
+
+  void Terminate()
+  {
+    Stage::GetCurrent().Remove( mActor );
+    mActor.Reset();
+    mNotification.Reset();
+  }
+
+  void OnPropertyNotify( PropertyNotification& source )
+  {
+    tet_infoline(" OnPropertyNotify");
+    gCallBackCalled = true;
+  }
+
+  Actor mActor;
+  PropertyNotification mNotification;
+};
+
+
+/*
+ * Simulate time passed by.
+ *
+ * @note this will always process at least 1 frame (1/60 sec)
+ *
+ * @param application Test application instance
+ * @param duration Time to pass in milliseconds.
+ * @return The actual time passed in milliseconds
+ */
+int Wait(TestApplication& application, int duration = 0)
+{
+  int time = 0;
+
+  for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++)
+  {
+    application.SendNotification();
+    application.Render(RENDER_FRAME_INTERVAL);
+    time += RENDER_FRAME_INTERVAL;
+  }
+
+  return time;
+}
+
+} // unnamed namespace
+
+
+// Positive test case for a method
+int UtcDaliPropertyNotificationDownCast(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationDownCast");
+
+  Actor actor = Actor::New();
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f));
+  BaseHandle handle = notification;
+  PropertyNotification notificationHandle;
+
+  DALI_TEST_CHECK(notification);
+  DALI_TEST_CHECK(handle);
+  DALI_TEST_CHECK(!notificationHandle);
+
+  notificationHandle = PropertyNotification::DownCast( handle );
+  DALI_TEST_CHECK(notificationHandle);
+  END_TEST;
+}
+
+
+// Negative test case for a method
+int UtcDaliPropertyNotificationDownCastNegative(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationDownCastNegative");
+
+  // Create something derived from BaseHandle other than a PropertyNotification.
+  Actor somethingElse = Actor::New();
+
+  Actor actor = Actor::New();
+  actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f));
+  BaseHandle handle = somethingElse;
+  PropertyNotification notificationHandle;
+
+  notificationHandle = PropertyNotification::DownCast( handle );
+  DALI_TEST_CHECK(!notificationHandle);
+  END_TEST;
+}
+
+int UtcDaliAddPropertyNotification(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+  tet_infoline(" UtcDaliAddPropertyNotification");
+
+  Actor actor = Actor::New();
+
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, GreaterThanCondition(100.0f));
+  DALI_TEST_CHECK( notification );
+  END_TEST;
+}
+
+int UtcDaliAddPropertyNotificationCallback(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  TestClass* object = new TestClass;
+
+  object->Initialize();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+
+  gCallBackCalled = false;
+
+  tet_infoline(" UtcDaliAddPropertyNotificationCallback - Forcing notification condition true, should receive a notification");
+  object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_CHECK( gCallBackCalled );
+  gCallBackCalled = false;
+
+  tet_infoline(" UtcDaliAddPropertyNotificationCallback - Forcing notification condition false, should not receive a notification");
+  object->mActor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_CHECK( !gCallBackCalled );
+  gCallBackCalled = false;
+
+  tet_infoline(" UtcDaliAddPropertyNotificationCallback - Deleting notification and it's owning object, should not receive a notification");
+  object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  object->Terminate();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  tet_infoline(" UtcDaliAddPropertyNotificationCallback - Removing notification and it's owning object, should not receive a notification");
+  object->Initialize();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  gCallBackCalled = false;
+
+  object->RemovePropertyNotification();
+
+  object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  tet_infoline(" UtcDaliAddPropertyNotificationCallback - Removing all notifications and it's owning object, should not receive a notification");
+  object->Initialize();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  gCallBackCalled = false;
+
+  object->RemovePropertyNotifications();
+
+  object->mActor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+
+  delete object;
+  END_TEST;
+}
+
+int UtcDaliAddPropertyNotificationTypeProperty(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+
+  // Currently, Type registry properties cannot be animated
+  try
+  {
+    actor.AddPropertyNotification( PROPERTY_REGISTRATION_START_INDEX, GreaterThanCondition( 100.0f ) );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false && \"Property notification added to event side only property", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGetCondition(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetCondition");
+
+  Actor actor = Actor::New();
+
+  PropertyCondition condition = GreaterThanCondition(100.0f);
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, condition);
+  DALI_TEST_CHECK( condition == notification.GetCondition() );
+  END_TEST;
+}
+
+class PropertyNotificationConstWrapper
+{
+public:
+
+  PropertyNotificationConstWrapper(PropertyNotification propertyNotification)
+  :mPropertyNotification(propertyNotification)
+  {
+
+  }
+
+  /**
+   * Returns const reference to property notification.
+   * @return const reference.
+   */
+  const PropertyCondition& GetCondition() const
+  {
+    return mPropertyNotification.GetCondition();
+  }
+
+  PropertyNotification mPropertyNotification;
+};
+
+int UtcDaliPropertyNotificationGetConditionConst(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetConditionConst");
+
+  Actor actor = Actor::New();
+
+  PropertyCondition condition = GreaterThanCondition(100.0f);
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X, condition);
+  PropertyNotificationConstWrapper notificationConst(notification);
+  const PropertyCondition& conditionReference1 = notificationConst.GetCondition();
+  const PropertyCondition& conditionReference2 = notificationConst.GetCondition();
+
+  DALI_TEST_CHECK( (&conditionReference1) == (&conditionReference2) );
+  DALI_TEST_CHECK( conditionReference1 == condition );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGetTarget(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetTarget");
+
+  Actor actor = Actor::New();
+  Actor actor2 = Actor::New();
+
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X,
+                                                                    GreaterThanCondition(100.0f));
+  Actor targetActor = Actor::DownCast( notification.GetTarget() );
+
+  DALI_TEST_CHECK( targetActor == actor );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGetProperty(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetProperty");
+
+  Actor actor = Actor::New();
+
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X,
+                                                                    GreaterThanCondition(100.0f));
+  Property::Index targetProperty = notification.GetTargetProperty();
+
+  DALI_TEST_EQUALS( targetProperty, Actor::Property::POSITION_X, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGetNotifyMode(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetNotifyMode");
+
+  Actor actor = Actor::New();
+
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X,
+                                                                    GreaterThanCondition(100.0f));
+  notification.SetNotifyMode(PropertyNotification::NotifyOnChanged);
+  PropertyNotification::NotifyMode notifyMode = notification.GetNotifyMode();
+
+  DALI_TEST_EQUALS( notifyMode, PropertyNotification::NotifyOnChanged, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGetNotifyResultP(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGetNotifyMode");
+
+  Actor actor = Actor::New();
+
+  PropertyNotification notification = actor.AddPropertyNotification(Actor::Property::POSITION_X,
+                                                                    GreaterThanCondition(100.0f));
+  notification.SetNotifyMode(PropertyNotification::NotifyOnChanged);
+  gCallBackCalled = false;
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+
+  bool notifyResult = notification.GetNotifyResult();
+
+  DALI_TEST_EQUALS( notifyResult, false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationGreaterThan(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGreaterThan");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move right to satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move left to un-satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  // Move right to satisfy condition again.
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationLessThan(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationLessThan");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, LessThanCondition(100.0f ) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move left to satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move right to un-satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  // Move left to satisfy condition again.
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationInside(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationInside");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, InsideCondition(100.0f, 200.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move inside to satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move outside (right) to un-satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(300.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  // Move inside to satisfy condition again.
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationOutside(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationOutside");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION_X, OutsideCondition(100.0f, 200.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move outside (left) to satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move inside to un-satisfy condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(150.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( !gCallBackCalled );
+
+  // Move outside (right) to satisfy condition again.
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(300.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationVectorComponentGreaterThan(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationGreaterThan");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, GreaterThanCondition(100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, GreaterThanCondition(100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, GreaterThanCondition(100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, GreaterThanCondition(0.5f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move right to satisfy XAxis condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move down to satisfy YAxis condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 200.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move forward to satisfy ZAxis
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Change alpha Colour to satisfy w/alpha component condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationVectorComponentLessThan(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationLessThan");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, LessThanCondition(-100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, LessThanCondition(-100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, LessThanCondition(-100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, LessThanCondition(0.5f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move left to satisfy XAxis condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(-200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move up to satisfy YAxis condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(-200.0f, -200.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move back to satisfy ZAxis
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(-200.0f, -200.0f, -200.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Change alpha Colour to satisfy w/alpha component condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationVectorComponentInside(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationInside");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, InsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, InsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, InsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, InsideCondition(0.25f, 0.75f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  // set outside all conditions
+  actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f));
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move x to inside condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(0.0f, 200.0f, 200.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move y to inside condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(0.0f, 0.0f, 200.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move z to inside condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // change alpha to inside condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationVectorComponentOutside(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationOutside");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, OutsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 1, OutsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::POSITION, 2, OutsideCondition(-100.0f, 100.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+  notification = actor.AddPropertyNotification( Actor::Property::COLOR, 3, OutsideCondition(0.25f, 0.75f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  // set inside all conditions
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 0.5f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // Move x to outside condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move y to outside condition
+  gCallBackCalled = false;
+  actor.SetPosition(Vector3(200.0f, 200.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // Move z to outside condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetPosition(Vector3(200.0f, 200.0f, 200.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+
+  // change alpha to outside condition
+  gCallBackCalled = false;
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  actor.SetColor(Vector4(0.0f, 0.0f, 0.0f, 1.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+  DALI_TEST_CHECK( gCallBackCalled );
+  END_TEST;
+}
+
+int UtcDaliPropertyConditionGetArguments(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyConditionGetArguments");
+
+  PropertyCondition condition = GreaterThanCondition( 50.0f );
+
+  DALI_TEST_EQUALS( condition.GetArgumentCount(), 1u, TEST_LOCATION );
+  float value = condition.GetArgument( 0 );
+  DALI_TEST_EQUALS( value, 50.0f, TEST_LOCATION );
+
+  condition = InsideCondition( 125.0f, 250.0f );
+
+  DALI_TEST_EQUALS( condition.GetArgumentCount(), 2u, TEST_LOCATION );
+  float value1 = condition.GetArgument( 0 );
+  float value2 = condition.GetArgument( 1 );
+  DALI_TEST_EQUALS( value1, 125.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( value2, 250.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationStep(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationStep");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  const float step = 100.0f;
+  // float
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, StepCondition(step, 50.0f) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  // set initial position
+  actor.SetPosition(Vector3(0.0f, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  // test both directions
+  for( int i = 1 ; i < 10 ; ++i )
+  {
+    // Move x to negative position
+    gCallBackCalled = false;
+    actor.SetPosition(Vector3((i * step), 0.0f, 0.0f));
+    Wait(application, DEFAULT_WAIT_PERIOD);
+    DALI_TEST_CHECK( gCallBackCalled );
+  }
+
+  for( int i = 1 ; i < 10 ; ++i )
+  {
+    // Move x to negative position
+    gCallBackCalled = false;
+    actor.SetPosition(Vector3(-(i * step), 0.0f, 0.0f));
+    Wait(application, DEFAULT_WAIT_PERIOD);
+    DALI_TEST_CHECK( gCallBackCalled );
+  }
+  END_TEST;
+}
+
+int UtcDaliPropertyNotificationVariableStep(void)
+{
+  TestApplication application;
+  tet_infoline(" UtcDaliPropertyNotificationStep");
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+
+  Dali::Vector<float> values;
+
+  const float averageStep = 100.0f;
+
+  for( int i = 1 ; i < 10 ; i++ )
+  {
+    values.PushBack(i * averageStep + (i % 2 == 0 ? -(averageStep * 0.2f) : (averageStep * 0.2f)));
+  }
+  // float
+  PropertyNotification notification = actor.AddPropertyNotification( Actor::Property::POSITION, 0, VariableStepCondition(values) );
+  notification.NotifySignal().Connect( &TestCallback );
+
+  // set initial position lower than first position in list
+  actor.SetPosition(Vector3(values[0] - averageStep, 0.0f, 0.0f));
+  Wait(application, DEFAULT_WAIT_PERIOD);
+
+  for( unsigned int i = 0 ; i < values.Count() - 1 ; ++i )
+  {
+    gCallBackCalled = false;
+    // set position half way between the current values
+    float position = values[i] + (0.5f * (values[i + 1] - values[i]));
+    actor.SetPosition(Vector3(position, 0.0f, 0.0f));
+    Wait(application, DEFAULT_WAIT_PERIOD);
+    DALI_TEST_CHECK( gCallBackCalled );
+  }
+  END_TEST;
+}
+
+static bool gCallBack2Called = false;
+void TestCallback2(PropertyNotification& source)
+{
+  gCallBack2Called = true;
+}
+
+int UtcDaliPropertyNotificationOrder(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  // this should complete in first frame
+  PropertyNotification notification1 = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(90.0f) );
+  notification1.NotifySignal().Connect( &TestCallback );
+  // this should complete in second frame
+  PropertyNotification notification2 = actor.AddPropertyNotification( Actor::Property::POSITION_X, GreaterThanCondition(150.0f) );
+  notification2.NotifySignal().Connect( &TestCallback2 );
+  Animation animation = Animation::New( 0.032f ); // finishes in 32 ms
+  animation.AnimateTo( Property(actor, Actor::Property::POSITION ), Vector3( 200.0f, 0.0f, 0.0f ), AlphaFunction::LINEAR );
+  animation.Play();
+
+  // flush the queue
+  application.SendNotification();
+  // first frame
+  application.Render(RENDER_FRAME_INTERVAL);
+  // no notifications yet
+  DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+  gCallBackCalled = false;
+  gCallBack2Called = false;
+
+  // dont serve the notifications but run another update & render
+  // this simulates situation where there is a notification in event side but it's not been picked up by event thread
+  // second frame
+  application.Render(RENDER_FRAME_INTERVAL);
+  DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+
+  // serve the notifications
+  application.SendNotification();
+  DALI_TEST_EQUALS( gCallBackCalled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( gCallBack2Called, true, TEST_LOCATION );
+
+  gCallBackCalled = false;
+  gCallBack2Called = false;
+  application.Render(RENDER_FRAME_INTERVAL);
+  application.SendNotification();
+  DALI_TEST_EQUALS( gCallBackCalled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( gCallBack2Called, false, TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PropertyTypes.cpp b/automated-tests/src/dali/utc-Dali-PropertyTypes.cpp
new file mode 100644 (file)
index 0000000..c5b6252
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+DALI_IMPORT_API const char* const GetName(Property::Type type);
+
+int UtcDaliPropertyTypesGetNameP(void)
+{
+  DALI_TEST_EQUALS( "NONE",               Dali::PropertyTypes::GetName(Property::NONE               ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "BOOLEAN",            Dali::PropertyTypes::GetName(Property::BOOLEAN            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "FLOAT",              Dali::PropertyTypes::GetName(Property::FLOAT              ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "INTEGER",            Dali::PropertyTypes::GetName(Property::INTEGER            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "VECTOR2",            Dali::PropertyTypes::GetName(Property::VECTOR2            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "VECTOR3",            Dali::PropertyTypes::GetName(Property::VECTOR3            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "VECTOR4",            Dali::PropertyTypes::GetName(Property::VECTOR4            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "MATRIX3",            Dali::PropertyTypes::GetName(Property::MATRIX3            ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "MATRIX",             Dali::PropertyTypes::GetName(Property::MATRIX             ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "RECTANGLE",          Dali::PropertyTypes::GetName(Property::RECTANGLE          ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "ROTATION",           Dali::PropertyTypes::GetName(Property::ROTATION           ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "STRING",             Dali::PropertyTypes::GetName(Property::STRING             ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "ARRAY",              Dali::PropertyTypes::GetName(Property::ARRAY              ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "MAP",                Dali::PropertyTypes::GetName(Property::MAP                ), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet02P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<bool>() == Property::BOOLEAN );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet03P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<float>() == Property::FLOAT );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet04P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<int>() == Property::INTEGER );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet06P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Vector2>() == Property::VECTOR2 );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet07P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Vector3>() == Property::VECTOR3 );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet08P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Vector4>() == Property::VECTOR4 );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet09P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Matrix3>() == Property::MATRIX3 );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet10(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Matrix>() == Property::MATRIX );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet11P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::AngleAxis>() == Property::ROTATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet12P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Quaternion>() == Property::ROTATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet13P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<std::string>() == Property::STRING );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet14P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Rect<int> >() == Property::RECTANGLE );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet15P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Property::Map>() == Property::MAP );
+  END_TEST;
+}
+
+int UtcDaliPropertyTypesGet16P(void)
+{
+  DALI_TEST_CHECK( Dali::PropertyTypes::Get<Dali::Property::Array>() == Property::ARRAY );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-PropertyValue.cpp b/automated-tests/src/dali/utc-Dali-PropertyValue.cpp
new file mode 100644 (file)
index 0000000..6b0bba5
--- /dev/null
@@ -0,0 +1,1242 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+void CheckTypeName(const Property::Type& type)
+{
+  switch(type)
+  {
+    case Property::NONE:
+    {
+      DALI_TEST_CHECK( "NONE" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      DALI_TEST_CHECK( "BOOLEAN" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::FLOAT:
+    {
+      DALI_TEST_CHECK( "FLOAT" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::INTEGER:
+    {
+      DALI_TEST_CHECK( "INTEGER" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      DALI_TEST_CHECK( "VECTOR2" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      DALI_TEST_CHECK( "VECTOR3" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      DALI_TEST_CHECK( "VECTOR4" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      DALI_TEST_CHECK( "MATRIX3" == std::string(PropertyTypes::GetName( type  ) ) );
+      break;
+    }
+    case Property::MATRIX:
+    {
+      DALI_TEST_CHECK( "MATRIX" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      DALI_TEST_CHECK( "RECTANGLE" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::ROTATION:
+    {
+      DALI_TEST_CHECK( "ROTATION" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::STRING:
+    {
+      DALI_TEST_CHECK( "STRING" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::ARRAY:
+    {
+      DALI_TEST_CHECK( "ARRAY" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+    case Property::MAP:
+    {
+      DALI_TEST_CHECK( "MAP" == std::string(PropertyTypes::GetName( type ) ) );
+      break;
+    }
+  } // switch(type)
+
+} // CheckTypeName
+
+template <typename T>
+struct CheckCopyCtorP
+{
+  CheckCopyCtorP(Property::Value value)
+  {
+    Property::Value copy( value );
+    DALI_TEST_CHECK( value.Get<T>() == copy.Get<T>() );
+  }
+};
+
+} // unnamed namespace
+
+void utc_dali_property_value_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_property_value_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliPropertyValueConstructorsNoneP(void)
+{
+  Property::Value value;
+
+  DALI_TEST_CHECK( value.GetType() == Property::NONE );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsNoneTypeP(void)
+{
+  Property::Value value( Property::NONE );
+
+  DALI_TEST_CHECK( value.GetType() == Property::NONE );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsBoolP(void)
+{
+  Property::Value value(true);
+
+  DALI_TEST_CHECK( value.GetType() == Property::BOOLEAN );
+  DALI_TEST_CHECK( value.Get<bool>() == true );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorBoolTypeP(void)
+{
+  Property::Value value(Property::BOOLEAN);
+
+  DALI_TEST_CHECK( value.GetType() == Property::BOOLEAN );
+  DALI_TEST_CHECK( value.Get<bool>() == false );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsFloatP(void)
+{
+  Property::Value value(2.f);
+
+  DALI_TEST_CHECK( value.GetType() == Property::FLOAT );
+  DALI_TEST_CHECK( value.Get<float>() == 2.f );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsFloatTypeP(void)
+{
+  Property::Value value(Property::FLOAT);
+
+  DALI_TEST_CHECK( value.GetType() == Property::FLOAT );
+  DALI_TEST_CHECK( value.Get<float>() == 0.f );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsIntP(void)
+{
+  Property::Value value(1);
+
+  DALI_TEST_CHECK( value.GetType() == Property::INTEGER );
+  DALI_TEST_CHECK( value.Get<int>() == 1 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsIntTypeP(void)
+{
+  Property::Value value(Property::INTEGER);
+
+  DALI_TEST_CHECK( value.GetType() == Property::INTEGER );
+  DALI_TEST_CHECK( value.Get<int>() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector2P(void)
+{
+  Vector2 v(1,1);
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR2 );
+  DALI_TEST_CHECK( value.Get<Vector2>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector2TypeP(void)
+{
+  Property::Value value( Property::VECTOR2 );
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR2 );
+  DALI_TEST_CHECK( value.Get<Vector2>() == Vector2::ZERO );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector3P(void)
+{
+  Vector3 v(1.f,2.f,3.f);
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR3 );
+  DALI_TEST_CHECK( value.Get<Vector3>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector3TypeP(void)
+{
+  Property::Value value( Property::VECTOR3 );
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR3 );
+  DALI_TEST_CHECK( value.Get<Vector3>() == Vector3() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector4P(void)
+{
+  Vector4 v(1.f,1.f,1.f,0.9f);
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR4 );
+  DALI_TEST_CHECK( value.Get<Vector4>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsVector4TypeP(void)
+{
+  Property::Value value( Property::VECTOR4 );
+
+  DALI_TEST_CHECK( value.GetType() == Property::VECTOR4 );
+  DALI_TEST_CHECK( value.Get<Vector4>() == Vector4() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMatrix3P(void)
+{
+  Matrix3 v(1.0,1.0,1.0, 1.0,1.0,1.0, 1.0,1.0,1.0);
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::MATRIX3 );
+  DALI_TEST_CHECK( value.Get<Matrix3>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMatrix3TypeP(void)
+{
+  Property::Value value( Property::MATRIX3 );
+
+  DALI_TEST_CHECK( value.GetType() == Property::MATRIX3 );
+  DALI_TEST_CHECK( value.Get<Matrix3>() == Matrix3() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMatrixP(void)
+{
+  float a[] = {1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0};
+  Matrix v(a);
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::MATRIX );
+  DALI_TEST_CHECK( value.Get<Matrix>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMatrixTypeP(void)
+{
+  Property::Value value( Property::MATRIX );
+
+  DALI_TEST_CHECK( value.GetType() == Property::MATRIX );
+  DALI_TEST_CHECK( value.Get<Matrix>() == Matrix() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsRectP(void)
+{
+  Rect<int> v(1.0,1.0,1.0,1.0);
+  Property::Value value(v);
+
+  DALI_TEST_EQUALS( value.GetType(), Property::RECTANGLE, TEST_LOCATION );
+  DALI_TEST_CHECK( value.Get<Rect<int> >() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsRectTypeP(void)
+{
+  Property::Value value( Property::RECTANGLE );
+
+  DALI_TEST_CHECK( value.GetType() == Property::RECTANGLE );
+  DALI_TEST_CHECK( value.Get<Rect<int> >() == Rect<int>(0,0,0,0) );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsAngleAxisP(void)
+{
+  AngleAxis input( Dali::ANGLE_90, Vector3::XAXIS );
+  Property::Value value( input );
+
+  DALI_TEST_CHECK( value.GetType() == Property::ROTATION );
+  AngleAxis result = value.Get<AngleAxis>();
+  DALI_TEST_EQUALS( result.angle, input.angle, TEST_LOCATION );
+  DALI_TEST_EQUALS( result.axis, input.axis, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsQuaternionP(void)
+{
+  Quaternion v( Vector4(1.0,1.0,1.0,1.0) );
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::ROTATION );
+  DALI_TEST_CHECK( value.Get<Quaternion>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsRotationTypeP(void)
+{
+  Property::Value value( Property::ROTATION );
+
+  DALI_TEST_CHECK( value.GetType() == Property::ROTATION );
+  AngleAxis result = value.Get<AngleAxis>();
+  DALI_TEST_EQUALS( result.angle, Radian(0.f), TEST_LOCATION );
+  DALI_TEST_EQUALS( result.axis, Vector3::ZERO, TEST_LOCATION ); // identity quaternion returns a zero angle-axis
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsStringP(void)
+{
+  std::string v("1");
+  Property::Value value(v);
+
+  DALI_TEST_CHECK( value.GetType() == Property::STRING );
+  DALI_TEST_CHECK( value.Get<std::string>() == v );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsStringTypeP(void)
+{
+  Property::Value value( Property::STRING );
+
+  DALI_TEST_CHECK( value.GetType() == Property::STRING );
+  DALI_TEST_CHECK( value.Get<std::string>() == std::string() );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsArrayP(void)
+{
+  Property::Array foo;
+  Property::Value value( foo );
+
+  DALI_TEST_CHECK( value.GetType() == Property::ARRAY );
+  DALI_TEST_CHECK( value.Get<Property::Array>().Count() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsArray2P(void)
+{
+  Property::Array foo;
+  foo.PushBack( Property::Value() );
+  Property::Value value( foo );
+
+  DALI_TEST_CHECK( value.GetType() == Property::ARRAY );
+  DALI_TEST_CHECK( value.Get<Property::Array>().Count() == 1 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsArrayTypeP(void)
+{
+  Property::Value value(Property::ARRAY);
+
+  DALI_TEST_CHECK( value.GetType() == Property::ARRAY );
+  DALI_TEST_CHECK( value.Get<Property::Array>().Count() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMapP(void)
+{
+  Property::Map map;
+  Property::Value value( map );
+
+  DALI_TEST_CHECK( value.GetType() == Property::MAP );
+  DALI_TEST_CHECK( value.Get<Property::Map>().Count() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMap2P(void)
+{
+  Property::Map map;
+  map.Insert( "", "" );
+  Property::Value value( map );
+
+  DALI_TEST_CHECK( value.GetType() == Property::MAP );
+  DALI_TEST_CHECK( value.Get<Property::Map>().Count() == 1 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueConstructorsMapTypeP(void)
+{
+  Property::Value value(Property::MAP);
+
+  DALI_TEST_CHECK( value.GetType() == Property::MAP );
+  DALI_TEST_CHECK( value.Get<Property::Map>().Count() == 0 );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorP(void)
+{
+  Property::Value value;
+  Property::Value value2( value );
+  DALI_TEST_EQUALS( value.GetType(), value2.GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( value.GetMap(), value2.GetMap(), TEST_LOCATION );
+  DALI_TEST_EQUALS( value.GetArray(), value2.GetArray(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorBoolP(void)
+{
+  CheckCopyCtorP<bool> check(true);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorFloatP(void)
+{
+  CheckCopyCtorP<float> check(1.f);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorIntP(void)
+{
+  CheckCopyCtorP<int> check(1);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructoVector2P(void)
+{
+  CheckCopyCtorP<Vector2> check( Vector2(2,1) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorVector3P(void)
+{
+  CheckCopyCtorP<Vector3> check( Vector3(3.f,2.f,1.f) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorVector4P(void)
+{
+  CheckCopyCtorP<Vector3> check( Vector4(4.f,3.f,2.f,1.f) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorMatrix3P(void)
+{
+  CheckCopyCtorP<Matrix3> check( Matrix3::IDENTITY );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorMatrixP(void)
+{
+  CheckCopyCtorP<Matrix> check(Matrix::IDENTITY);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorRectP(void)
+{
+  CheckCopyCtorP<Rect<int> > check( Rect<int>(1.0,1.0,1.0,1.0) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorAngleAxisP(void)
+{
+  CheckCopyCtorP<AngleAxis> check( AngleAxis(Degree(1.0), Vector3(1.0,1.0,1.0)) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorQuaternionP(void)
+{
+  CheckCopyCtorP<Quaternion> check( Quaternion( Vector4(1.0, 1.0, 1.0, 1.0) ) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorStringP(void)
+{
+  CheckCopyCtorP<std::string> check( std::string("1") );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorArrayP(void)
+{
+  Property::Value value1(Property::ARRAY);
+  Property::Array* array= value1.GetArray();
+  array->PushBack(Property::Value(1));
+
+  Property::Value value2( value1 );
+  DALI_TEST_EQUALS( value1.GetType(), value2.GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( value1.GetArray()->Count(), value2.GetArray()->Count(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueCopyConstructorMapP(void)
+{
+  Property::Value value1(Property::MAP);
+  Property::Map* map = value1.GetMap();
+  (*map)["1"] = Property::Value(1);
+
+  Property::Value value2( value1 );
+  DALI_TEST_EQUALS( value1.GetType(), value2.GetType(), TEST_LOCATION );
+  DALI_TEST_EQUALS( value1.GetMap()->Count(), value2.GetMap()->Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( value1.GetMap()->GetKey( 0 ), value2.GetMap()->GetKey( 0 ), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentSelfP(void)
+{
+  Property::Value value;
+  Property::Value* self = &value;
+  value = *self;
+  DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION );
+  DALI_TEST_CHECK( value.GetMap() == NULL );
+  DALI_TEST_CHECK( value.GetArray() == NULL );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorNoneP(void)
+{
+  Property::Value value;
+  value = Property::Value(); // type match
+  DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION );
+  Property::Value copy( false );
+  copy = value; // type mismatch
+  DALI_TEST_EQUALS( value.GetType(), Property::NONE, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorBoolP(void)
+{
+  Property::Value value;
+  value = Property::Value(true); // type mismatch
+  DALI_TEST_CHECK( true == value.Get<bool>() );
+  Property::Value copy( false );
+  copy = value; // type match
+  DALI_TEST_CHECK( true == copy.Get<bool>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorIntP(void)
+{
+  Property::Value value;
+  value = Property::Value(10); // type mismatch
+  DALI_TEST_CHECK( 10 == value.Get<int>() );
+  Property::Value copy( 99 );
+  copy = value; // type match
+  DALI_TEST_CHECK( 10 == copy.Get<int>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorFloatP(void)
+{
+  Property::Value value;
+  value = Property::Value(10.f); // mismatch
+  DALI_TEST_CHECK( Dali::Equals(10.f, value.Get<float>() ) );
+  Property::Value copy(321.f);
+  copy = value; // match
+  DALI_TEST_CHECK( Dali::Equals(10.f, copy.Get<float>() ) );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorVector2P(void)
+{
+  Property::Value value;
+  value = Property::Value( Vector2(1,2) ); // mismatch
+  DALI_TEST_CHECK( Vector2(1,2) == value.Get<Vector2>() );
+  Property::Value copy( Property::VECTOR2 );
+  copy = value; // match
+  DALI_TEST_CHECK( Vector2(1,2) == copy.Get<Vector2>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorVector3P(void)
+{
+  Property::Value value;
+  value = Property::Value( Vector3(1.f,2.f,3.f) ); // mismatch
+  DALI_TEST_CHECK( Vector3(1.f,2.f,3.f) == value.Get<Vector3>() );
+  Property::Value copy( Property::VECTOR3 );
+  copy = value; // match
+  DALI_TEST_CHECK( Vector3(1.f,2.f,3.f) == copy.Get<Vector3>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorVector4P(void)
+{
+  Property::Value value;
+  value = Property::Value( Vector4(1,2,3,4) ); // mismatch
+  DALI_TEST_CHECK( Vector4(1,2,3,4) == value.Get<Vector4>() );
+  Property::Value copy( Vector4(0,1,2,3) );
+  copy = value; // match
+  DALI_TEST_CHECK( Vector4(1,2,3,4) == copy.Get<Vector4>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorMatrix3P(void)
+{
+  Property::Value value;
+  value = Property::Value( Matrix3::IDENTITY ); // mismatch
+  DALI_TEST_CHECK( Matrix3::IDENTITY == value.Get<Matrix3>() );
+  Property::Value copy( Property::MATRIX3 );
+  copy = value; // match
+  DALI_TEST_CHECK( Matrix3::IDENTITY == copy.Get<Matrix3>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorMatrixP(void)
+{
+  Property::Value value;
+  value = Property::Value( Matrix::IDENTITY ); // mismatch
+  DALI_TEST_CHECK( Matrix::IDENTITY == value.Get<Matrix>()  );
+  Matrix foo;
+  Property::Value copy( foo );
+  copy = value; // match
+  DALI_TEST_CHECK( Matrix::IDENTITY == copy.Get<Matrix>()  );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorRectP(void)
+{
+  Property::Value value;
+  typedef Dali::Rect<int> Rectangle;
+  value = Property::Value( Rectangle(4,3,2,1) ); // mismatch
+  DALI_TEST_CHECK( Rectangle(4,3,2,1) == value.Get<Rectangle>() );
+  Property::Value copy( Property::RECTANGLE );
+  copy = value; // match
+  Rectangle copyRect;
+  copy.Get(copyRect);
+  DALI_TEST_CHECK( Rectangle(4,3,2,1) == copyRect );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorQuaternionP(void)
+{
+  Property::Value value;
+  value = Property::Value( Quaternion(1,1,1,1) ); // mismatch
+  DALI_TEST_CHECK( Quaternion(1,1,1,1) == value.Get<Quaternion>() );
+  Property::Value copy( Property::ROTATION );
+  copy = value; // match
+  DALI_TEST_CHECK( Quaternion(1,1,1,1) == copy.Get<Quaternion>() );
+  END_TEST;
+}
+
+
+int UtcDaliPropertyValueAssignmentOperatorAngleAxisP(void)
+{
+  Property::Value value;
+  value = Property::Value( AngleAxis( Radian(Math::PI_2), Vector3::XAXIS ) ); // mismatch
+  DALI_TEST_EQUALS( value.Get<AngleAxis>().axis, Vector3::XAXIS, TEST_LOCATION );
+  DALI_TEST_EQUALS( value.Get<AngleAxis>().angle, Radian(Math::PI_2), TEST_LOCATION );
+  Property::Value copy( Property::ROTATION );
+  copy = value; // match
+  DALI_TEST_EQUALS( value.Get<AngleAxis>().axis, copy.Get<AngleAxis>().axis, TEST_LOCATION );
+  DALI_TEST_EQUALS( value.Get<AngleAxis>().angle, copy.Get<AngleAxis>().angle, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorStringP(void)
+{
+  Property::Value value;
+  value = Property::Value("yes"); // mismatch
+  DALI_TEST_CHECK( "yes" == value.Get<std::string>() );
+  Property::Value copy("no");
+  copy = value; // match
+  DALI_TEST_CHECK( "yes" == copy.Get<std::string>() );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorArrayP(void)
+{
+  Property::Value value;
+  value = Property::Value(Property::ARRAY); // mismatch
+  value.GetArray()->PushBack(10);
+  DALI_TEST_CHECK( value.GetArray() );
+  Property::Value copy(Property::ARRAY);
+  copy = value; // match
+  Property::Array array;
+  copy.Get( array );
+  int getItem = 0;
+  array[0].Get( getItem );
+  DALI_TEST_CHECK( getItem == 10 );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueAssignmentOperatorMapP(void)
+{
+  Property::Value value;
+  value = Property::Value(Property::MAP); // mismatch
+  value.GetMap()->Insert("key", "value");
+  Property::Value copy( Property::MAP ); // match
+  copy = value;
+  Property::Map map;
+  copy.Get( map );
+  DALI_TEST_CHECK( map.GetKey(0) == "key" );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetTypeP(void)
+{
+  Property::Value value;
+  DALI_TEST_CHECK( value.GetType() == Property::NONE );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetBoolP(void)
+{
+  Property::Value value(true);
+  bool boolean( false );
+  DALI_TEST_CHECK( value.Get( boolean ) == true );
+  DALI_TEST_CHECK( value.Get<bool>() == true );
+  std::string string;
+  DALI_TEST_CHECK( value.Get( string ) == false );
+  value = Property::Value(1.f);
+  DALI_TEST_CHECK( value.Get<float>() == 1.f );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetBoolN(void)
+{
+  Property::Value value;
+  DALI_TEST_CHECK( value.Get<bool>() == false );
+  bool boolean( false );
+  DALI_TEST_CHECK( value.Get( boolean ) == false );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetFloatP(void)
+{
+  Property::Value value(1.1f);
+  float flow( 0.0f );
+  DALI_TEST_EQUALS( 1.1f, value.Get<float>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( flow ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1.1f, flow, TEST_LOCATION );
+
+  Property::Value intValue(100);
+  DALI_TEST_EQUALS( 100.f, intValue.Get<float>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, intValue.Get( flow ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 100.f, flow, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetFloatN(void)
+{
+  Property::Value value;
+  float result( 1.0f );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1.0f, result, TEST_LOCATION ); // result is not modified
+  Property::Value value2( "" );
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1.0f, result, TEST_LOCATION ); // result is not modified
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetIntP(void)
+{
+  Property::Value value(123);
+  int result( 10 );
+  DALI_TEST_EQUALS( 123, value.Get<int>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 123, result, TEST_LOCATION );
+
+  Property::Value floatValue(21.f);
+  DALI_TEST_EQUALS( 21, floatValue.Get<int>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, floatValue.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 21, result, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetIntN(void)
+{
+  Property::Value value;
+  int result( 10 );
+  DALI_TEST_EQUALS( 0, value.Get<int>(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 10, result, TEST_LOCATION ); // result is not modified
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 10, result, TEST_LOCATION ); // result is not modified
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetRectP(void)
+{
+  Property::Value value( Rect<int>(1,2,3,4) );
+  Rect<int> result(4,3,2,1);
+  DALI_TEST_EQUALS( Rect<int>(1,2,3,4), value.Get< Rect<int> >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Rect<int>(1,2,3,4), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetRectN(void)
+{
+  Property::Value value;
+  Rect<int> result(4,3,2,1);
+  DALI_TEST_EQUALS( Rect<int>(0,0,0,0), value.Get< Rect<int> >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Rect<int>(4,3,2,1), result, TEST_LOCATION );
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Rect<int>(4,3,2,1), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector2P(void)
+{
+  Property::Value value( Vector2(1.0f,2.0f) );
+  Vector2 result;
+  DALI_TEST_EQUALS( Vector2(1.0f,2.0f), value.Get< Vector2 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector2(1.0f,2.0f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector2N(void)
+{
+  Property::Value value;
+  Vector2 result;
+  DALI_TEST_EQUALS( Vector2(0.f,0.f), value.Get< Vector2 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector2(), result, TEST_LOCATION );
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector2(), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector3P(void)
+{
+  Property::Value value( Vector3(1.0f,2.0f,-1.f) );
+  Vector3 result;
+  DALI_TEST_EQUALS( Vector3(1.0f,2.0f,-1.f), value.Get< Vector3 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3(1.0f,2.0f,-1.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector3N(void)
+{
+  Property::Value value;
+  Vector3 result;
+  DALI_TEST_EQUALS( Vector3(0.f,0.f,0.f), value.Get< Vector3 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3(), result, TEST_LOCATION );
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3(), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector4P(void)
+{
+  Property::Value value( Vector4(1.f,2.f,-1.f,-3.f) );
+  Vector4 result;
+  DALI_TEST_EQUALS( Vector4(1.f,2.f,-1.f,-3.f), value.Get< Vector4 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector4(1.f,2.f,-1.f,-3.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetVector4N(void)
+{
+  Property::Value value;
+  Vector4 result;
+  DALI_TEST_EQUALS( Vector4(0.f,0.f,0.f,0.f), value.Get< Vector4 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector4(), result, TEST_LOCATION );
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector4(), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMatrix3P(void)
+{
+  Property::Value value( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f) );
+  Matrix3 result;
+  DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), value.Get< Matrix3 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMatrix3N(void)
+{
+  Property::Value value;
+  Matrix3 result(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f);
+  DALI_TEST_EQUALS( Matrix3(), value.Get< Matrix3 >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION );
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix3(1.f,2.f,3.f,4.f,5.f,6.f,7.f,8.f,9.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMatrixP(void)
+{
+  float matrixValues[16] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 };
+  Matrix input( matrixValues );
+  Property::Value value( input );
+  Matrix result;
+  DALI_TEST_EQUALS( input, value.Get< Matrix >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( input, result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMatrixN(void)
+{
+  Property::Value value;
+  Matrix result( Matrix::IDENTITY );
+  DALI_TEST_EQUALS( Matrix(), value.Get< Matrix >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix::IDENTITY, result, TEST_LOCATION );
+
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix::IDENTITY, result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetAngleAxisP(void)
+{
+  AngleAxis input( Dali::ANGLE_90, Vector3::XAXIS );
+  Property::Value value( input );
+  AngleAxis result = value.Get<AngleAxis>();
+  DALI_TEST_EQUALS( input.angle, result.angle, TEST_LOCATION );
+  DALI_TEST_EQUALS( input.axis, result.axis, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( input, result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetAngleAxisN(void)
+{
+  Property::Value value;
+  AngleAxis b = value.Get<AngleAxis>();
+  AngleAxis result;
+  DALI_TEST_EQUALS( 0.f, b.angle, TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3::ZERO, b.axis, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( AngleAxis(), result, TEST_LOCATION );
+
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( AngleAxis(), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetQuaternionP(void)
+{
+  Property::Value value( Quaternion(1.f,2.f,3.f,4.f) );
+  Quaternion result;
+  DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), value.Get< Quaternion >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetQuaternionN(void)
+{
+  Property::Value value;
+  Quaternion result(1.f,2.f,3.f,4.f);
+  DALI_TEST_EQUALS( Quaternion(), value.Get< Quaternion >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION );
+
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( Quaternion(1.f,2.f,3.f,4.f), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetStringP(void)
+{
+  Property::Value value( std::string("hello") );
+  std::string result;
+  DALI_TEST_EQUALS( std::string("hello"), value.Get< std::string >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( std::string("hello"), result, TEST_LOCATION );
+
+  Property::Value value2( "C hi!" );
+  DALI_TEST_EQUALS( "C hi!", value2.Get< std::string >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( true, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "C hi!", result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetStringN(void)
+{
+  Property::Value value;
+  std::string result("doesn't change");
+  DALI_TEST_EQUALS( std::string(), value.Get< std::string >(), TEST_LOCATION );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "doesn't change", result, TEST_LOCATION );
+
+  Property::Value value2(10);
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( "doesn't change", result, TEST_LOCATION );
+
+  Property::Value value3((char*)NULL);
+  DALI_TEST_EQUALS( true, value3.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( std::string(), result, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetArrayP(void)
+{
+  Property::Value value( Property::ARRAY );
+  DALI_TEST_CHECK( NULL != value.GetArray() );
+  value.GetArray()->PushBack( Property::Value(1) );
+  Property::Array got = value.Get<Property::Array>();
+  DALI_TEST_CHECK( got[0].Get<int>() == 1);
+  Property::Array result;
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_CHECK( result[0].Get<int>() == 1);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetArrayN(void)
+{
+  Property::Value value;
+  DALI_TEST_CHECK( NULL == value.GetArray() );
+  Property::Array result;
+  result.PushBack( Property::Value( 10 ) );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION  ); // array is not modified
+
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION  ); // array is not modified
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMapP(void)
+{
+  Property::Value value(Property::MAP);
+  DALI_TEST_CHECK( NULL == value.GetArray() );
+  DALI_TEST_CHECK( NULL != value.GetMap() );
+  value.GetMap()->Insert("key", Property::Value(1));
+  Property::Map result = value.Get<Property::Map>();
+  DALI_TEST_CHECK(result.Find("key")->Get<int>() == 1);
+  DALI_TEST_EQUALS( true, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_CHECK(result.Find("key")->Get<int>() == 1);
+  END_TEST;
+}
+
+int UtcDaliPropertyValueGetMapN(void)
+{
+  Property::Value value;
+  DALI_TEST_CHECK( NULL == value.GetMap() );
+  DALI_TEST_EQUALS( 0, value.Get<Property::Map>().Count(), TEST_LOCATION );
+  Property::Map result;
+  result.Insert("key", "value" );
+  DALI_TEST_EQUALS( false, value.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION );
+
+  Property::Value value2("");
+  DALI_TEST_EQUALS( false, value2.Get( result ), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1, result.Count(), TEST_LOCATION  ); // array is not modified
+  END_TEST;
+}
+
+int UtcDaliPropertyValueOutputStream(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Property::Value output stream");
+  typedef Dali::Rect<int> Rectangle;
+
+  Property::Value value(true);
+  {
+    std::ostringstream stream;
+    stream << value;
+    DALI_TEST_CHECK( stream.str() == "1" )
+  }
+
+  {
+    Property::Value empty;
+    std::ostringstream stream;
+    stream << empty;
+    DALI_TEST_EQUALS( stream.str(), "empty type", TEST_LOCATION );
+  }
+
+  {
+    Property::Value empty( Property::NONE );
+    std::ostringstream stream;
+    stream << empty;
+    DALI_TEST_CHECK( stream.str() == "undefined type" )
+  }
+
+  {
+    value = Property::Value(20.2f);
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "20.2" )
+  }
+
+  {
+    value = Property::Value(-25);
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "-25" )
+  }
+
+  {
+    value = Property::Value( Vector2(1.f,1.f) );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "[1, 1]" );
+  }
+
+  {
+    value = Property::Value( Vector3(1.f,1.f,1.f) );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "[1, 1, 1]" );
+  }
+
+  {
+    value = Property::Value( Vector4(-4.f,-3.f,-2.f,-1.f) );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_EQUALS( stream.str(), "[-4, -3, -2, -1]", TEST_LOCATION );
+  }
+
+  {
+    value = Property::Value( Matrix3::IDENTITY );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "[ [1, 0, 0], [0, 1, 0], [0, 0, 1] ]" );
+  }
+
+  {
+    value = Property::Value( Matrix::IDENTITY );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "[ [1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1] ]" );
+  }
+
+  {
+    value = Property::Value( Rectangle(1,2,3,4) );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "[1, 2, 3, 4]" );
+  }
+
+  {
+    value = Property::Value( AngleAxis( Dali::ANGLE_120, Vector3::XAXIS ) );
+    std::ostringstream stream;
+    stream <<  value;
+    tet_printf("angle axis = %s \n", stream.str().c_str() );
+    DALI_TEST_EQUALS( stream.str(), "[ Axis: [1, 0, 0], Angle: 120 degrees ]", TEST_LOCATION );
+  }
+
+  {
+    value = Property::Value( std::string( "Foo" ) );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( stream.str() == "Foo" );
+  }
+
+  // Maps and arrays currently not supported, we just check a message is output
+  {
+    Property::Map map;
+    value = Property::Value( map );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( !stream.str().empty() );
+  }
+  {
+    Property::Array array;
+    value = Property::Value( array );
+    std::ostringstream stream;
+    stream <<  value;
+    DALI_TEST_CHECK( !stream.str().empty() );
+  }
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Quaternion.cpp b/automated-tests/src/dali/utc-Dali-Quaternion.cpp
new file mode 100644 (file)
index 0000000..aac64e6
--- /dev/null
@@ -0,0 +1,1118 @@
+/*
+ * Copyright ( c ) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 ( the "License" );
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+void utc_dali_quaternion_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_quaternion_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliQuaternionCtorDefaultP(void)
+{
+  Quaternion q;
+  DALI_TEST_EQUALS( q.AsVector().w,  1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().x,  0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().y,  0.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().z,  0.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorCosSinThetaP(void)
+{
+  Quaternion q( 1.0f, 0.1f, 0.2f, 0.3f );
+
+  DALI_TEST_EQUALS( q.AsVector().w,  1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().x,  0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().y,  0.2f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().z,  0.3f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorVector4P(void)
+{
+  Quaternion q( Vector4( 1.0f, 0.1f, 0.2f, 0.3f ) );
+
+  DALI_TEST_EQUALS( q.AsVector().x,  1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().y,  0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().z,  0.2f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().w,  0.3f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorAxisAngleVector3P(void)
+{
+  Quaternion q( Dali::ANGLE_90, Vector3( 1.0f, 2.0f, 3.0f ) );
+
+  // This will be normalised:
+  DALI_TEST_EQUALS( q.AsVector().w,  0.707f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().x,  0.189f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().y,  0.378f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q.AsVector().z,  0.567f, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorEulerAngleP(void)
+{
+  Quaternion q1(0.924f, 0.383f, 0.0f, 0.0f);
+  Vector4 r1(Radian(Degree(45)), 0.0f, 0.0f, 0.0f);
+
+  Quaternion q2(0.793f, 0.0f, 0.609f, 0.0f);
+  Vector4 r2(0.0f, Radian(Degree(75)), 0.0f, 0.0f);
+
+  Quaternion q3(0.383f, 0.0f, 0.0f, 0.924f);
+  Vector4 r3(0.0f, 0.0f, Radian(Degree(135)), 0.0f);
+
+  Quaternion q4(0.795f, 0.478f, 0.374f, 0.006f);
+  Vector4 r4(Radian(Degree(71)), Radian(Degree(36)), Radian(Degree(27)), 0.0f);
+
+  Quaternion q5( -0.149f, -0.697f, 0.145f, -0.686f);
+  Vector4 r5(Radian(Degree(148.0)), Radian(Degree(-88.2)), Radian(Degree(8.0)), 0.0f);
+
+  DALI_TEST_EQUALS(q1.EulerAngles(), r1, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(q2.EulerAngles(), r2, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(q3.EulerAngles(), r3, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(q4.EulerAngles(), r4, 0.01,  TEST_LOCATION);
+  DALI_TEST_EQUALS(q5.EulerAngles(), r5, 0.01,  TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorMatrixP01(void)
+{
+  // angle: 60 deg, axis: [1,2,3]
+  float Mref_raw[16] = { 0.535714f, 0.765794f, -0.355767f, 0.0f,
+                      -0.622936f, 0.642857f, 0.445741f, 0.0f,
+                      0.570053f, -0.0171693f, 0.821429f, 0.0f,
+                      0.0f,       0.0f,       0.0f,        1.0f};
+  Matrix Mref( Mref_raw );
+
+  Quaternion q1( Radian(M_PI/3.0f), Vector3( 1.0f, 2.0f, 3.0f ) );
+  Quaternion q2( Mref );
+
+  DALI_TEST_EQUALS( q1, q2, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorMatrixP02(void)
+{
+  // IDENTITY rotation
+  Quaternion q;
+
+  Matrix m( q );     // Convert to matrix
+
+  Quaternion q2( m ); // and back to a quaternion
+
+  DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( m, Matrix::IDENTITY, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorMatrixP03(void)
+{
+  // Create an arbitrary forward vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward( x, y, z );
+        vForward.Normalize();
+
+        // Construct an up vector from a sideways move
+        Vector3 vSide;
+        Vector3 vUp = vForward.Cross( Vector3( vForward.x+1.0f, vForward.y, vForward.z ) );
+        if( vUp.Length() > 0.01 )
+        {
+          vUp.Normalize();
+          vSide = vUp.Cross( vForward );
+          vSide.Normalize();
+        }
+        else
+        {
+          vSide = vForward.Cross( Vector3( vForward.x, vForward.y+1.0f, vForward.z ) );
+          vSide.Normalize();
+          vUp = vForward.Cross( vSide );
+          vUp.Normalize();
+        }
+
+        // Generate a matrix, and then a quaternion from it
+        Matrix rotMatrix( Matrix::IDENTITY );
+        rotMatrix.SetXAxis( vSide );
+        rotMatrix.SetYAxis( vUp );
+        rotMatrix.SetZAxis( vForward );
+        Quaternion q( rotMatrix );
+
+        // Generate a matrix from the quaternion, check they are the same
+        Matrix resultMatrix( q );
+        DALI_TEST_EQUALS( resultMatrix, rotMatrix, 0.001f, TEST_LOCATION );
+
+        // Rotate an arbitrary vector by both quaternion and rotation matrix,
+        // check the result is the same
+
+        Vector4 aVector( -2.983f, -3.213f, 8.2239f, 1.0f );
+        Vector3 aVectorRotatedByQ = q.Rotate( Vector3( aVector ) );
+        Vector4 aVectorRotatedByR = rotMatrix*aVector;
+        DALI_TEST_EQUALS( aVectorRotatedByQ, Vector3( aVectorRotatedByR ), 0.001f, TEST_LOCATION );
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorAxesP01(void)
+{
+  // angle: 60 deg, axis: [1,2,3]
+  float Mref_raw[16] = { 0.535714f, 0.765794f, -0.355767f, 0.0f,
+                      -0.622936f, 0.642857f, 0.445741f, 0.0f,
+                      0.570053f, -0.0171693f, 0.821429f, 0.0f,
+                      0.0f,       0.0f,       0.0f,        1.0f};
+  Matrix Mref( Mref_raw );
+
+  Quaternion q1( Radian(M_PI/3.0f), Vector3( 1.0f, 2.0f, 3.0f ) );
+  Quaternion q2( Mref.GetXAxis(), Mref.GetYAxis(), Mref.GetZAxis() );
+
+  DALI_TEST_EQUALS( q1, q2, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorAxesP02(void)
+{
+  Vector3 xAxis( Vector3::XAXIS );
+  Vector3 yAxis( Vector3::YAXIS );
+  Vector3 zAxis( Vector3::ZAXIS );
+
+  Quaternion q1( xAxis, yAxis, zAxis );
+
+  DALI_TEST_EQUALS( q1, Quaternion::IDENTITY, TEST_LOCATION );
+
+  xAxis = Vector3( 1.0f, 1.0f, 0.0f );
+  xAxis.Normalize();
+  yAxis = Vector3( -1.0f, 1.0f, 0.0f ); // 45 degrees anticlockwise ( +ve ) around z
+  yAxis.Normalize();
+  zAxis = xAxis.Cross( yAxis );
+  zAxis.Normalize();
+  Quaternion q2( xAxis, yAxis, zAxis );
+
+  DALI_TEST_EQUALS( q2, Quaternion( Radian( Degree( 45 ) ), Vector3::ZAXIS ), 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionCtorAxesP03(void)
+{
+  // Create an arbitrary forward vector
+  for( float x=-1.0f; x<=1.0f; x+=0.1f )
+  {
+    for( float y=-1.0f; y<1.0f; y+=0.1f )
+    {
+      for( float z=-1.0f; z<1.0f; z+=0.1f )
+      {
+        Vector3 vForward( x, y, z );
+        vForward.Normalize();
+
+        // Construct an up vector from a sideways move
+        Vector3 vSide;
+        Vector3 vUp = vForward.Cross( Vector3( vForward.x+1.0f, vForward.y, vForward.z ) );
+        if( vUp.Length() > 0.01 )
+        {
+          vUp.Normalize();
+          vSide = vUp.Cross( vForward );
+          vSide.Normalize();
+        }
+        else
+        {
+          vSide = vForward.Cross( Vector3( vForward.x, vForward.y+1.0f, vForward.z ) );
+          vSide.Normalize();
+          vUp = vForward.Cross( vSide );
+          vUp.Normalize();
+        }
+
+        // Generate a quaternion
+        Quaternion q( vSide, vUp, vForward );
+
+        Matrix rotMatrix;
+        rotMatrix.SetXAxis( vSide );
+        rotMatrix.SetYAxis( vUp );
+        rotMatrix.SetZAxis( vForward );
+
+        // Generate a matrix from the quaternion, check they are the same
+        Matrix m( q );
+        DALI_TEST_EQUALS( m.GetXAxis(), vSide, 0.001f, TEST_LOCATION );
+        DALI_TEST_EQUALS( m.GetYAxis(), vUp, 0.001f, TEST_LOCATION );
+        DALI_TEST_EQUALS( m.GetZAxis(), vForward, 0.001f, TEST_LOCATION );
+
+        // Rotate an arbitrary vector by both quaternion and rotation matrix,
+        // check the result is the same
+
+        Vector4 aVector( 2.043f, 12.8f, -3.872f, 1.0f );
+        Vector3 aVectorRotatedByQ = q.Rotate( Vector3( aVector ) );
+        Vector4 aVectorRotatedByR = rotMatrix*aVector;
+        DALI_TEST_EQUALS( aVectorRotatedByQ, Vector3( aVectorRotatedByR ), 0.001f, TEST_LOCATION );
+      }
+    }
+  }
+  END_TEST;
+}
+
+int UtcDaliQuaternionCtorTwoVectorsP(void)
+{
+  Vector3 v0( 1.0f, 2.0f, 3.0f );
+  Vector3 v1( -2.0f, 10.0f, -1.0f );
+  v0.Normalize();
+  v1.Normalize();
+  Quaternion q( v0, v1 );
+
+  DALI_TEST_EQUALS( q*v0, v1, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionAsVectorP(void)
+{
+  Vector4 v( 1.0f, 0.1f, 0.2f, 0.3f );
+  Quaternion q( v );
+
+  DALI_TEST_EQUALS( v, q.AsVector(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionToAxisAngleVector3P(void)
+{
+  Quaternion q( 0.932f, 1.1f, 3.4f, 2.7f );
+  Radian angle;
+  Vector3 axis;
+  bool converted = q.ToAxisAngle( axis, angle );
+  DALI_TEST_EQUALS( converted, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( angle.radian,  0.74f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.x, 3.03f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.y, 9.38f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.z, 7.45f, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionToAxisAngleVector3N(void)
+{
+  Quaternion q( 1, 2, 3, 4 );
+  Radian angle;
+  Vector3 axis;
+  bool converted = q.ToAxisAngle( axis, angle );
+  DALI_TEST_EQUALS( converted, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( angle.radian,  0.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.x, 0.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.y, 0.0f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.z, 0.0f, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionSetEulerP(void)
+{
+  // Test from euler angles
+  Quaternion e1;
+  e1.SetEuler( Dali::ANGLE_45, Dali::ANGLE_0, Dali::ANGLE_0 );
+  Vector4 r1( 0.383f, 0.0f, 0.0f, 0.924f );
+
+  Quaternion e2;
+  e2.SetEuler( Dali::ANGLE_0, Radian( Degree( 75 ) ), Dali::ANGLE_0 );
+  Vector4 r2( 0.0f, 0.609f, 0.0f, 0.793f );
+
+  Quaternion e3;
+  e3.SetEuler( Dali::ANGLE_0, Dali::ANGLE_0, Dali::ANGLE_135 );
+  Vector4 r3( 0.0f, 0.0f, 0.924f, 0.383f );
+
+  Quaternion e4;
+  e4.SetEuler( Radian( Degree( 71 ) ), Radian( Degree( 36 ) ), Radian( Degree( 27 ) ) );
+  Vector4 r4( 0.478f, 0.374f, 0.006f, 0.795f );
+
+  Quaternion e5;
+  e5.SetEuler( Radian( Degree( -31 ) ), Radian( Degree( -91 ) ), Radian( Degree( -173 ) ) );
+  Vector4 r5( -0.697f, 0.145f, -0.686f, -0.149f );
+
+  DALI_TEST_EQUALS( e1.AsVector(), r1, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( e2.AsVector(), r2, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( e3.AsVector(), r3, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( e4.AsVector(), r4, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( e5.AsVector(), r5, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionEulerAnglesP(void)
+{
+  Quaternion q1( 0.924f, 0.383f, 0.0f, 0.0f );
+  Vector4 r1( Radian( Degree( 45 ) ), 0.0f, 0.0f, 0.0f );
+
+  Quaternion q2( 0.793f, 0.0f, 0.609f, 0.0f );
+  Vector4 r2( 0.0f, Radian( Degree( 75 ) ), 0.0f, 0.0f );
+
+  Quaternion q3( 0.383f, 0.0f, 0.0f, 0.924f );
+  Vector4 r3( 0.0f, 0.0f, Radian( Degree( 135 ) ), 0.0f );
+
+  Quaternion q4( 0.795f, 0.478f, 0.374f, 0.006f );
+  Vector4 r4( Radian( Degree( 71 ) ), Radian( Degree( 36 ) ), Radian( Degree( 27 ) ), 0.0f );
+
+  Quaternion q5(  -0.149f, -0.697f, 0.145f, -0.686f );
+  Vector4 r5( Radian( Degree( 148.0 ) ), Radian( Degree( -88.2 ) ), Radian( Degree( 8.0 ) ), 0.0f );
+
+  DALI_TEST_EQUALS( q1.EulerAngles(), r1, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q2.EulerAngles(), r2, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q3.EulerAngles(), r3, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( q4.EulerAngles(), r4, 0.01,  TEST_LOCATION );
+  DALI_TEST_EQUALS( q5.EulerAngles(), r5, 0.01,  TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionToMatrixP01(void)
+{
+  Quaternion q( Radian( 0.69813 ), Vector3( 1.0f, 0.0f, 0.0f ) ); // 40 degree rotation around X axis
+
+  // Result calculated using a different maths library ( with appropriate row/col ordering )
+
+  float els[] = { 1.0f,  0.0f,   0.0f,  0.0f,
+                  0.0f,  0.766f, 0.643f, 0.0f,
+                  0.0f, -0.643f, 0.766f, 0.0f,
+                  0.0f,  0.0f,   0.0f,  1.0f };
+  Matrix mRes( els );
+  Matrix m( q );
+
+  DALI_TEST_EQUALS( m, mRes, 0.01, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionToMatrixP02(void)
+{
+  // rotation around arbitrary axis
+  Quaternion q2( Radian( -1.23918f ), Vector3( 7.0f, -13.0f, 11.0f ) );
+
+  float els[] = {  0.423f, -0.746f, -0.514f,  0.00f,
+                   0.384f,  0.662f, -0.644f,  0.00f,
+                   0.821f,  0.075f,  0.566f,  0.00f,
+                   0.000f,  0.000f,  0.000f,  1.00f };
+  Matrix mRes2( els );
+
+  Matrix m2( q2 );
+
+  DALI_TEST_EQUALS( m2, mRes2, 0.01, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionOperatorAdditionP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f );
+
+  Quaternion r1( 0.383f, 0.609f, 0.0f, 1.717f );
+
+  DALI_TEST_EQUALS( q1+q2, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorSubtractionP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q2( 0.383f, 0.690f, 0.234f, 1.917f );
+
+  Quaternion r1( 0.0f, 0.240f, 0.111f, 0.993f );
+
+  DALI_TEST_EQUALS( q2-q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionConjugateP(void)
+{
+  float s1 = 0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f );
+  float s2 = 0.697f; Vector3 v2( 0.612, 0.344, -0.144 );
+
+  Quaternion q1( s1, v1.x, v1.y, v1.z );
+  Quaternion q2( s2, v2.x, v2.y, v2.z );
+  q1.Conjugate();
+  q2.Conjugate();
+
+  Quaternion r1( s1, -v1.x, -v1.y, -v1.z );
+  Quaternion r2( s2, -v2.x, -v2.y, -v2.z );
+
+  DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplicationQuaternionP(void)
+{
+  float s1=0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f );
+  float s2=0.697f; Vector3 v2( 0.612, 0.344, -0.144 );
+
+  Quaternion q1( s1, v1.x, v1.y, v1.z );
+  Quaternion q2( s2, v2.x, v2.y, v2.z );
+
+  Vector3 vp = v1.Cross( v2 ) + v2*s1 + v1*s2;
+  Quaternion r1( s1*s2-v1.Dot( v2 ), vp.x, vp.y, vp.z );
+
+  DALI_TEST_EQUALS( q1*q2, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+// Quaternion * vector == Vector rotation
+int UtcDaliQuaternionOperatorMultiplicationVector3P(void)
+{
+  // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
+  Vector3 v( 2, 3, 4 );
+  Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS );
+  Quaternion qI = q;
+  qI.Invert();
+  Quaternion qv( 0.0f, v.x, v.y, v.z );
+  Quaternion r1 = ( q * qv ) * qI;
+
+  Vector3 r2 = q * v;
+
+  DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplicationFloatP01(void)
+{
+  // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
+  Quaternion q( Vector4( 0.1f, 0.2f, 0.3f, 1.0f ) );
+  Quaternion q2 = q * 2.f;
+  Vector4 v2( 0.2f, 0.4f, 0.6f, 2.0f );
+
+  DALI_TEST_EQUALS( q2.AsVector(), v2, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplicationFloatP02(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f );
+
+  DALI_TEST_EQUALS( q1 * 2.0f, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplicationFloatP03(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion r1( 0.5f* 0.383f, 0.0f, 0.0f, 0.5f * 0.924f );
+
+  DALI_TEST_EQUALS( q1 / 2.0f, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorDivisionQuaternionP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f );
+
+  // q1 / q2 = q1 * q2^-1
+  // q2^-1 = q2* / ||q2||^2
+  //       = Conjugate of q2 / Square of Norm of q2
+
+  Quaternion r1 = q2;
+  r1.Conjugate();
+  r1 *= 1.0f/q2.LengthSquared();
+  Quaternion r2 = q1 * r1;
+
+  DALI_TEST_EQUALS( q1 / q2, r2, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorDivisionFloatP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f );
+
+  DALI_TEST_EQUALS( q1, r1/2.0f, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorDivideAssignedFloatP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion r1( 2.0f* 0.383f, 0.0f, 0.0f, 2.0f * 0.924f );
+  r1 /= 2.0f;
+
+  DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorNegationP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion r1( -0.383f, -0.0f, -0.0f, -0.924f );
+
+  DALI_TEST_EQUALS( -q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorAddAssignP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+  Quaternion q2( 0.0f, 0.609f, 0.0f, 0.793f );
+
+  Quaternion r1( 0.383f, 0.609f, 0.0f, 1.717f );
+
+  q1 += q2;
+  DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorSubtractAssignP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q2( 0.383f, 0.690f, 0.234f, 1.917f );
+
+  Quaternion r1( 0.0f, 0.240f, 0.111f, 0.993f );
+  q2 -= q1;
+  DALI_TEST_EQUALS( q2, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplyAssignQuaternionP(void)
+{
+  float s1=0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f );
+  float s2=0.697f; Vector3 v2( 0.612, 0.344, -0.144 );
+
+  Quaternion q1( s1, v1.x, v1.y, v1.z );
+  Quaternion q2( s2, v2.x, v2.y, v2.z );
+
+  Quaternion r3 = q2 * q1;
+  q2 *= q1;
+  DALI_TEST_EQUALS( q2, r3, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplyAssignFloatP01(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  float scale = 2.5f;
+  Quaternion r1( scale*0.383f, scale*0.450f, scale*0.123f, scale*0.924f );
+  q1 *= scale;
+  DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorMultiplyAssignFloatP02(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  float scale = 2.5f;
+  Quaternion r1( 0.383f/scale, 0.450f/scale, 0.123f/scale, 0.924f/scale );
+  q1 /= scale;
+  DALI_TEST_EQUALS( q1, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorEqualityP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q2( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q3( 0.383f, 0.450f, 0.123f, 0.800f );
+  Quaternion q4( 0.383f, 0.450f, 0.100f, 0.800f );
+  Quaternion q5( 0.383f, 0.100f, 0.100f, 0.800f );
+  Quaternion q6( 0.100f, 0.100f, 0.100f, 0.800f );
+
+  Quaternion q7( -0.383f, -0.450f, -0.123f, -0.924f );
+  Quaternion q8( -0.383f, -0.450f, -0.123f,  0.924f );
+  Quaternion q9( -0.383f, -0.450f,  0.123f,  0.924f );
+  Quaternion q10( -0.383f,  0.450f,  0.123f,  0.924f );
+
+  DALI_TEST_CHECK( q1 == q2 );
+  DALI_TEST_CHECK( !( q1 == q3 ) );
+  DALI_TEST_CHECK( !( q1 == q4 ) );
+  DALI_TEST_CHECK( !( q1 == q5 ) );
+  DALI_TEST_CHECK( !( q1 == q6 ) );
+  DALI_TEST_CHECK( ( q1 == q7 ) );
+  DALI_TEST_CHECK( !( q1 == q8 ) );
+  DALI_TEST_CHECK( !( q1 == q9 ) );
+  DALI_TEST_CHECK( !( q1 == q10 ) );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOperatorInequalityP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q2( 0.383f, 0.450f, 0.123f, 0.924f );
+  Quaternion q3( -0.383f, -0.0f, -0.0f, -0.924f );
+  DALI_TEST_CHECK( !( q1 != q2 ) );
+  DALI_TEST_CHECK( q1 != q3 );
+  END_TEST;
+}
+
+int UtcDaliQuaternionLengthP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  float length = sqrtf( 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f );
+  DALI_TEST_EQUALS( q1.Length(), length, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionLengthSquaredP(void)
+{
+  Quaternion q1( 0.383f, 0.450f, 0.123f, 0.924f );
+  float lengthSquared = 0.383f*0.383f + 0.450f*0.450f + 0.123f*0.123f + 0.924f*0.924f;
+  DALI_TEST_EQUALS( q1.LengthSquared(), lengthSquared, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionNormalizeP(void)
+{
+  Quaternion q1( 0.118f, 0.692f, -0.127f, 0.701f );
+  Quaternion q2 = q1;
+  q2 *= 5.0f;
+  q2.Normalize();
+  DALI_TEST_EQUALS( q1, q2, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionNormalizedP(void)
+{
+  Quaternion q1( 0.118f, 0.692f, -0.127f, 0.701f );
+  Quaternion q2 = q1;
+  q2 *= 5.0f;
+  DALI_TEST_EQUALS( q1, q2.Normalized(), 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionIsIdentityP(void)
+{
+  Quaternion q( 1.0f, 0.0f, 0.0f, 0.0f );
+  DALI_TEST_EQUALS( q.IsIdentity(),  true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionIsIdentityN(void)
+{
+  Quaternion q( 1.0f, 0.1f, 0.0f, 0.0f );
+  DALI_TEST_EQUALS( q.IsIdentity(),  false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionInvertP(void)
+{
+  Quaternion q1( 0.383f, 0.0f, 0.0f, 0.924f );
+
+  // q1^-1 = q1* / ||q1||^2
+  //       = Conjugate of q1 / Square of Norm of q1
+
+  Quaternion r1 = q1;
+  r1.Conjugate();
+  r1 *= 1.0f/q1.LengthSquared();
+
+  Quaternion q2 = q1;
+  q2.Invert();
+  DALI_TEST_EQUALS( q2, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionDotP(void)
+{
+  // q.q' = s*s' + v dot v'
+  float s1 = 0.784f; Vector3 v1( 0.045f, 0.443f, 0.432f );
+  float s2 = 0.697f; Vector3 v2( 0.612, 0.344, -0.144 );
+
+  Quaternion q1( s1, v1.x, v1.y, v1.z );
+  Quaternion q2( s2, v2.x, v2.y, v2.z );
+
+  float r1 = s1*s2 + v1.Dot( v2 );
+
+  DALI_TEST_EQUALS( Quaternion::Dot( q1, q2 ), r1, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionRotateVector3P(void)
+{
+  // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
+  Vector3 v( 2, 3, 4 );
+  Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS );
+  Quaternion qI = q;
+  qI.Invert();
+  Quaternion qv( 0.0f, v.x, v.y, v.z );
+  Quaternion r1 = q * qv * qI;
+
+  Vector3 r2 = q.Rotate( v );
+
+  DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( q.Rotate( v ), q*v, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionRotateVector4P(void)
+{
+  // Rotation of vector p = ( x,y,z ) by Quaternion q == q [0,p] q^-1
+  Vector4 v( 2, 3, 4, 5 );
+  Quaternion q( Radian( Degree( 72 ) ), Vector3::ZAXIS );
+  Quaternion qI = q;
+  qI.Invert();
+  Quaternion qv( 0.0f, v.x, v.y, v.z );
+  Quaternion r1 = q * qv * qI;
+
+  Vector4 r2 = q.Rotate( v );
+
+  DALI_TEST_EQUALS( r1.mVector.x, r2.x, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.y, r2.y, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.z, r2.z, 0.001f, TEST_LOCATION );
+  DALI_TEST_EQUALS( r1.mVector.w, 0.0f, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionExpP01(void)
+{
+  Quaternion q1( 0.0f, 1.0f, 1.2f, 1.3f );
+  Quaternion q2 = q1.Exp();
+  Quaternion r2( -0.4452, 0.4406, 0.5287, 0.5728 );
+
+  DALI_TEST_EQUALS( q2.Length(), 1.0f, 0.01f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION );
+
+  // Note, this trick only works when |v| < pi, which it is!
+  Quaternion q3 = q2.Log();
+  DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionExpP02(void)
+{
+  Quaternion q1( 0.0f, 0.0f, 0.0f, 0.0f );
+  Quaternion q2 = q1.Exp();
+  Quaternion r2( 1.0f, 0.0f, 0.0f, 0.0f );
+
+  DALI_TEST_EQUALS( q2.Length(), 1.0f, 0.01f, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( q2, r2, 0.001f, TEST_LOCATION );
+
+  // Note, this trick only works when |v| < pi, which it is!
+  Quaternion q3 = q2.Log();
+  DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionExpN(void)
+{
+  Quaternion q( Radian( 0.0f ), Vector3(5.0f, 6.0f, 7.0f) );
+
+  // q.w is non-zero. Should assert.
+  try
+  {
+    q.Exp();
+    DALI_TEST_CHECK( false );
+  }
+  catch( DaliException& e )
+  {
+    DALI_TEST_CHECK( true );
+  }
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionLogP01(void)
+{
+  Quaternion q( Radian( Math::PI*0.73f ), Vector3(2,3,4) );
+  Quaternion q2 = q;
+  q2.Normalize();
+
+  Quaternion r = q2.Log();
+  DALI_TEST_EQUALS( r.mVector.w, 0.0f, 0.01f, TEST_LOCATION );
+
+  Quaternion r2 = r.Exp();
+  DALI_TEST_EQUALS( r2, q2, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionLogP02(void)
+{
+  Quaternion q1( 1.0f, 0.0f, 0.0f, 0.0f );
+  Quaternion r1( 0.0f, 0.0f, 0.0f, 0.0f );
+
+  Quaternion q2 = q1.Log();
+
+  DALI_TEST_EQUALS( q2, r1, 0.01f, TEST_LOCATION );
+
+  Quaternion q3 = q2.Exp();
+  DALI_TEST_EQUALS( q1, q3, 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionLerpP(void)
+{
+  Quaternion q1( Radian( Degree( -80 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+  Quaternion q2( Radian( Degree( 80 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+
+  Quaternion p = Quaternion::Lerp( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( p, q1, 0.001f, TEST_LOCATION );
+
+  p = Quaternion::Lerp( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( p, q2, 0.001f, TEST_LOCATION );
+
+  p = Quaternion::Lerp( q1, q2, 0.5f );
+  Quaternion r1 = ( q1 + q2 ) * 0.5f;
+  r1.Normalize();
+  DALI_TEST_EQUALS( p, r1, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionSlerpP01(void)
+{
+  Quaternion q1(Radian(M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f));
+  Quaternion q2(Radian(-M_PI/4.0f), Vector3(0.0f, 0.0f, 1.0f));
+
+  Quaternion q = Quaternion::Slerp( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION );
+
+  // @ 25%, will be at M_PI/8
+  q = Quaternion::Slerp( q1, q2, 0.25f );
+  Vector3 axis;
+  Radian angle;
+  bool converted = q.ToAxisAngle( axis, angle );
+  DALI_TEST_EQUALS( converted, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.x, 0.0f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.y, 0.0f, 0.001, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.z, 1.0f, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+
+
+int UtcDaliQuaternionSlerpP02(void)
+{
+  Quaternion q1( Dali::ANGLE_30, Vector3(0.0f, 0.0f, 1.0f));
+  Quaternion q2( Dali::ANGLE_90, Vector3(0.0f, 0.0f, 1.0f));
+
+  Quaternion q = Quaternion::Slerp( q1, q2, 0.0f );
+
+  DALI_TEST_EQUALS( q,  q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp( q1, q2, 1.0f );
+
+  DALI_TEST_EQUALS( q,  q2, 0.001, TEST_LOCATION );
+
+  // @ 50%, will be at M_PI/3 around z
+  q = Quaternion::Slerp( q1, q2, 0.5f );
+
+  Quaternion r( Dali::ANGLE_60, Vector3( 0.0f, 0.0f, 1.0f));
+  DALI_TEST_EQUALS( q, r, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionSlerpP03(void)
+{
+  Quaternion q1( Radian( Degree( 125 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+  Quaternion q2( Radian( Degree( -125 ) ), Vector3( 0.002f, 0.001f, 1.001f ) );
+
+  Quaternion q = Quaternion::Slerp( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( q,  q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( q,  q2, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp(q1, q2, 0.05f);
+  Vector3 axis;
+  Radian angle;
+  bool converted = q.ToAxisAngle(axis, angle);
+  DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS( axis.x,  0.0f, 0.01, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.y,  0.0f, 0.01, TEST_LOCATION );
+  DALI_TEST_EQUALS( axis.z,  1.0f, 0.01, TEST_LOCATION );
+  END_TEST;
+}
+
+
+
+int UtcDaliQuaternionSlerpP04(void)
+{
+  Quaternion q1( Radian( Degree( 120 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+  Quaternion q2( Radian( Degree( 130 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+
+  Quaternion q = Quaternion::Slerp( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( q,  q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( q,  q2, 0.001, TEST_LOCATION );
+
+  q = Quaternion::Slerp(q1, q2, 0.5f);
+  Vector3 axis;
+  Radian angle;
+  bool converted = q.ToAxisAngle(axis, angle);
+  DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.x,  0.0f, 0.01, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.y,  0.0f, 0.01, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.z,  1.0f, 0.01, TEST_LOCATION);
+  END_TEST;
+}
+
+
+
+int UtcDaliQuaternionSlerpNoInvertP01(void)
+{
+  Quaternion q1( Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
+  Quaternion q2(-Dali::ANGLE_45, Vector3(0.0f, 0.0f, 1.0f));
+
+  Quaternion q = Quaternion::SlerpNoInvert( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( q, q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::SlerpNoInvert( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( q, q2, 0.001, TEST_LOCATION );
+
+  // @ 25%, will be at M_PI/8
+  q = Quaternion::SlerpNoInvert(q1, q2, 0.25f);
+  Vector3 axis;
+  Radian angle;
+  bool converted = q.ToAxisAngle(axis, angle);
+  DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(angle.radian, Math::PI/8.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.x, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.y, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.z, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionSlerpNoInvertP02(void)
+{
+  Quaternion q1( Radian( Degree( 120 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+  Quaternion q2( Radian( Degree( 130 ) ), Vector3( 0.0f, 0.0f, 1.0f ) );
+
+  Quaternion q = Quaternion::SlerpNoInvert( q1, q2, 0.0f );
+  DALI_TEST_EQUALS( q,  q1, 0.001, TEST_LOCATION );
+
+  q = Quaternion::SlerpNoInvert( q1, q2, 1.0f );
+  DALI_TEST_EQUALS( q,  q2, 0.001, TEST_LOCATION );
+
+  q = Quaternion::SlerpNoInvert(q1, q2, 0.5f);
+  Vector3 axis;
+  Radian angle;
+  bool converted = q.ToAxisAngle(axis, angle);
+  DALI_TEST_EQUALS(converted, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(angle.radian, float(Radian(Degree(125))), 0.01f, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.x,  0.0f, 0.01, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.y,  0.0f, 0.01, TEST_LOCATION);
+  DALI_TEST_EQUALS(axis.z,  1.0f, 0.01, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliQuaternionSquadP(void)
+{
+  Quaternion q1( Radian( Degree( 45 ) ),     Vector3( 0.0f, 0.0f, 1.0f ) );
+  Quaternion q1out( Radian( Degree( 40 ) ),  Vector3( 0.0f, 1.0f, 2.0f ) );
+  Quaternion q2in( Radian( Degree( 35 ) ),   Vector3( 0.0f, 2.0f, 3.0f ) );
+  Quaternion q2( Radian( Degree( 30 ) ),     Vector3( 0.0f, 1.0f, 3.0f ) );
+
+  Quaternion q = Quaternion::Squad( q1, q2, q1out, q2in, 0.0f );
+  DALI_TEST_EQUALS( q, q1, 0.001f, TEST_LOCATION );
+
+  q = Quaternion::Squad( q1, q2, q1out, q2in, 1.0f );
+  DALI_TEST_EQUALS( q, q2, 0.001f, TEST_LOCATION );
+
+  // Don't know what actual value should be, but can make some informed guesses.
+  q = Quaternion::Squad(q1, q2, q1out, q2in, 0.5f);
+  Radian angle;
+  Vector3 axis;
+  q.Normalize();
+  q.ToAxisAngle( axis, angle );
+
+  if( angle < 0.0f )
+  {
+    q = -q; // Might get negative quat
+    q.ToAxisAngle( axis, angle );
+  }
+  float deg = Degree(angle).degree;
+  DALI_TEST_CHECK(deg >= 0 && deg <= 90);
+  DALI_TEST_CHECK(axis.y > 0);
+  DALI_TEST_CHECK(axis.z > 0);
+  END_TEST;
+}
+
+int UtcDaliAngleBetweenP(void)
+{
+  Quaternion q1( ANGLE_45, ANGLE_0, ANGLE_0 );
+  Quaternion q2(Radian(Degree(47)), ANGLE_0, ANGLE_0 );
+  DALI_TEST_EQUALS(Quaternion::AngleBetween(q1, q2), fabsf(Radian(Degree(45)) - Radian(Degree(47))), 0.001f, TEST_LOCATION);
+
+  Quaternion q3( Radian( Degree( 80 ) ), Vector3::YAXIS );
+  Quaternion q4( Radian( Degree( 90 ) ), Vector3::YAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q3, q4 ), fabsf( Radian( Degree( 80 ) ) - Radian( Degree( 90 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q5( Radian( Degree( 0 ) ), Vector3::YAXIS );
+  Quaternion q6( Radian( Degree( 90 ) ), Vector3::XAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q5, q6 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 90 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q7( Radian( Degree( 0 ) ), Vector3::YAXIS );
+  Quaternion q8( Radian( Degree( 0 ) ), Vector3::XAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q7, q8 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 0 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q9( Radian( Degree( 0 ) ), Vector3::XAXIS );
+  Quaternion q10( Radian( Degree( 180 ) ), Vector3::XAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q9, q10 ), fabsf( Radian( Degree( 0 ) ) - Radian( Degree( 180 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q11( Radian( Degree( 1 ) ), Vector3::YAXIS );
+  Quaternion q12( Radian( Degree( 240 ) ), Vector3::YAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q11, q12 ), fabsf( Radian( Degree( 1 - 240 + 360 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q13( Radian( Degree( 240 ) ), Vector3::YAXIS );
+  Quaternion q14( Radian( Degree( 1 ) ), Vector3::YAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q13, q14 ), fabsf( Radian( Degree( 240 - 1 - 360 ) ) ), 0.001f, TEST_LOCATION );
+
+  Quaternion q15( Radian( Degree( 240 ) ), Vector3::YAXIS );
+  Quaternion q16( Radian( Degree( 1 ) ), Vector3::ZAXIS );
+  DALI_TEST_EQUALS( Quaternion::AngleBetween( q15, q16 ), Quaternion::AngleBetween( q16, q15 ), 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliQuaternionOStreamOperatorP(void)
+{
+  std::ostringstream oss;
+
+  Quaternion quaternion( Dali::ANGLE_180, Vector3::YAXIS );
+
+  oss << quaternion;
+
+  std::string expectedOutput = "[ Axis: [0, 1, 0], Angle: 180 degrees ]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Radian.cpp b/automated-tests/src/dali/utc-Dali-Radian.cpp
new file mode 100644 (file)
index 0000000..cfb3528
--- /dev/null
@@ -0,0 +1,150 @@
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+void utc_dali_radian_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_radian_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+// Positive test case for constructors
+int UtcDaliRadianConstructors01(void)
+{
+  // Default constructor, does not initialise the value
+  Radian radian0( 0.0f );
+
+  // Test float assignment operator
+  radian0 = Math::PI;
+  DALI_TEST_EQUALS( float(radian0), Math::PI, 0.001f, TEST_LOCATION );
+
+  // Constructor from float value
+  Radian radian1( Math::PI );
+  DALI_TEST_EQUALS( float(radian1), Math::PI, 0.001f, TEST_LOCATION );
+
+  // Constructor from a Degree
+  Radian radian2( Degree( 180.0f ) );
+  DALI_TEST_EQUALS( float(radian2), Math::PI, 0.001f, TEST_LOCATION );
+
+  // Assignment from Degree
+  Radian radian3( 0.0f );
+  radian3 = Degree( 180.0f );
+  DALI_TEST_EQUALS( float(radian3), Math::PI, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+// Positive test case for comparison
+int UtcDaliRadianComparison01(void)
+{
+  // Comparison between radians
+  Radian radian0( Math::PI_2 );
+  Radian radian1( Math::PI_2 );
+  Radian radian2( Math::PI );
+
+  DALI_TEST_CHECK( radian0 == radian1 );
+  DALI_TEST_CHECK( radian0 != radian2 );
+
+  // Comparison between radian to degree
+  Radian radian3( Math::PI );
+  Radian radian4( Math::PI_2 );
+  Degree degree0( 180.0f );
+
+  DALI_TEST_CHECK( radian3 == Radian(degree0) );
+  DALI_TEST_CHECK( radian4 != Radian(degree0) );
+
+  // Comparison with float
+  Radian radian5( Math::PI_2 );
+
+  DALI_TEST_CHECK( radian5 == Math::PI_2 );
+  DALI_TEST_CHECK( radian5 != Math::PI );
+
+  END_TEST;
+}
+
+
+// test case for cast operators
+int UtcDaliRadianCastOperators01(void)
+{
+  Radian radian0( Math::PI );
+
+  const float& value0( radian0.radian );
+  DALI_TEST_EQUALS( value0, Math::PI, 0.001f, TEST_LOCATION );
+
+  radian0 = Math::PI_2;
+  DALI_TEST_EQUALS( value0, Math::PI_2, 0.001f, TEST_LOCATION );
+
+  float value1( radian0 );
+  DALI_TEST_EQUALS( value1, Math::PI_2, 0.001f, TEST_LOCATION );
+
+  radian0 = Math::PI;
+  DALI_TEST_EQUALS( float(radian0), Math::PI, 0.001f, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliRadianCastOperatorEquals(void)
+{
+  Radian a(Math::PI_2);
+  Radian b(Math::PI_2);
+  Radian c(Math::PI);
+
+  DALI_TEST_EQUALS( a == a, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( a == b, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( a == c, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( Degree(c) == c, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRadianCastOperatorNotEquals(void)
+{
+  Radian a(Math::PI_2);
+  Radian b(Math::PI_2);
+  Radian c(Math::PI);
+
+  DALI_TEST_EQUALS( a != a, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( a != b, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( a != c, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( Degree(a) != c, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRadianCastOperatorLessThan(void)
+{
+  Radian a(Math::PI_4);
+  Radian b(Math::PI_2);
+  Radian c(Math::PI);
+  Radian d(2.0f*Math::PI);
+  Radian e(-Math::PI);
+
+  DALI_TEST_EQUALS(a < a, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(a < b, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(a < c, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(a < d, true, TEST_LOCATION);
+  DALI_TEST_EQUALS(a < e, false, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(b < a, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(b < b, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(c < b, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(d < b, false, TEST_LOCATION);
+  DALI_TEST_EQUALS(e < b, true, TEST_LOCATION);
+
+  DALI_TEST_EQUALS( Radian(Math::PI_2) < Degree(180.0f), true,  TEST_LOCATION);
+  DALI_TEST_EQUALS( Radian(Math::PI_2) < Degree(90.0f),  false, TEST_LOCATION);
+  DALI_TEST_EQUALS( Radian(Math::PI_2) > Degree(45.0f),  true,  TEST_LOCATION);
+
+  DALI_TEST_EQUALS( Degree(180.0f) > Radian(Math::PI_2), true,  TEST_LOCATION);
+  DALI_TEST_EQUALS( Degree(90.0f)  > Radian(Math::PI_2), false, TEST_LOCATION);
+  DALI_TEST_EQUALS( Degree(45.0f)  < Radian(Math::PI_2), true,  TEST_LOCATION);
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Random.cpp b/automated-tests/src/dali/utc-Dali-Random.cpp
new file mode 100644 (file)
index 0000000..a3c8670
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+int UtcDaliRandomRangeMethod(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  float a=0, b=1;
+  for(size_t i=0; i<100; i++)
+  {
+    float r = Dali::Random::Range(a, b);
+    DALI_TEST_CHECK(r >= a && r <= b);
+  }
+
+  a=100; b=-100;
+  for(size_t i=0; i<100; i++)
+  {
+    float r = Dali::Random::Range(a, b);
+    DALI_TEST_CHECK(r >= b && r <= a);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliRandomAxisMethod(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  for(size_t i=0; i<100; i++)
+  {
+    Vector4 axis = Dali::Random::Axis();
+    DALI_TEST_EQUALS(axis.Length(), 1.0f, 0.0001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Rect.cpp b/automated-tests/src/dali/utc-Dali-Rect.cpp
new file mode 100644 (file)
index 0000000..24ce9d8
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_rect_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_rect_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+// Positive test case for a method
+int UtcDaliRectCons01(void)
+{
+  TestApplication application;
+
+  Rect<float> rect;
+  DALI_TEST_EQUALS(rect.x, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.y, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.width, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.height, 0.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectCons02(void)
+{
+  TestApplication application;
+
+  Rect<float> rect(10.0f, 20.0f, 400.0f, 200.0f);
+  DALI_TEST_EQUALS(rect.x, 10.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.y, 20.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.width, 400.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.height, 200.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectCons03(void)
+{
+  TestApplication application;
+
+  Rect<float> rect(10.0f, 20.0f, 400.0f, 200.0f);
+
+  Rect<float> r2 = rect;
+
+  DALI_TEST_EQUALS(r2.x, 10.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.y, 20.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.width, 400.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.height, 200.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectCons04(void)
+{
+  TestApplication application;
+
+  Rect<float> rect(10.0f, 20.0f, 400.0f, 200.0f);
+
+  Rect<float> r2(rect);
+
+  DALI_TEST_EQUALS(r2.x, 10.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.y, 20.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.width, 400.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(r2.height, 200.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectSet(void)
+{
+  TestApplication application;
+
+  Rect<float> rect(10.0f, 20.0f, 400.0f, 200.0f);
+
+  rect.Set(1.0f, 2.0f, 3.0f, 4.0f);
+
+  DALI_TEST_EQUALS(rect.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.y, 2.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.width, 3.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(rect.height, 4.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectIsEmpty(void)
+{
+  TestApplication application;
+
+  Rect<int>   ri;
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+  Rect<float> rf2;
+  Rect<float> rf3(10.0f, 20.0f, 0.0f, 200.0f);
+  Rect<float> rf4(10.0f, 20.0f, 400.0f, 0.0f);
+  Rect<double> rd(10.0, 20.0, 0.0, 200.0);
+  Rect<unsigned int> ru(0u, 0u, 4u, 0u);
+
+  DALI_TEST_CHECK(!rf.IsEmpty());
+  DALI_TEST_CHECK(rf2.IsEmpty());
+  DALI_TEST_CHECK(rf3.IsEmpty());
+  DALI_TEST_CHECK(rf4.IsEmpty());
+  DALI_TEST_CHECK(ri.IsEmpty());
+  DALI_TEST_CHECK(rd.IsEmpty());
+  DALI_TEST_CHECK(ru.IsEmpty());
+  END_TEST;
+}
+
+int UtcDaliRectLeft(void)
+{
+  TestApplication application;
+
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+
+  DALI_TEST_EQUALS(rf.Left(), 10.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectRight(void)
+{
+  TestApplication application;
+
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+
+  DALI_TEST_EQUALS(rf.Right(), 410.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectTop(void)
+{
+  TestApplication application;
+
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+
+  DALI_TEST_EQUALS(rf.Top(), 20.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRectBottom(void)
+{
+  TestApplication application;
+
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+
+  DALI_TEST_EQUALS(rf.Bottom(), 220.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliRectArea(void)
+{
+  TestApplication application;
+
+  Rect<float> rf(10.0f, 20.0f, 400.0f, 200.0f);
+
+  DALI_TEST_EQUALS(rf.Area(), 80000.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliRectIntersects(void)
+{
+  TestApplication application;
+
+  Rect<float> rf1( 10.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf2( 10.0f, 120.0f, 200.0f, 200.0f);
+  Rect<float> rf3( 10.0f, -80.0f, 200.0f, 200.0f);
+  Rect<float> rf4(110.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf5(-90.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf6(1000.0f, 1200.0f, 10.0f, 10.0f);
+
+  DALI_TEST_CHECK(rf1.Intersects(rf2));
+  DALI_TEST_CHECK(rf1.Intersects(rf3));
+  DALI_TEST_CHECK(rf1.Intersects(rf4));
+  DALI_TEST_CHECK(rf1.Intersects(rf5));
+  DALI_TEST_CHECK(!rf1.Intersects(rf6));
+  END_TEST;
+}
+
+
+
+int UtcDaliRectContains(void)
+{
+  TestApplication application;
+
+  Rect<float> rf1( 10.0f,  20.0f, 200.0f, 200.0f);
+
+  Rect<float> rf2( 10.0f, 120.0f, 200.0f, 200.0f);
+  Rect<float> rf3( 10.0f, -80.0f, 200.0f, 200.0f);
+  Rect<float> rf4(110.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf5(-90.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf6(1000.0f, 1200.0f, 10.0f, 10.0f);
+
+  Rect<float> rf7( 50.0f,  70.0f, 50.0f,   50.0f);
+
+  Rect<float> rf8(  10.0f,  20.0f, 100.0f, 100.0f);
+  Rect<float> rf9( 110.0f,  20.0f, 100.0f, 100.0f);
+  Rect<float> rf10( 110.0f, 120.0f, 100.0f, 100.0f);
+  Rect<float> rf11(  10.0f, 120.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(rf1.Contains(rf1));
+  DALI_TEST_CHECK(!rf1.Contains(rf2));
+  DALI_TEST_CHECK(!rf1.Contains(rf3));
+  DALI_TEST_CHECK(!rf1.Contains(rf4));
+  DALI_TEST_CHECK(!rf1.Contains(rf5));
+  DALI_TEST_CHECK(!rf1.Contains(rf6));
+
+  DALI_TEST_CHECK(rf1.Contains(rf7));
+
+  DALI_TEST_CHECK(rf1.Contains(rf8));
+  DALI_TEST_CHECK(rf1.Contains(rf9));
+  DALI_TEST_CHECK(rf1.Contains(rf10));
+  DALI_TEST_CHECK(rf1.Contains(rf11));
+  END_TEST;
+}
+
+
+int UtcDaliRectOperatorNotEquals(void)
+{
+  TestApplication application;
+
+  Rect<float> rf1( 10.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf2( 10.0f, 120.0f, 200.0f, 200.0f);
+  Rect<float> rf3( 10.0f, -80.0f, 200.0f, 200.0f);
+  Rect<float> rf4(110.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf5(-90.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf6(1000.0f, 1200.0f, 10.0f, 10.0f);
+  Rect<float> rf7( 50.0f,  70.0f, 50.0f,   50.0f);
+  Rect<float> rf8(  10.0f,  20.0f, 100.0f, 100.0f);
+  Rect<float> rf9( 110.0f,  20.0f, 100.0f, 100.0f);
+  Rect<float> rf10( 110.0f, 120.0f, 100.0f, 100.0f);
+  Rect<float> rf11(  10.0f, 120.0f, 100.0f, 100.0f);
+
+  DALI_TEST_CHECK(rf1 != rf2);
+  DALI_TEST_CHECK(rf1 != rf3);
+  DALI_TEST_CHECK(rf1 != rf4);
+  DALI_TEST_CHECK(rf1 != rf5);
+  DALI_TEST_CHECK(rf1 != rf6);
+  DALI_TEST_CHECK(rf1 != rf7);
+  DALI_TEST_CHECK(rf1 != rf8);
+  DALI_TEST_CHECK(rf1 != rf9);
+  DALI_TEST_CHECK(rf1 != rf10);
+  DALI_TEST_CHECK(rf1 != rf11);
+  END_TEST;
+}
+
+
+int UtcDaliRectOperatorEquals(void)
+{
+  TestApplication application;
+
+  Rect<float> rf1( 10.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf1p( 10.0f,  20.0f, 200.0f, 200.0f);
+
+  Rect<float> rf2(110.0f,  20.0f, 200.0f, 200.0f);
+  Rect<float> rf3( 10.0f, 120.0f, 200.0f, 200.0f);
+  Rect<float> rf4( 10.0f,  20.0f, 300.0f, 200.0f);
+  Rect<float> rf5( 10.0f,  20.0f, 200.0f, 500.0f);
+
+  Rect<float> rf6( 0.0f,  0.0f, 9.0f, 10.0f);
+
+  DALI_TEST_CHECK(rf1 == rf1p);
+  DALI_TEST_CHECK(rf1 == rf1);
+  DALI_TEST_CHECK(!(rf1 == rf2));
+  DALI_TEST_CHECK(!(rf1 == rf3));
+  DALI_TEST_CHECK(!(rf1 == rf4));
+  DALI_TEST_CHECK(!(rf1 == rf5));
+  DALI_TEST_CHECK(!(rf1 == rf6));
+
+
+  // integers
+  Rect<int> ri1( 10,  20, 200, 200 );
+  Rect<int> ri1p( 10,  20, 200, 200 );
+
+  DALI_TEST_CHECK(ri1 == ri1p);
+  END_TEST;
+}
+
+int UtcDaliRectOStreamOperatorP(void)
+{
+  TestApplication application;
+  std::ostringstream oss;
+
+  Rect<int> rect( 1, 2, 10, 10 );
+
+  oss << rect;
+
+  std::string expectedOutput = "[1, 2, 10, 10]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-RenderTask.cpp b/automated-tests/src/dali/utc-Dali-RenderTask.cpp
new file mode 100644 (file)
index 0000000..74bd263
--- /dev/null
@@ -0,0 +1,3456 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali-test-suite-utils.h>
+#include <dali/integration-api/debug.h>
+#include <test-native-image.h>
+
+#include <mesh-builder.h>
+
+#define BOOLSTR(x) ((x)?"T":"F")
+
+
+using namespace Dali;
+
+void utc_dali_render_task_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_render_task_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+/**
+ * APIs:
+ *
+ * Constructor, Destructor, DownCast, New, copy constructor, assignment operator
+ *
+ * SetSourceActor                      2+ve, 1-ve
+ * GetSourceActor                      1+ve, 1-ve
+ * SetExclusive                        2+ve, 0-ve
+ * IsExclusive                         2+ve, 0-ve
+ * SetInputEnabled                     1+ve, 0-ve
+ * GetInputEnabled                     1+ve, 0-ve
+ * SetCameraActor                      1+ve, 1-ve
+ * GetCameraActor                      1+ve, 1-ve
+ * SetTargetFrameBuffer                1+ve, 1-ve
+ * GetTargetFrameBuffer                1+ve, 1-ve
+ * SetScreenToFrameBufferFunction      1+ve, 1-ve
+ * GetScreenToFrameBufferFunction      1+ve, 1-ve
+ * SetScreenToFrameBufferMappingActor  1+ve, 1-ve
+ * GetScreenToFrameBufferMappingActor  1+ve, 1-ve
+ * SetViewportPosition                 1+ve
+ * GetCurrentViewportPosition          1+ve
+ * SetViewportSize                     1+ve
+ * GetCurrentViewportSize              1+ve
+ * SetViewport                         2+ve, 1-ve
+ * GetViewport                         2+ve, 1-ve
+ * SetClearColor                       1+ve, 1-ve
+ * GetClearColor                       1+ve, 1-ve
+ * SetClearEnabled                     1+ve, 1-ve
+ * GetClearEnabled                     1+ve, 1-ve
+ * SetCullMode
+ * GetCullMode
+ * SetRefreshRate                      Many
+ * GetRefreshRate                      1+ve
+ * FinishedSignal                      1+ve
+ */
+
+namespace // unnamed namespace
+{
+
+const int RENDER_FRAME_INTERVAL = 16;                           ///< Duration of each frame in ms. (at approx 60FPS)
+
+/*
+ * Simulate time passed by.
+ *
+ * @note this will always process at least 1 frame (1/60 sec)
+ *
+ * @param application Test application instance
+ * @param duration Time to pass in milliseconds.
+ * @return The actual time passed in milliseconds
+ */
+int Wait(TestApplication& application, int duration = 0)
+{
+  int time = 0;
+
+  for(int i = 0; i <= ( duration / RENDER_FRAME_INTERVAL); i++)
+  {
+    application.SendNotification();
+    application.Render(RENDER_FRAME_INTERVAL);
+    time += RENDER_FRAME_INTERVAL;
+  }
+
+  return time;
+}
+
+struct RenderTaskFinished
+{
+  RenderTaskFinished( bool& finished )
+  : finished( finished )
+  {
+  }
+
+  void operator()( RenderTask& renderTask )
+  {
+    finished = true;
+  }
+
+  bool& finished;
+};
+
+struct RenderTaskFinishedRemoveSource
+{
+  RenderTaskFinishedRemoveSource( bool& finished )
+  : finished( finished ),
+    finishedOnce(false)
+  {
+  }
+
+  void operator()( RenderTask& renderTask )
+  {
+    DALI_TEST_CHECK(finishedOnce == false);
+    finished = true;
+    finishedOnce = true;
+    Actor srcActor = renderTask.GetSourceActor();
+    UnparentAndReset(srcActor);
+  }
+
+  bool& finished;
+  bool finishedOnce;
+};
+
+struct RenderTaskFinishedRenderAgain
+{
+  RenderTaskFinishedRenderAgain( bool& finished )
+  : finished( finished ),
+    finishedOnce(false)
+  {
+  }
+
+  void operator()( RenderTask& renderTask )
+  {
+    DALI_TEST_CHECK(finishedOnce == false);
+    finished = true;
+    finishedOnce = true;
+    renderTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  }
+
+  bool& finished;
+  bool finishedOnce;
+};
+
+
+bool TestScreenToFrameBufferFunction( Vector2& coordinates )
+{
+  coordinates = coordinates + Vector2( 1, 2 );
+
+  return true;
+}
+
+ImageActor CreateLoadingImage(TestApplication& application, std::string filename, ResourceImage::LoadPolicy loadPolicy, Image::ReleasePolicy releasePolicy)
+{
+  Image image = ResourceImage::New(filename, loadPolicy, releasePolicy);
+  DALI_TEST_CHECK( image );
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  ImageActor actor = ImageActor::New(image);
+  actor.SetSize( 80, 80 );
+  application.SendNotification();
+  application.Render(16);
+  return actor;
+}
+
+Sampler CreateSamplerWithLoadingImage(TestApplication& application, std::string filename, ResourceImage::LoadPolicy loadPolicy, Image::ReleasePolicy releasePolicy)
+{
+  Image image = ResourceImage::New(filename, loadPolicy, releasePolicy);
+  DALI_TEST_CHECK( image );
+  application.SendNotification();
+  application.Render(16);
+  DALI_TEST_CHECK( application.GetPlatform().WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  Sampler sampler = Sampler::New( image, "sTexture" );
+  application.SendNotification();
+  application.Render(16);
+  return sampler;
+}
+
+void CompleteImageLoad(TestApplication& application, Integration::ResourceId resourceId, Integration::ResourceTypeId requestType)
+{
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
+
+  application.GetPlatform().SetResourceLoaded(resourceId, requestType, resource);
+}
+
+void FailImageLoad(TestApplication& application, Integration::ResourceId resourceId )
+{
+  application.GetPlatform().SetResourceLoadFailed(resourceId, Integration::FailureUnknown);
+}
+
+void ReloadImage(TestApplication& application, ResourceImage image)
+{
+  application.GetPlatform().ClearReadyResources();
+  application.GetPlatform().DiscardRequest();
+  application.GetPlatform().ResetTrace();
+  application.GetPlatform().SetClosestImageSize(Vector2(80.0f, 80.0f)); // Ensure reload is called.
+  image.Reload();
+}
+
+RenderTask CreateRenderTask(TestApplication& application,
+                            CameraActor offscreenCamera,
+                            Actor rootActor,       // Reset default render task to point at this actor
+                            Actor secondRootActor, // Source actor
+                            unsigned int refreshRate,
+                            bool glSync)
+{
+  // Change main render task to use a different root
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  taskList.GetTask(0u).SetSourceActor( rootActor );
+
+  FrameBufferImage frameBufferImage;
+  if( glSync )
+  {
+    NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10);
+    frameBufferImage= FrameBufferImage::New( *(testNativeImagePtr.Get()) );
+  }
+  else
+  {
+    frameBufferImage = FrameBufferImage::New( 10, 10 );
+  }
+
+  // Don't draw output framebuffer // '
+
+  RenderTask newTask = taskList.CreateTask();
+  newTask.SetCameraActor( offscreenCamera );
+  newTask.SetSourceActor( secondRootActor );
+  newTask.SetInputEnabled( false );
+  newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) );
+  newTask.SetClearEnabled( true );
+  newTask.SetExclusive( true );
+  newTask.SetRefreshRate( refreshRate );
+  newTask.SetTargetFrameBuffer( frameBufferImage );
+  return newTask;
+}
+
+bool UpdateRender(TestApplication& application, TraceCallStack& callStack, bool testDrawn, bool& finishedSig, bool testFinished, bool testKeepUpdating )
+{
+  finishedSig = false;
+  callStack.Reset();
+  application.Render(16);
+  application.SendNotification();
+
+  bool sigPassed = false;
+  if( testFinished )
+  {
+    sigPassed = finishedSig;
+  }
+  else
+  {
+    sigPassed = ! finishedSig;
+  }
+
+  bool drawResult = callStack.FindMethod("DrawElements") || callStack.FindMethod("DrawArrays");
+
+  bool drawPassed = false;
+  if( testDrawn )
+  {
+    drawPassed = drawResult;
+  }
+  else
+  {
+    drawPassed = !drawResult;
+  }
+
+  bool keepUpdating = (application.GetUpdateStatus() != 0);
+  bool keepUpdatingPassed = false;
+  if( testKeepUpdating )
+  {
+    keepUpdatingPassed = keepUpdating;
+  }
+  else
+  {
+    keepUpdatingPassed = !keepUpdating;
+  }
+
+  bool result = (sigPassed && drawPassed && keepUpdatingPassed);
+
+  tet_printf("UpdateRender: Expected: Draw:%s Signal:%s Keep Updating: %s  Actual: Draw:%s  Signal:%s KeepUpdating: %s  %s\n",
+             BOOLSTR(testDrawn), BOOLSTR(testFinished), BOOLSTR(testKeepUpdating),
+             BOOLSTR(drawResult), BOOLSTR(finishedSig), BOOLSTR(keepUpdating),
+             result ? "Passed":"Failed");
+
+  return result;
+}
+
+// The functor to be used in the hit-test algorithm to check whether the actor is hittable.
+bool IsActorHittableFunction(Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+  bool hittable = false;
+
+  switch (type)
+  {
+    case Dali::HitTestAlgorithm::CHECK_ACTOR:
+    {
+      // Check whether the actor is visible and not fully transparent.
+      if( actor.IsVisible()
+          && actor.GetCurrentWorldColor().a > 0.01f) // not FULLY_TRANSPARENT
+      {
+
+        hittable = true;
+      }
+      break;
+    }
+    case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+    {
+      if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
+      {
+        hittable = true;
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return hittable;
+}
+
+} // unnamed namespace
+
+
+/****************************************************************************************************/
+/****************************************************************************************************/
+/********************************   TEST CASES BELOW   **********************************************/
+/****************************************************************************************************/
+/****************************************************************************************************/
+
+int UtcDaliRenderTaskDownCast01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::DownCast()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  BaseHandle base = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( base );
+
+  RenderTask task = RenderTask::DownCast( base );
+  DALI_TEST_CHECK( task );
+
+  // Try calling a method
+  DALI_TEST_CHECK( task.GetSourceActor() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskDownCast02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::DownCast()");
+
+  Actor actor = Actor::New();
+
+  RenderTask task = RenderTask::DownCast( actor );
+  DALI_TEST_CHECK( ! task );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetSourceActorN(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::SetSourceActor() Negative - try with empty actor handle");
+  Stage stage = Stage::GetCurrent();
+
+  Actor srcActor;
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+  RenderTask renderTask = taskList.CreateTask();
+  renderTask.SetSourceActor(srcActor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( ! renderTask.GetSourceActor() );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetSourceActorP01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetSourceActor() Positive - check that setting a non-renderable actor stops existing source actor being rendered ");
+
+  Stage stage = Stage::GetCurrent();
+
+  const std::vector<GLuint>& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetSourceActor();
+  DALI_TEST_CHECK( actor );
+
+  std::vector<GLuint> ids;
+  ids.push_back( 7 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor newActor = ImageActor::New( img );
+  newActor.SetSize(1,1);
+  stage.Add( newActor );
+
+  Actor nonRenderableActor = Actor::New();
+  stage.Add( nonRenderableActor );
+
+  // Stop the newActor from being rendered by changing the source actor
+  DALI_TEST_CHECK( nonRenderableActor );
+  task.SetSourceActor( nonRenderableActor );
+  DALI_TEST_CHECK( task.GetSourceActor() != actor );
+  DALI_TEST_CHECK( task.GetSourceActor() == nonRenderableActor );
+
+  // Update & Render nothing!
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetSourceActorP02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetSourceActor() Positive - check that switching source from a non-renderable to a renderable actor causes the texture to be drawn");
+
+  Stage stage = Stage::GetCurrent();
+
+  const std::vector<GLuint>& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetSourceActor();
+  DALI_TEST_CHECK( actor );
+
+  std::vector<GLuint> ids;
+  ids.push_back( 7 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor newActor = ImageActor::New( img );
+  newActor.SetSize(1,1);
+  stage.Add( newActor );
+
+  Actor nonRenderableActor = Actor::New();
+  stage.Add( nonRenderableActor );
+
+  // Stop the newActor from being rendered by changing the source actor
+  DALI_TEST_CHECK( nonRenderableActor );
+  task.SetSourceActor( nonRenderableActor );
+  DALI_TEST_CHECK( task.GetSourceActor() != actor );
+  DALI_TEST_CHECK( task.GetSourceActor() == nonRenderableActor );
+
+  // Update & Render nothing!
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION );
+
+  // Set newActor as the new source Actor
+  task.SetSourceActor( newActor );
+  DALI_TEST_CHECK( task.GetSourceActor() != actor );
+  DALI_TEST_CHECK( task.GetSourceActor() == newActor );
+
+  // Update & Render the newActor
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that the newActor was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION );
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], 7u, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetSourceActorOffStage(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetSourceActor (on/off stage testing)");
+
+  Stage stage = Stage::GetCurrent();
+
+  const std::vector<GLuint>& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetSourceActor();
+  DALI_TEST_CHECK( actor );
+
+  std::vector<GLuint> ids;
+  GLuint expectedTextureId( 3 );
+  ids.push_back( expectedTextureId );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor newActor = ImageActor::New( img );
+  newActor.SetSize(1,1);
+  task.SetSourceActor( newActor );
+  // Don't add newActor to stage yet   //'
+
+  // Update & Render with the actor initially off-stage
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION );
+
+  // Now add to stage
+  stage.Add( newActor );
+
+  // Update & Render with the actor on-stage
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that the newActor was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION );
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], expectedTextureId, TEST_LOCATION );
+  }
+
+  // Now remove from stage
+  stage.Remove( newActor );
+
+  // Update & Render with the actor off-stage
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetSourceActorEmpty(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetSourceActor (empty handle case)");
+
+  Stage stage = Stage::GetCurrent();
+
+  const std::vector<GLuint>& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetSourceActor();
+  DALI_TEST_CHECK( actor );
+
+  std::vector<GLuint> ids;
+  GLuint expectedTextureId( 5 );
+  ids.push_back( expectedTextureId );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img = BufferImage::New( 1,1 );
+  ImageActor newActor = ImageActor::New( img );
+  newActor.SetSize(1,1);
+  stage.Add( newActor );
+
+  Actor nonRenderableActor = Actor::New();
+  stage.Add( nonRenderableActor );
+
+  // Set with empty handle
+  task.SetSourceActor( Actor() );
+  DALI_TEST_CHECK( ! task.GetSourceActor() );
+
+  // Update & Render nothing!
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that nothing was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 0u, TEST_LOCATION );
+
+  // Set with non-empty handle
+  task.SetSourceActor( newActor );
+  DALI_TEST_CHECK( task.GetSourceActor() == newActor );
+
+  // Update & Render the newActor
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that the newActor was rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION );
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], expectedTextureId, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetSourceActorP01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetSourceActor() Check the default render task has a valid source actor");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetSourceActor();
+  DALI_TEST_CHECK( actor );
+
+  // By default the entire scene should be rendered
+  Actor root = Stage::GetCurrent().GetLayer( 0 );
+  DALI_TEST_CHECK( root == actor );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetSourceActorP02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetSourceActor() Create a new render task, Add a new actor to the stage and set it as the source of the new render task. Get its source actor and check that it is equivalent to what was set.");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.CreateTask();
+  Actor actor = Actor::New();
+  Stage::GetCurrent().Add(actor);
+  task.SetSourceActor( actor );
+
+  DALI_TEST_EQUALS( actor, task.GetSourceActor(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetSourceActorN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetSourceActor() Try with empty handle");
+
+  RenderTask task;
+  try
+  {
+    Actor actor = task.GetSourceActor();
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetExclusive(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetExclusive() Check that exclusion works");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // Manipulate the GenTextures behaviour, to identify different ImageActors
+
+  std::vector<GLuint> ids;
+  ids.push_back( 8 ); // 8 = actor1
+  ids.push_back( 9 ); // 9 = actor2
+  ids.push_back( 10 ); // 10 = actor3
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img1 = BufferImage::New( 1,1 );
+  ImageActor actor1 = ImageActor::New( img1 );
+  actor1.SetSize(1,1);
+  Stage::GetCurrent().Add( actor1 );
+
+  // Update & Render actor1
+  application.SendNotification();
+  application.Render();
+
+  // Check that the actor1 was rendered
+  const std::vector<GLuint>& boundTextures = application.GetGlAbstraction().GetBoundTextures( GL_TEXTURE0 );
+  DALI_TEST_EQUALS( boundTextures.size(), 1u, TEST_LOCATION );
+
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], 8u/*unique to actor1*/, TEST_LOCATION );
+  }
+
+  BufferImage img2 = BufferImage::New( 1,1 );
+  ImageActor actor2 = ImageActor::New( img2 );
+  actor2.SetSize(1,1);
+
+  // Force actor2 to be rendered before actor1
+  Layer layer = Layer::New();
+  Stage::GetCurrent().Add( layer );
+  layer.Add( actor2 );
+  layer.LowerToBottom();
+
+  // Update & Render
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that the actors were rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 2u, TEST_LOCATION );
+
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], 9u/*unique to actor2*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( boundTextures[1], 8u/*unique to actor1*/, TEST_LOCATION );
+  }
+
+  BufferImage img3 = BufferImage::New( 1,1 );
+  ImageActor actor3 = ImageActor::New( img3 );
+  actor3.SetSize(1,1);
+
+  // Force actor3 to be rendered before actor2
+  layer = Layer::New();
+  Stage::GetCurrent().Add( layer );
+  layer.Add( actor3 );
+  layer.LowerToBottom();
+
+  // Update & Render all actors
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  // Check that the actors were rendered
+  DALI_TEST_EQUALS( boundTextures.size(), 3u, TEST_LOCATION );
+
+  if ( boundTextures.size() )
+  {
+    DALI_TEST_EQUALS( boundTextures[0], 10u/*unique to actor3*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( boundTextures[1], 9u/*unique to actor2*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( boundTextures[2], 8u/*unique to actor1*/, TEST_LOCATION );
+  }
+
+  // Both actors are now connected to the root node
+  // Setup 2 render-tasks - the first will render from the root-node, and the second from actor2
+
+  // Not exclusive is the default
+  RenderTask task1 = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( false == task1.IsExclusive() );
+
+  RenderTask task2 = taskList.CreateTask();
+  DALI_TEST_CHECK( false == task2.IsExclusive() );
+  task2.SetSourceActor( actor2 );
+
+  // Task1 should render all actors, and task 2 should render only actor2
+
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( boundTextures.size(), 4u, TEST_LOCATION );
+
+  if ( boundTextures.size() == 4 )
+  {
+    // Test that task 1 renders actor3, then actor2 & then actor1
+    DALI_TEST_CHECK( boundTextures[0] == 10u );
+    DALI_TEST_CHECK( boundTextures[1] == 9u );
+    DALI_TEST_CHECK( boundTextures[2] == 8u );
+
+    // Test that task 2 renders actor2
+    DALI_TEST_EQUALS( boundTextures[3], 9u, TEST_LOCATION );
+  }
+
+  // Make actor2 exclusive to task2
+
+  task2.SetExclusive( true );
+  DALI_TEST_CHECK( true == task2.IsExclusive() );
+
+  // Task1 should render only actor1, and task 2 should render only actor2
+
+  application.GetGlAbstraction().ClearBoundTextures();
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( boundTextures.size(), 3u, TEST_LOCATION );
+  if ( boundTextures.size() == 3 )
+  {
+    // Test that task 1 renders actor3 & actor1
+    DALI_TEST_CHECK( boundTextures[0] == 10u );
+    DALI_TEST_CHECK( boundTextures[1] == 8u );
+
+    // Test that task 2 renders actor2
+    DALI_TEST_CHECK( boundTextures[2] == 9u );
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetExclusive02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetExclusive() Check that changing from exclusive to not-exclusive works");
+
+  std::vector<GLuint> ids;
+  ids.push_back( 8 ); // 8 = actor1
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+
+  BufferImage img1 = BufferImage::New( 1,1 );
+  ImageActor actor1 = ImageActor::New( img1 );
+  actor1.SetSize(1,1);
+  Stage::GetCurrent().Add( actor1 );
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.CreateTask();
+
+  task.SetSourceActor( actor1 );
+  task.SetExclusive(true); // Actor should only render once
+
+  TestGlAbstraction& gl = application.GetGlAbstraction();
+  TraceCallStack& drawTrace = gl.GetDrawTrace();
+  drawTrace.Enable(true);
+
+  // Update & Render actor1
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( drawTrace.CountMethod("DrawArrays"), 1, TEST_LOCATION );
+
+  // Set task to non-exclusive - actor1 should render twice:
+  drawTrace.Reset();
+  task.SetExclusive(false);
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( drawTrace.CountMethod("DrawArrays"), 2, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetExclusiveN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetExclusive() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    task.SetExclusive(true);
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskIsExclusive01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::IsExclusive() Check default values are non-exclusive");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // Not exclusive is the default
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( false == task.IsExclusive() );
+
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_CHECK( false == newTask.IsExclusive() );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskIsExclusive02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::IsExclusive() Check the getter returns set values");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // Not exclusive is the default
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_EQUALS( newTask.IsExclusive(), false, TEST_LOCATION );
+
+  newTask.SetExclusive(true);
+  DALI_TEST_EQUALS( newTask.IsExclusive(), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskIsExclusiveN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::IsExclusive() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    bool x = task.IsExclusive();
+    x=x;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetInputEnabled(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetInputEnabled()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // Input is enabled by default
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( true == task.GetInputEnabled() );
+
+  task.SetInputEnabled( false );
+  DALI_TEST_CHECK( false == task.GetInputEnabled() );
+
+  task.SetInputEnabled( true );
+  DALI_TEST_CHECK( true == task.GetInputEnabled() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetInputEnabled(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetInputEnabled()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // Input is enabled by default
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_EQUALS( true, task.GetInputEnabled(), TEST_LOCATION );
+
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_EQUALS( true, newTask.GetInputEnabled(), TEST_LOCATION );
+
+  newTask.SetInputEnabled(false);
+  DALI_TEST_EQUALS( false, newTask.GetInputEnabled(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetCameraActorP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetCameraActor()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor defaultCameraActor = task.GetCameraActor();
+  DALI_TEST_CHECK( defaultCameraActor );
+
+  CameraActor newCameraActor = CameraActor::New();
+  DALI_TEST_CHECK( newCameraActor );
+
+  task.SetCameraActor( newCameraActor );
+  DALI_TEST_CHECK( task.GetCameraActor() != defaultCameraActor );
+  DALI_TEST_EQUALS( task.GetCameraActor(), newCameraActor, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetCameraActorN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetCameraActor() with empty actor handle");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Actor actor = task.GetCameraActor();
+  DALI_TEST_CHECK( actor );
+
+  CameraActor cameraActor;
+
+  task.SetCameraActor( cameraActor );
+  DALI_TEST_EQUALS( (bool)task.GetCameraActor(), false, TEST_LOCATION );
+  DALI_TEST_EQUALS( task.GetCameraActor(), cameraActor, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskGetCameraActorP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetCameraActor()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  CameraActor actor = task.GetCameraActor();
+  DALI_TEST_CHECK( actor );
+  DALI_TEST_EQUALS( actor.GetProjectionMode(), Dali::Camera::PERSPECTIVE_PROJECTION, TEST_LOCATION );
+  DALI_TEST_GREATER( actor.GetFieldOfView(), 0.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetCameraActorN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetCameraActor() with empty handle");
+  RenderTask task;
+
+  try
+  {
+    Actor actor = task.GetCameraActor();
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetTargetFrameBufferP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetTargetFrameBuffer()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  FrameBufferImage newImage = FrameBufferImage::New();
+  task.SetTargetFrameBuffer( newImage );
+  DALI_TEST_CHECK( task.GetTargetFrameBuffer() == newImage );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetTargetFrameBufferN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetTargetFrameBuffer()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+  FrameBufferImage newImage; // Empty handle
+  task.SetTargetFrameBuffer( newImage );
+  DALI_TEST_EQUALS( (bool)task.GetTargetFrameBuffer(), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetTargetFrameBufferP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetTargetFrameBuffer()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask newTask = taskList.CreateTask();
+  FrameBufferImage fb = FrameBufferImage::New(128, 128, Pixel::RGBA8888);
+  newTask.SetTargetFrameBuffer( fb );
+  DALI_TEST_EQUALS( newTask.GetTargetFrameBuffer(), fb, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetTargetFrameBufferN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetTargetFrameBuffer()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  // By default render-tasks do not render off-screen
+  FrameBufferImage image = task.GetTargetFrameBuffer();
+  DALI_TEST_CHECK( !image );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetScreenToFrameBufferFunctionP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetScreenToFrameBufferFunction()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  task.SetScreenToFrameBufferFunction( TestScreenToFrameBufferFunction );
+
+  Vector2 coordinates( 5, 10 );
+  Vector2 convertedCoordinates( 6, 12 ); // + Vector(1, 2)
+
+  RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction();
+  DALI_TEST_CHECK( func( coordinates ) );
+  DALI_TEST_CHECK( coordinates == convertedCoordinates );
+
+  task.SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
+  func = task.GetScreenToFrameBufferFunction();
+  DALI_TEST_CHECK( func( coordinates ) );
+
+  task.SetScreenToFrameBufferFunction( RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION );
+  func = task.GetScreenToFrameBufferFunction();
+  DALI_TEST_CHECK( ! func( coordinates ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetScreenToFrameBufferFunctionN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetScreenToFrameBufferFunction()");
+
+  RenderTask task; // Empty handle
+  try
+  {
+    task.SetScreenToFrameBufferFunction( TestScreenToFrameBufferFunction );
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetScreenToFrameBufferFunctionP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetScreenToFrameBufferFunction()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Vector2 originalCoordinates( 5, 10 );
+  Vector2 coordinates( 5, 10 );
+
+  RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction();
+  DALI_TEST_CHECK( !func( coordinates ) ); // conversion should fail by default
+  DALI_TEST_CHECK( coordinates == originalCoordinates ); // coordinates should not be modified
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetScreenToFrameBufferFunctionN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetScreenToFrameBufferFunction() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    RenderTask::ScreenToFrameBufferFunction func = task.GetScreenToFrameBufferFunction();
+    func=func;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskGetScreenToFrameBufferMappingActorP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor ");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask renderTask = taskList.CreateTask();
+  Actor mappingActor = Actor::New();
+  renderTask.SetScreenToFrameBufferMappingActor(mappingActor);
+
+  DALI_TEST_EQUALS( mappingActor, renderTask.GetScreenToFrameBufferMappingActor(), TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskGetScreenToFrameBufferMappingActorN(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor with empty task handle");
+
+  RenderTask task;
+  try
+  {
+    Actor mappingActor;
+    task.SetScreenToFrameBufferMappingActor(mappingActor);
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetScreenToFrameBufferMappingActor02N(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::GetScreenToFrameBufferMappingActor with empty task handle");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask renderTask = taskList.CreateTask();
+  Actor actor;
+  renderTask.SetScreenToFrameBufferMappingActor(actor);
+
+  DALI_TEST_EQUALS( (bool)renderTask.GetScreenToFrameBufferMappingActor(), false, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetViewportP01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetViewport() on default task");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+  Viewport viewport = task.GetViewport();
+
+  // By default the viewport should match the stage width/height
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height );
+  DALI_TEST_CHECK( viewport == expectedViewport );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetViewportP02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetViewport() on new task");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.CreateTask();
+  Viewport viewport = task.GetViewport();
+
+  // By default the viewport should match the stage width/height
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height );
+  DALI_TEST_CHECK( viewport == expectedViewport );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetViewportN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetViewport() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    Viewport viewport = task.GetViewport();
+    viewport = viewport;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetViewportP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetViewport()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Viewport newViewport( 0, 0, stageSize.width * 0.5f, stageSize.height * 0.5f );
+  task.SetViewport( newViewport );
+
+  // Update (viewport is a property)
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( task.GetViewport() == newViewport );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetViewportN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetViewport()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task;
+  try
+  {
+    Vector2 stageSize = Stage::GetCurrent().GetSize();
+    Viewport newViewport( 0, 0, stageSize.width * 0.5f, stageSize.height * 0.5f );
+    task.SetViewport( newViewport );
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetViewportPosition(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetViewportPosition()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Viewport viewport = task.GetViewport();
+
+  // By default the viewport should match the stage width/height
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height );
+  DALI_TEST_CHECK( viewport == expectedViewport );
+
+  // 'Setter' test
+  Vector2 newPosition(25.0f, 50.0f);
+  task.SetViewportPosition( newPosition );
+
+  // Update (viewport is a property)
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  // Set by Property test
+  Vector2 newPosition2(32.0f, 32.0f);
+  task.SetProperty( RenderTask::Property::VIEWPORT_POSITION, newPosition2 );
+
+  // Update
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition2, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  Vector2 newPosition3(64.0f, 0.0f);
+  Animation animation = Animation::New(1.0f);
+  animation.AnimateTo( Property( task, RenderTask::Property::VIEWPORT_POSITION ), newPosition3, AlphaFunction::LINEAR );
+  animation.Play();
+
+  // Perform 1000ms worth of updates at which point animation should have completed.
+  Wait(application, 1000);
+  DALI_TEST_EQUALS( task.GetCurrentViewportPosition(), newPosition3, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetViewportSize(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetViewportSize()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+
+  Viewport viewport = task.GetViewport();
+
+  // By default the viewport should match the stage width/height
+
+  Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Viewport expectedViewport( 0, 0, stageSize.width, stageSize.height );
+  DALI_TEST_CHECK( viewport == expectedViewport );
+
+  Vector2 newSize(128.0f, 64.0f);
+  task.SetViewportSize( newSize );
+
+  // Update (viewport is a property)
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  // Set by Property test
+  Vector2 newSize2(50.0f, 50.0f);
+  task.SetProperty( RenderTask::Property::VIEWPORT_SIZE, newSize2 );
+
+  // Update
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize2, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  Vector2 newSize3(10.0f, 10.0f);
+  Animation animation = Animation::New(1.0f);
+  animation.AnimateTo( Property( task, RenderTask::Property::VIEWPORT_SIZE ), newSize3, AlphaFunction::LINEAR );
+  animation.Play();
+
+  // Perform 1000ms worth of updates at which point animation should have completed.
+  Wait(application, 1000);
+  DALI_TEST_EQUALS( task.GetCurrentViewportSize(), newSize3, Math::MACHINE_EPSILON_1, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetClearColorP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetClearColor()");
+
+  Vector4 testColor( 1.0f, 2.0f, 3.0f, 4.0f );
+  Vector4 testColor2( 5.0f, 6.0f, 7.0f, 8.0f );
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( task.GetClearColor() != testColor );
+
+  task.SetClearColor( testColor );
+
+  // Wait a frame.
+  Wait(application);
+
+  DALI_TEST_EQUALS( task.GetClearColor(), testColor, TEST_LOCATION );
+
+  task.SetProperty( RenderTask::Property::CLEAR_COLOR, testColor2 );
+
+  // Wait a frame.
+  Wait(application);
+
+  DALI_TEST_EQUALS( task.GetClearColor(), testColor2, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetClearColorN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetClearColor() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    task.SetClearColor( Vector4::ZERO );
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetClearColorP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetClearColor()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_EQUALS( task.GetClearColor(), RenderTask::DEFAULT_CLEAR_COLOR, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetClearColorN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetClearColor()");
+
+  RenderTask task;
+  try
+  {
+    Vector4 color = task.GetClearColor();
+    color = color;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetClearEnabledP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetClearEnabled()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( !task.GetClearEnabled() ); // defaults to false
+
+  task.SetClearEnabled( true );
+  DALI_TEST_EQUALS( task.GetClearEnabled(), true, TEST_LOCATION );
+
+  task.SetClearEnabled( false );
+  DALI_TEST_EQUALS( task.GetClearEnabled(), false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetClearEnabledN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetClearEnabled() with empty handle");
+
+  RenderTask task;
+  try
+  {
+    task.SetClearEnabled(true);
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetClearEnabledP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetClearEnabled()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( !task.GetClearEnabled() ); // defaults to false
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskGetClearEnabledN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetClearEnabled() with empty handle");
+
+  RenderTask task;
+  try
+  {
+    bool x = task.GetClearEnabled();
+    x=x;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetCullModeP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetCullMode()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_EQUALS( task.GetCullMode(), true, TEST_LOCATION );
+
+  task.SetCullMode( false );
+
+  DALI_TEST_EQUALS( task.GetCullMode(), false, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetCullModeN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetCullMode() on empty handle");
+
+  RenderTask task;
+  try
+  {
+    task.SetCullMode( false );
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetCullModeP(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetCullMode()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_EQUALS( task.GetCullMode(), true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetCullModeN(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetCullMode() with empty handle");
+
+  RenderTask task;
+  try
+  {
+    bool x = task.GetCullMode();
+    x=x;
+  }
+  catch (Dali::DaliException(e))
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "RenderTask handle is empty", TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskSetRefreshRate(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SetRefreshRate()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // By default tasks will be processed every frame
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() );
+
+  task.SetRefreshRate( 2u ); // every-other frame
+  DALI_TEST_CHECK( 2u == task.GetRefreshRate() );
+
+  task.SetRefreshRate( RenderTask::REFRESH_ALWAYS );
+  DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskGetRefreshRate(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::GetRefreshRate()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+
+  // By default tasks will be processed every frame
+  RenderTask task = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == task.GetRefreshRate() );
+
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_CHECK( RenderTask::REFRESH_ALWAYS == newTask.GetRefreshRate() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSignalFinished(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SignalFinished()");
+
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  BufferImage image = BufferImage::New( 10, 10 );
+  ImageActor rootActor = ImageActor::New( image );
+  rootActor.SetSize( 10, 10 );
+  Stage::GetCurrent().Add( rootActor );
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10);
+  FrameBufferImage frameBufferImage = FrameBufferImage::New( *testNativeImagePtr.Get() );
+
+  // Flush all outstanding messages
+  application.SendNotification();
+  application.Render();
+
+  RenderTask newTask = taskList.CreateTask();
+  newTask.SetCameraActor( offscreenCameraActor );
+  newTask.SetSourceActor( rootActor );
+  newTask.SetInputEnabled( false );
+  newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) );
+  newTask.SetClearEnabled( true );
+  newTask.SetExclusive( true );
+  newTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
+  newTask.SetTargetFrameBuffer( frameBufferImage );
+
+  // Framebuffer doesn't actually get created until Connected, i.e. by previous line
+
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+
+  // Flush the queue and render.
+  application.SendNotification();
+
+  // 1 render to process render task, then wait for sync before finished msg is sent
+  // from update to the event thread.
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  application.Render();
+  DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION );
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  application.Render();
+  DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION );
+  application.SendNotification();
+  DALI_TEST_CHECK( ! finished );
+
+  sync.SetObjectSynced( lastSyncObj, true );
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( finished );
+  finished = false;
+
+  application.Render(); // Double check no more finished signal
+  application.SendNotification();
+  DALI_TEST_CHECK( ! finished );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskContinuous01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (source actor not staged)\nPOST:continuous renders, no Finished signal");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.SendNotification();
+
+  // START PROCESS/RENDER                     Input,    Expected  Input, Expected, KeepUpdating
+  DALI_TEST_CHECK( UpdateRender(application,  drawTrace, false,   finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+
+  // ADD SOURCE ACTOR TO STAGE - expect continuous renders to start, no finished signal
+  Stage::GetCurrent().Add(secondRootActor);
+  application.SendNotification();
+
+  // CONTINUE PROCESS/RENDER                  Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application,  drawTrace, true,    finished, false, false ) );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskContinuous02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (source actor not visible)\nPOST:continuous renders, no Finished signal");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+  secondRootActor.SetVisible(false);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected, KeepUpdating
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+
+  // MAKE SOURCE ACTOR VISIBLE - expect continuous renders to start, no finished signal
+  secondRootActor.SetVisible(true);
+  application.SendNotification();
+
+  // CONTINUE PROCESS/RENDER                 Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskContinuous03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: render task not ready (camera actor not staged)\nPOST:continuous renders, no Finished signal");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+
+  // ADD CAMERA ACTOR TO STAGE - expect continuous renders to start, no finished signal
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  application.SendNotification();
+
+  // CONTINUE PROCESS/RENDER                 Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskContinuous04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Continuous using loading image\nPRE: Resource not ready\nPOST:continuous renders, no Finished signal");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING - expect 'continuous' renders to start, no finished signal
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskContinous05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Continuous using Mesh which accesses texture through sampler with loading image\n"
+               "PRE: Resource not ready\nPOST:continuous renders, no Finished signal");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  Material material = CreateMaterial(1.0f);
+  Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor secondRootActor = Actor::New();
+  secondRootActor.AddRenderer(renderer);
+  secondRootActor.SetSize(100, 100);
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING - expect 'continuous' renders to start, no finished signal
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskOnce01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync, using loading image\nPRE: Resources not ready, Source not visible\nPOST: Finished signal sent once only");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // MAKE SOURCE VISIBLE
+  secondRootActor.SetVisible(true);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING - expect no rendering yet
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  application.GetPlatform().ClearReadyResources();
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,   finished, false, true  ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnce02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync, using Mesh which accesses texture through sampler with loading image.\n"
+               "PRE: Resources not ready\nPOST: Finished signal sent once only");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  Material material = CreateMaterial(1.0f);
+  Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor secondRootActor = Actor::New();
+  secondRootActor.AddRenderer(renderer);
+  secondRootActor.SetSize(100, 100);
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+   // FINISH RESOURCE LOADING - expect no rendering yet
+   CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+   Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+   DALI_TEST_CHECK( lastSyncObj != NULL );
+
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+   application.GetPlatform().ClearReadyResources();
+   sync.SetObjectSynced( lastSyncObj, true );
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,   finished, false, true  ) );
+   DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+
+   END_TEST;
+}
+
+int UtcDaliRenderTaskOnce03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync, using loading image. Switch from render always after ready to render once\n"
+               "PRE: Render task ready, Image not loaded\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true  ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskOnce04(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask Render Once GlSync, using Mesh which accesses texture through sampler with loading image.\n"
+               "Switch from render always after ready to render once\n"
+               "PRE: Render task ready, Image not loaded\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  Material material = CreateMaterial(1.0f);
+  Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor secondRootActor = Actor::New();
+  secondRootActor.AddRenderer(renderer);
+  secondRootActor.SetSize(100, 100);
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true  ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnce05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync\n"
+               "Switch from Render always after ready to render once with resources unready\n"
+               "PRE: Everything ready to render\n"
+               "POST: Finished signal sent once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // CHANGE TO RENDER ONCE
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+  application.GetPlatform().ClearReadyResources();
+
+  sync.SetObjectSynced( lastSyncObj, true );
+
+  // Expect: No draw - we've just drawn our render task once, above. No finished signal -
+  // we won't read the gl sync until the next frame. Continue rendering - we're waiting for
+  // the sync
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true  ) );
+
+  // Expect: 1 final draw - this Update doesn't update the scene, hence render instructions
+  // from last frame but 1 are still present.
+  // Finished signal should be true - we've just done the sync.
+  // Should now stop rendering and updating - nothing left to do.
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,   finished, true, false  ) );
+
+  END_TEST;
+}
+
+#if 0
+//int UtcDaliRenderTaskOnce06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync\n"
+               "During RenderOnce, make ready resources unready before sending first finished signal\n"
+               "PRE: Everything ready.\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+
+  Stage::GetCurrent().Add(secondRootActor);
+  application.GetPlatform().ClearReadyResources();
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+
+  // CHANGE TO RENDER ONCE, RESOURCES BECOME NOT READY
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+
+  // Doesn't work...
+  ReloadImage(application, secondRootActor.GetImage());
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_EQUALS( secondRootActor.GetImage().GetLoadingState(), Dali::ResourceLoading, TEST_LOCATION);
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  application.GetPlatform().ClearReadyResources();
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true  ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, true  ) );
+
+  // Finished rendering - expect no more renders, no more signals:
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  END_TEST;
+}
+#endif
+
+int UtcDaliRenderTaskOnce07(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GLSync\n"
+               "Render once, Second call to SetRefreshRate(ONCE) triggers only one more finished signal\n"
+               "PRE: Everything ready\n"
+               "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false  ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnce08(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GLSync\n"
+               "Render once, Call to SetRefreshRate(ONCE) in Finished signal callback triggers "
+               "another render & another finished signal\n"
+               "PRE: Everything ready\n"
+               "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)");
+
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+
+  ConnectionTracker connectionTracker;
+  RenderTaskFinishedRenderAgain renderTaskFinishedRenderAgain( finished );
+  newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinishedRenderAgain );
+
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj == NULL );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  application.SendNotification();
+
+  // Expect SetRefreshRate to have been called again
+  // Prevent next finished signal calling refresh once again
+  RenderTaskFinished renderTaskFinished( finished );
+  connectionTracker.DisconnectAll();
+  newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinished );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskOnce09(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync\n"
+               "SetRefreshRate(ONCE) again before first finished signal has been sent.\n"
+               "PRE: resources ready\n"
+               "POST: Only 1 finished signal sent.");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  sync.SetObjectSynced( lastSyncObj, true );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnce10(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once GlSync\n"
+               "SetRefreshRate(ONCE), resource load failed completes render task.\n"
+               "PRE: resources not ready\n"
+               "POST: Only 1 finished signal sent.");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, true);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  tet_printf("  FailImageLoad\n");
+
+  FailImageLoad(application, imageRequestId); // Need to run Update again for this to complete
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) ); // nothing to draw
+  application.SendNotification();
+
+  // Drawing empty framebuffer, so will still get a GL sync
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  sync.SetObjectSynced( lastSyncObj, true );
+
+  // Expect finished signal, as all resources are complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once, using loading image\nPRE: Resources not ready, Source not visible\nPOST: Finished signal sent once only");
+
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING - expect immediate rendering yet
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync02(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once, using Mesh which accesses texture through sampler with loading image.\n"
+               "PRE: Resources not ready\nPOST: Finished signal sent once only");
+  // SETUP AN OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  Material material = CreateMaterial(1.0f);
+  Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor secondRootActor = Actor::New();
+  secondRootActor.AddRenderer(renderer);
+  secondRootActor.SetSize(100, 100);
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ONCE, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING - expect immediate rendering yet
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false ) );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync03(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once, using loading image. Switch from render always after ready to render once\n"
+               "PRE: Render task ready, Image not loaded\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync04(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once, using Mesh which accesses texture through sampler with loading image.\n"
+               "Switch from render always after ready to render once\n"
+               "PRE: Render task ready, Image not loaded\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  Material material = CreateMaterial(1.0f);
+  Sampler sampler = CreateSamplerWithLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  material.AddSampler( sampler );
+
+  Geometry geometry = CreateQuadGeometry();
+  Renderer renderer = Renderer::New(geometry, material);
+  Actor secondRootActor = Actor::New();
+  secondRootActor.AddRenderer(renderer);
+  secondRootActor.SetSize(100, 100);
+  Stage::GetCurrent().Add(secondRootActor);
+
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+  application.GetPlatform().ClearReadyResources();
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync05(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "Switch from Render always after ready to render once with resources unready\n"
+               "PRE: Everything ready to render\n"
+               "POST: Finished signal sent once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // CHANGE TO RENDER ONCE
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true, false  ) );
+  END_TEST;
+}
+
+#if 0
+//int UtcDaliRenderTaskOnceNoSync06(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "During RenderOnce, make ready resources unready before sending first finished signal\n"
+               "PRE: Everything ready.\n"
+               "POST: Finished signal sent only once");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE, RESOURCES BECOME NOT READY
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+
+  // Doesn't work...
+  ReloadImage(application, secondRootActor.GetImage());
+  application.SendNotification(); //         Input,    Expected  Input,    Expected
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_EQUALS( secondRootActor.GetImage().GetLoadingState(), Dali::ResourceLoading, TEST_LOCATION);
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // FINISH RESOURCE LOADING
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, true, true ) );
+  application.GetPlatform().ClearReadyResources();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true  ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, false, true ) );
+  END_TEST;
+}
+#endif
+
+int UtcDaliRenderTaskOnceNoSync07(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "Render once, Second call to SetRefreshRate(ONCE) triggers only one more finished signal\n"
+               "PRE: Everything ready\n"
+               "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync08(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "Render once, Call to SetRefreshRate(ONCE) in Finished signal callback triggers\n"
+               "another render & another finished signal\n"
+               "PRE: Everything ready\n"
+               "POST: exactly 1 finished signal per call to SetRefreshRate(ONCE)");
+
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+
+  ConnectionTracker connectionTracker;
+  RenderTaskFinishedRenderAgain renderTaskFinishedRenderAgain( finished );
+  newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinishedRenderAgain );
+
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+
+  // Expect SetRefreshRate to have been called again
+  // Prevent next finished signal calling refresh once again
+  RenderTaskFinished renderTaskFinished( finished );
+  connectionTracker.DisconnectAll();
+  newTask.FinishedSignal().Connect( &connectionTracker, renderTaskFinished );
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskOnceNoSync09(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "SetRefreshRate(ONCE) again before first finished signal has been sent.\n"
+               "PRE: resources ready\n"
+               "POST: Only 1 finished signal sent.");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  application.Render();
+  application.GetPlatform().ClearReadyResources();
+
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, false ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,   finished, true,  false ) );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskOnceNoSync10(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once\n"
+               "SetRefreshRate(ONCE), resource load failed, completes render task.\n"
+               "PRE: resources not ready\n"
+               "POST: Only 1 finished signal sent.");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor rootActor = Actor::New();
+  Stage::GetCurrent().Add( rootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor secondRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Stage::GetCurrent().Add(secondRootActor);
+
+  RenderTask newTask = CreateRenderTask(application, offscreenCameraActor, rootActor, secondRootActor, RenderTask::REFRESH_ALWAYS, false);
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,     Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  // CHANGE TO RENDER ONCE,
+  newTask.SetRefreshRate(RenderTask::REFRESH_ONCE);
+  application.SendNotification();
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) );
+
+  FailImageLoad(application, imageRequestId); // Need to run Update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, false, true ) ); // nothing to draw
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,    finished, true,  false  ) );
+
+  END_TEST;
+}
+
+
+
+int UtcDaliRenderTaskOnceChain01(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask Render Once Chained render tasks\n"
+               "SetRefreshRate(ONCE), resource load completes, both render tasks render.\n"
+               "PRE: resources not ready\n"
+               "POST: 2 finished signals sent.");
+
+  // SETUP A CONTINUOUS OFFSCREEN RENDER TASK
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TraceCallStack& drawTrace = application.GetGlAbstraction().GetDrawTrace();
+  drawTrace.Enable(true);
+
+  Actor defaultRootActor = Actor::New(); // Root for default RT
+  Stage::GetCurrent().Add( defaultRootActor );
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+  Stage::GetCurrent().Add( offscreenCameraActor );
+  ImageActor firstRootActor = CreateLoadingImage(application, "aFile.jpg", ResourceImage::IMMEDIATE, Image::UNUSED);
+  Integration::ResourceRequest* imageRequest = application.GetPlatform().GetRequest();
+  Integration::ResourceId imageRequestId = imageRequest->GetId();
+  Integration::ResourceTypeId imageType  = imageRequest->GetType()->id;
+  Stage::GetCurrent().Add(firstRootActor);
+
+  // first render task
+  RenderTask firstTask = CreateRenderTask(application, offscreenCameraActor, defaultRootActor, firstRootActor, RenderTask::REFRESH_ONCE, false);
+  bool firstFinished = false;
+  RenderTaskFinished renderTask1Finished( firstFinished );
+  firstTask.FinishedSignal().Connect( &application, renderTask1Finished );
+
+  // Second render task
+  FrameBufferImage fbo = firstTask.GetTargetFrameBuffer();
+  ImageActor secondRootActor = ImageActor::New( fbo );
+  Stage::GetCurrent().Add(secondRootActor);
+  RenderTask secondTask = CreateRenderTask(application, offscreenCameraActor, defaultRootActor, secondRootActor, RenderTask::REFRESH_ONCE, false);
+  bool secondFinished = false;
+  RenderTaskFinished renderTask2Finished( secondFinished );
+  secondTask.FinishedSignal().Connect( &application, renderTask2Finished );
+
+  application.SendNotification();
+
+  // START PROCESS/RENDER                    Input,    Expected  Input,    Expected
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,  firstFinished, false, true ) );
+  DALI_TEST_CHECK( secondFinished == false );
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,  firstFinished, false, true ) );
+  DALI_TEST_CHECK( secondFinished == false );
+
+  CompleteImageLoad(application, imageRequestId, imageType); // Need to run update again for this to complete
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, true,  firstFinished, false, true ) );
+  DALI_TEST_CHECK( secondFinished == false );
+  application.GetPlatform().ClearReadyResources();
+
+  DALI_TEST_CHECK( UpdateRender(application, drawTrace, false,  firstFinished, true,  false ) );
+  DALI_TEST_CHECK( secondFinished == true );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskProperties(void)
+{
+  TestApplication application;
+
+  RenderTask task = Stage::GetCurrent().GetRenderTaskList().CreateTask();
+
+  Property::IndexContainer indices;
+  task.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() );
+  DALI_TEST_EQUALS( indices.Size(), task.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskSetScreenToFrameBufferMappingActor(void)
+{
+  TestApplication application;
+  tet_infoline("Testing RenderTask::SetScreenToFrameBufferMappingActor ");
+
+  Stage stage = Stage::GetCurrent();
+  Size stageSize = stage.GetSize();
+  Actor mappingActor = Actor::New();
+  Vector2 scale( 0.6f, 0.75f);
+  Vector2 offset( stageSize.x*0.1f, stageSize.y*0.15f);
+  mappingActor.SetSize( stageSize * scale );
+  mappingActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  mappingActor.SetPosition( offset.x, offset.y );
+  stage.Add( mappingActor );
+
+  Actor offscreenActor = Actor::New();
+  offscreenActor.SetSize( stageSize );
+  offscreenActor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  stage.Add( offscreenActor );
+
+  RenderTaskList taskList = stage.GetRenderTaskList();
+  RenderTask renderTask = taskList.CreateTask();
+  FrameBufferImage frameBufferImage =  FrameBufferImage::New(stageSize.width*scale.x, stageSize.height*scale.y, Pixel::A8, Image::NEVER);
+  renderTask.SetSourceActor( offscreenActor );
+  renderTask.SetExclusive( true );
+  renderTask.SetInputEnabled( true );
+  renderTask.SetTargetFrameBuffer( frameBufferImage );
+  renderTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
+  renderTask.SetScreenToFrameBufferMappingActor( mappingActor );
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+  application.Render();
+  application.SendNotification();
+
+  Vector2 screenCoordinates( stageSize.x * 0.05f, stageSize.y * 0.05f );
+  Dali::HitTestAlgorithm::Results results;
+  DALI_TEST_CHECK( !results.actor );
+  DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION );
+  // miss expected, results not changed
+  DALI_TEST_CHECK( false == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) );
+  DALI_TEST_CHECK( !results.actor );
+  DALI_TEST_EQUALS( Vector2::ZERO, results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  screenCoordinates.x = stageSize.x * 0.265f;
+  screenCoordinates.y = stageSize.y * 0.33f;
+  results.actor = Actor();
+  results.actorCoordinates = Vector2::ZERO;
+  // hit expected, results changed
+  DALI_TEST_CHECK( true == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) );
+  DALI_TEST_CHECK( results.actor  == offscreenActor );
+  DALI_TEST_EQUALS( (screenCoordinates-offset)/scale , results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  screenCoordinates.x = stageSize.x * 0.435f;
+  screenCoordinates.y = stageSize.y * 0.52f;
+  // hit expected, results changed
+  DALI_TEST_CHECK( true == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) );
+  DALI_TEST_CHECK( results.actor  == offscreenActor );
+  const Vector2 expectedCoordinates = (screenCoordinates-offset)/scale;
+  DALI_TEST_EQUALS( expectedCoordinates , results.actorCoordinates, 0.1f, TEST_LOCATION );
+
+  screenCoordinates.x = stageSize.x * 0.65f;
+  screenCoordinates.y = stageSize.y * 0.95f;
+  // miss expected, results not changed
+  DALI_TEST_CHECK( false == Dali::HitTestAlgorithm::HitTest( renderTask, screenCoordinates, results, IsActorHittableFunction ) );
+  DALI_TEST_CHECK( results.actor  == offscreenActor );
+  DALI_TEST_EQUALS( expectedCoordinates , results.actorCoordinates, 0.1f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskFinishInvisibleSourceActor(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTask::SignalFinished()");
+
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE );
+  TestGlSyncAbstraction& sync = application.GetGlSyncAbstraction();
+
+  CameraActor offscreenCameraActor = CameraActor::New();
+
+  Stage::GetCurrent().Add( offscreenCameraActor );
+
+  BufferImage image = BufferImage::New( 10, 10 );
+  ImageActor rootActor = ImageActor::New( image );
+  rootActor.SetSize( 10, 10 );
+  rootActor.SetVisible(false);
+  Stage::GetCurrent().Add( rootActor );
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  NativeImageInterfacePtr testNativeImagePtr = TestNativeImage::New(10, 10);
+  FrameBufferImage frameBufferImage = FrameBufferImage::New( *testNativeImagePtr.Get() );
+
+  // Flush all outstanding messages
+  application.SendNotification();
+  application.Render();
+
+  RenderTask newTask = taskList.CreateTask();
+  newTask.SetCameraActor( offscreenCameraActor );
+  newTask.SetSourceActor( rootActor );
+  newTask.SetInputEnabled( false );
+  newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) );
+  newTask.SetClearEnabled( true );
+  newTask.SetExclusive( true );
+  newTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
+  newTask.SetTargetFrameBuffer( frameBufferImage );
+
+  // Framebuffer doesn't actually get created until Connected, i.e. by previous line
+
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+
+  // Flush the queue and render.
+  application.SendNotification();
+
+  // 1 render to process render task, then wait for sync before finished msg is sent
+  // from update to the event thread.
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  Integration::GlSyncAbstraction::SyncObject* lastSyncObj = sync.GetLastSyncObject();
+  DALI_TEST_CHECK( lastSyncObj != NULL );
+
+  application.Render();
+  DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION );
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  application.Render();
+  DALI_TEST_EQUALS( (application.GetUpdateStatus() & Integration::KeepUpdating::RENDER_TASK_SYNC), Integration::KeepUpdating::RENDER_TASK_SYNC, TEST_LOCATION );
+  application.SendNotification();
+  DALI_TEST_CHECK( ! finished );
+
+  sync.SetObjectSynced( lastSyncObj, true );
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( !finished );
+
+  application.Render();
+  application.SendNotification();
+  DALI_TEST_CHECK( finished );
+  finished = false;
+
+  application.Render(); // Double check no more finished signal
+  application.SendNotification();
+  DALI_TEST_CHECK( ! finished );
+
+  END_TEST;
+}
+
+int UtcDaliRenderTaskFinishMissingImage(void)
+{
+  TestApplication application;
+
+  // Previously we had bugs where not having a resource ID would cause render-tasks to wait forever
+  tet_infoline("Testing RenderTask::SignalFinished() when an ImageActor has no Image set");
+
+  Stage stage = Stage::GetCurrent();
+
+  BufferImage image = BufferImage::New( 10, 10 );
+  ImageActor rootActor = ImageActor::New( image );
+  rootActor.SetSize( 10, 10 );
+  stage.Add( rootActor );
+
+  ImageActor actorWithMissingImage = ImageActor::New( Image() );
+  actorWithMissingImage.SetSize( 10, 10 );
+  stage.Add( actorWithMissingImage );
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask newTask = taskList.CreateTask();
+  newTask.SetInputEnabled( false );
+  newTask.SetClearColor( Vector4( 0.f, 0.f, 0.f, 0.f ) );
+  newTask.SetClearEnabled( true );
+  newTask.SetExclusive( true );
+  newTask.SetRefreshRate( RenderTask::REFRESH_ONCE );
+
+  bool finished = false;
+  RenderTaskFinished renderTaskFinished( finished );
+  newTask.FinishedSignal().Connect( &application, renderTaskFinished );
+
+  // 1 render to process render task, then 1 before finished msg is sent from update to the event thread.
+  application.SendNotification();
+  application.Render();
+  application.Render();
+
+  application.SendNotification();
+  DALI_TEST_CHECK( finished );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-RenderTaskList.cpp b/automated-tests/src/dali/utc-Dali-RenderTaskList.cpp
new file mode 100644 (file)
index 0000000..2d69397
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_render_task_list_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_render_task_list_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliRenderTaskListDefaultConstructor(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::RenderTaskList()");
+
+  RenderTaskList taskList;
+
+  DALI_TEST_CHECK( ! taskList );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListCopyConstructor(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::RenderTaskList(const RenderTaskList& handle)");
+
+  RenderTaskList taskList1;
+
+  RenderTaskList taskList2( taskList1 );
+
+  DALI_TEST_CHECK( ! taskList2 );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListAssignment(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::RenderTaskList(const RenderTaskList& handle)");
+
+  RenderTaskList taskList1;
+
+  RenderTaskList taskList2;
+
+  taskList1 = taskList2;
+
+  DALI_TEST_CHECK( ! taskList1 );
+  END_TEST;
+}
+
+
+int UtcDaliRenderTaskListDownCast(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::DownCast()");
+
+  BaseHandle base = Stage::GetCurrent().GetRenderTaskList();
+
+  RenderTaskList taskList = RenderTaskList::DownCast( base );
+
+  DALI_TEST_CHECK( taskList );
+
+  // Try calling a method
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListCreateTask(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::CreateTask()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+
+  taskList.CreateTask();
+  DALI_TEST_CHECK( 2u == taskList.GetTaskCount() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListRemoveTask(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::RemoveTask()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_CHECK( 2u == taskList.GetTaskCount() );
+
+  taskList.RemoveTask( newTask );
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListGetTaskCount(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::GetTaskCount()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+
+  taskList.RemoveTask( taskList.GetTask(0u) );
+  DALI_TEST_CHECK( 0u == taskList.GetTaskCount() );
+  END_TEST;
+}
+
+int UtcDaliRenderTaskListGetTask(void)
+{
+  TestApplication application;
+
+  tet_infoline("Testing RenderTaskList::GetTask()");
+
+  RenderTaskList taskList = Stage::GetCurrent().GetRenderTaskList();
+  RenderTask defaultTask = taskList.GetTask( 0u );
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+  DALI_TEST_CHECK( defaultTask );
+  DALI_TEST_CHECK( defaultTask == taskList.GetTask( 0u ) );
+
+  RenderTask newTask = taskList.CreateTask();
+  DALI_TEST_CHECK( 2u == taskList.GetTaskCount() );
+
+  RenderTask temp = taskList.GetTask( 0u );
+  RenderTask temp2 = taskList.GetTask( 1u );
+
+  DALI_TEST_CHECK( newTask );
+  DALI_TEST_CHECK( defaultTask != newTask );
+  DALI_TEST_CHECK( taskList.GetTask( 0u ) == defaultTask );
+  DALI_TEST_CHECK( taskList.GetTask( 1u ) == newTask );
+  DALI_TEST_CHECK( taskList.GetTask( 1u ) != defaultTask );
+
+  taskList.RemoveTask( taskList.GetTask(0u) );
+  DALI_TEST_CHECK( 1u == taskList.GetTaskCount() );
+  DALI_TEST_CHECK( taskList.GetTask( 0u ) != defaultTask  );
+  DALI_TEST_CHECK( taskList.GetTask( 0u ) == newTask );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-ResourceImage.cpp b/automated-tests/src/dali/utc-Dali-ResourceImage.cpp
new file mode 100644 (file)
index 0000000..df2ee7e
--- /dev/null
@@ -0,0 +1,491 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <algorithm>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_resource_image_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_resource_image_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+static const char* gTestImageFilename = "icon_wrt.png";
+
+namespace
+{
+
+void LoadBitmapResource(TestPlatformAbstraction& platform)
+{
+  Integration::ResourceRequest* request = platform.GetRequest();
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD );
+  Integration::ResourcePointer resource(bitmap);
+  bitmap->GetPackedPixelsProfile()->ReserveBuffer(Pixel::RGBA8888, 80, 80, 80, 80);
+
+  if(request)
+  {
+    platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resource);
+  }
+}
+
+} // namespace
+
+
+// 1.1
+int UtcDaliResourceImageNew01(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliResourceImageNew01 - ResourceImage::New(const std::string&)");
+
+  // invoke default handle constructor
+  ResourceImage image;
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = ResourceImage::New(gTestImageFilename);
+
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+// 1.2
+int UtcDaliResourceImageNew02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliREsourceImageNew02 - ResourceImage New( const std::string& url, ImageDimensions size, FittingMode scalingMode, SamplingMode samplingMode, bool orientationCorrection = true )");
+
+  // invoke default handle constructor
+  ResourceImage image;
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = ResourceImage::New(gTestImageFilename, ImageDimensions( 128, 256 ), FittingMode::FIT_HEIGHT );
+
+  DALI_TEST_CHECK( image );
+  END_TEST;
+}
+
+// 1.3
+int UtcDaliResourceImageNewWithPolicies01(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+
+  // testing delayed loading
+  tet_infoline("UtcDaliResourceImageNewWithPolicies01 - Load image with LoadPolicy::OnDemand, ReleasePolicy::Never");
+  DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::NEVER);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading only when actor added to stage
+  DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  ImageActor actor = ImageActor::New(image);
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  // testing ReleasePolicy::Never
+  // fake loading image
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+  LoadBitmapResource( platform );
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // never discard texture
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+  END_TEST;
+}
+
+// 1.4
+int UtcDaliResourceImageNewWithPolicies02(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  const Vector2 closestImageSize( 80, 45);
+  platform.SetClosestImageSize(closestImageSize);
+
+  // testing resource deletion when taken off stage
+  tet_infoline("UtcDaliResourceImageNewWithPolicies02 - Load image with LoadPolicy::OnDemand, ReleasePolicy::Unused");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::UNUSED);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading only when actor added to stage
+  DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  ImageActor actor = ImageActor::New(image);
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  // testing ReleasePolicy::Unused
+  // fake loading image
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+  LoadBitmapResource( platform );
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // discard texture when actor comes off stage
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) );
+  END_TEST;
+}
+
+// 1.5
+int UtcDaliResourceImageNewWithPolicies03(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  const Vector2 closestImageSize( 80, 45);
+  platform.SetClosestImageSize(closestImageSize);
+
+  // load immediately -> resource deletion when taken off stage -> put actor back on stage -> load resource again
+  tet_infoline("UtcDaliResourceImageNewWithPolicies03 - Load image with LoadPolicy::Immediate, ReleasePolicy::Unused");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::UNUSED);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading immediately
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  ImageActor actor = ImageActor::New(image);
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  // testing ReleasePolicy::Unused
+  // fake loading image
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+  LoadBitmapResource( platform );
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // discard texture when actor comes off stage
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // check load request when actor added back to stage
+  application.GetPlatform().ResetTrace();
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  END_TEST;
+}
+
+// 1.6
+int UtcDaliResourceImageNewWithPolicies04(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+
+  // load immediately, don't release texture when off stage
+  tet_infoline("UtcDaliResourceImageNewWithPolicies03 - Load image with LoadPolicy::Immediate, ReleasePolicy::Never");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::IMMEDIATE, Image::NEVER);
+
+  DALI_TEST_CHECK( image );
+
+  application.SendNotification();
+  application.Render(16);
+
+  // request file loading immediately
+  DALI_TEST_CHECK( platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+
+  ImageActor actor = ImageActor::New(image);
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+
+  // testing ReleasePolicy::Never
+  // fake loading image
+  std::vector<GLuint> ids;
+  ids.push_back( 23 );
+  application.GetGlAbstraction().SetNextTextureIds( ids );
+  LoadBitmapResource(platform);
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // texture is not discarded
+  Stage::GetCurrent().Remove(actor);
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  DALI_TEST_CHECK ( !application.GetGlAbstraction().CheckTextureDeleted(23) );
+
+  // no load request when actor added back to stage
+  application.GetPlatform().ResetTrace();
+
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+
+  DALI_TEST_CHECK( !platform.WasCalled(TestPlatformAbstraction::LoadResourceFunc) );
+  END_TEST;
+}
+
+// 1.7
+int UtcDaliResourceImageDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ResourceImage::DownCast()");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename);
+
+  BaseHandle object(image);
+
+  ResourceImage image2 = ResourceImage::DownCast(object);
+  DALI_TEST_CHECK(image2);
+
+  ResourceImage image3 = DownCast< ResourceImage >(object);
+  DALI_TEST_CHECK(image3);
+
+  BaseHandle unInitializedObject;
+  ResourceImage image4 = ResourceImage::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!image4);
+
+  ResourceImage image5 = DownCast< ResourceImage >(unInitializedObject);
+  DALI_TEST_CHECK(!image5);
+
+  Image image6 = ResourceImage::New(gTestImageFilename);
+  ResourceImage image7 = ResourceImage::DownCast(image6);
+  DALI_TEST_CHECK(image7);
+  END_TEST;
+}
+
+// 1.8
+int UtcDaliResourceImageGetImageSize(void)
+{
+  TestApplication application;
+  TestPlatformAbstraction& platform = application.GetPlatform();
+
+  tet_infoline("UtcDaliResourceImageGetImageSize - ResourceImage::GetImageSize()");
+
+  Vector2 testSize(8.0f, 16.0f);
+  platform.SetClosestImageSize(testSize);
+
+  const ImageDimensions size = ResourceImage::GetImageSize(gTestImageFilename);
+
+  DALI_TEST_CHECK( application.GetPlatform().GetTrace().FindMethod("GetClosestImageSize"));
+  DALI_TEST_EQUALS( Vector2( size.GetX(), size.GetY() ), testSize, TEST_LOCATION);
+  END_TEST;
+}
+
+// 1.9
+int UtcDaliResourceImageGetUrl(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliResourceImageGetFilename - ResourceImage::GetUrl()");
+
+  // invoke default handle constructor
+  ResourceImage image;
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = ResourceImage::New(gTestImageFilename);
+
+  DALI_TEST_EQUALS( image.GetUrl(), gTestImageFilename, TEST_LOCATION);
+  END_TEST;
+}
+
+// 1.10
+int UtcDaliResourceImageGetLoadingState01(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliResourceImageGetLoadingState01");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename);
+  DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoading);
+  application.SendNotification();
+  application.Render(16);
+
+  // simulate load success
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  LoadBitmapResource( platform );
+  application.Render(16);
+  application.SendNotification();
+
+  // Test state == ResourceLoadingSucceeded
+  DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoadingSucceeded);
+  END_TEST;
+}
+
+// 1.11
+int UtcDaliResourceImageGetLoadingState02(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliResourceImageGetLoadingState02");
+
+  // invoke default handle constructor
+  ResourceImage image;
+
+  DALI_TEST_CHECK( !image );
+
+  // initialise handle
+  image = ResourceImage::New(gTestImageFilename);
+
+  // Test state == ResourceLoading
+  DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoading);
+  application.SendNotification();
+  application.Render(16);
+
+  // simulate load failure
+  Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+  if(request)
+  {
+    application.GetPlatform().SetResourceLoadFailed(request->GetId(), Integration::FailureUnknown);
+  }
+  application.Render(16);
+  application.SendNotification();
+
+  // Test state == ResourceLoadingFailed
+  DALI_TEST_CHECK(image.GetLoadingState() == ResourceLoadingFailed);
+  END_TEST;
+}
+
+// 1.12
+int UtcDaliResourceImageGetLoadPolicy(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliImageGetLoadPolicy");
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename, ResourceImage::ON_DEMAND, Image::NEVER);
+
+  DALI_TEST_CHECK( image );
+
+  DALI_TEST_CHECK( ResourceImage::ON_DEMAND == image.GetLoadPolicy());
+  END_TEST;
+}
+
+static bool SignalLoadFlag = false;
+
+static void SignalLoadHandler(ResourceImage image)
+{
+  tet_infoline("Received image load finished signal");
+
+  SignalLoadFlag = true;
+}
+
+// 1.13
+int UtcDaliResourceImageSignalLoadingFinished(void)
+{
+  TestApplication application;
+
+  tet_infoline("UtcDaliResourceImageSignalLoadingFinished");
+
+  SignalLoadFlag = false;
+
+  ResourceImage image = ResourceImage::New(gTestImageFilename);
+
+  image.LoadingFinishedSignal().Connect( SignalLoadHandler );
+  application.SendNotification();
+  application.Render(16);
+
+  Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+  if(request)
+  {
+    application.GetPlatform().SetResourceLoaded(request->GetId(), request->GetType()->id, Integration::ResourcePointer(Integration::Bitmap::New(Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_DISCARD)));
+  }
+
+  application.Render(16);
+  application.SendNotification();
+
+  DALI_TEST_CHECK( SignalLoadFlag == true );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-ShaderEffect.cpp b/automated-tests/src/dali/utc-Dali-ShaderEffect.cpp
new file mode 100644 (file)
index 0000000..0ce5d47
--- /dev/null
@@ -0,0 +1,949 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_shader_effect_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_shader_effect_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+static const char* VertexSource =
+"This is a custom vertex shader\n"
+"made on purpose to look nothing like a normal vertex shader inside dali\n";
+
+static const char* FragmentSource =
+"This is a custom fragment shader\n"
+"made on purpose to look nothing like a normal fragment shader inside dali\n";
+
+const int GETSOURCE_BUFFER_SIZE = 0x10000;
+
+
+struct TestConstraintToVector3
+{
+  TestConstraintToVector3(Vector3 target)
+  : mTarget(target)
+  {
+  }
+
+  void operator()( Vector3& current, const PropertyInputContainer& /* inputs */ )
+  {
+    current = mTarget;
+  }
+
+  Vector3 mTarget;
+};
+
+struct TestConstraintFromPositionToVector3
+{
+  TestConstraintFromPositionToVector3()
+  {
+  }
+
+  void operator()( Vector3& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetVector3();
+  }
+};
+
+struct TestConstraintToVector3Double
+{
+  TestConstraintToVector3Double(Vector3 target)
+  : mTarget(target)
+  {
+  }
+
+  void operator()( Vector3& current, const PropertyInputContainer& /* inputs */ )
+  {
+    current = mTarget * 2.0f;
+  }
+
+  Vector3 mTarget;
+};
+
+static const char* TestImageFilename = "icon_wrt.png";
+
+Integration::Bitmap* CreateBitmap( unsigned int imageHeight, unsigned int imageWidth, unsigned int initialColor )
+{
+  Integration::Bitmap* bitmap = Integration::Bitmap::New( Integration::Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Integration::PixelBuffer* pixbuffer = bitmap->GetPackedPixelsProfile()->ReserveBuffer( Pixel::RGBA8888,  imageWidth,imageHeight,imageWidth,imageHeight );
+  unsigned int bytesPerPixel = GetBytesPerPixel(  Pixel::RGBA8888 );
+
+  memset( pixbuffer,  initialColor , imageHeight*imageWidth*bytesPerPixel);
+
+  return bitmap;
+}
+
+} // anon namespace
+
+
+int UtcDaliShaderEffectMethodNew01(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK(effect);
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodNew02(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect;
+
+  try
+  {
+    // New must be called to create a ShaderEffect or it wont be valid.
+    effect.SetUniform( "uUniform", 0 );
+    DALI_TEST_CHECK( false );
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_CHECK( !effect );
+  }
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodNew05(void)
+{
+  TestApplication application;
+
+  // heap constructor / destructor
+  DefaultFunctionCoverage<ShaderEffect> shaderEffect;
+
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::ShaderEffect::DownCast()");
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+
+  BaseHandle object(effect);
+
+  ShaderEffect effect2 = ShaderEffect::DownCast(object);
+  DALI_TEST_CHECK(effect2);
+
+  ShaderEffect effect3 = DownCast< ShaderEffect >(object);
+  DALI_TEST_CHECK(effect3);
+
+  BaseHandle unInitializedObject;
+  ShaderEffect effect4 = ShaderEffect::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!effect4);
+
+  ShaderEffect effect5 = DownCast< ShaderEffect >(unInitializedObject);
+  DALI_TEST_CHECK(!effect5);
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodDelete01(void)
+{
+   TestApplication application;
+
+   // get the default shaders built, this is not required but makes it
+   // easier to debug the TET case and isolate the custom shader compilation.
+   application.SendNotification();
+   application.Render();
+
+   GLuint beforeShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled();
+
+   // create a new shader effect
+   // the vertex and fragment shader will be cached in the ShaderFactory
+   ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+
+   // destroy the shader effect
+   effect.Reset();
+
+   // Create the same shader effect again, this should now use the cached version
+   // held in the shader factory
+   effect= ShaderEffect::New( VertexSource, FragmentSource );
+
+   // Compile the shader effect
+   application.SendNotification();
+   application.Render();
+
+   GLuint lastShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled();
+   // no shaders were compiled as they are now compiled on demand and this shader was not used
+   DALI_TEST_EQUALS( beforeShaderCompiled, lastShaderCompiled, TEST_LOCATION );
+
+   END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformFloat(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uFloat", 1.0f );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uFloat", 1.0f ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformVector2(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec2", Vector2( 2.0f, 3.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec2", Vector2( 2.0f, 3.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformVector3(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 4.0f, 5.0f, 6.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 4.0f, 5.0f, 6.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformVector4(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec4", Vector4( 7.0f, 8.0f, 9.0f, 10.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec4", Vector4( 7.0f, 8.0f, 9.0f, 10.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformMatrix(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uModelView", Matrix::IDENTITY );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uModelView", Matrix::IDENTITY ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformMatrix3(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  Matrix3 matIdentity(1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f);
+  effect.SetUniform( "uMatrix3", matIdentity );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue("uMatrix3", matIdentity) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetUniformViewport(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  effect.SetUniform( "uVec2", Vector2( 0.0f, 0.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION );
+  effect.SetUniform( "uVec2Dir", Vector2( 1.0f, 2.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION );
+
+  application.SendNotification();
+  application.Render();
+
+  const Vector2& stageSize(Stage::GetCurrent().GetSize());
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uVec2", Vector2( stageSize.x/2, -stageSize.y/2 ) ) );
+
+  DALI_TEST_CHECK( application.GetGlAbstraction().CheckUniformValue( "uVec2Dir", Vector2( -1.0f, 2.0f ) ) );
+
+  // change coordinate types
+  effect.SetUniform( "uVec2", Vector2( 0.1f, 0.2f ), ShaderEffect::COORDINATE_TYPE_DEFAULT );
+  effect.SetUniform( "uVec2Dir", Vector2( 1.0f, 2.0f ), ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION );
+  actor.SetPixelArea( ImageActor::PixelArea( 0, 0, 10, 10 ) );
+
+  application.SendNotification();
+  application.Render();
+
+  Vector2 outValue;
+  application.GetGlAbstraction().GetUniformValue( "uVec2", outValue );
+  DALI_TEST_EQUALS( outValue, Vector2( 0.1f, 0.2f ), TEST_LOCATION );
+
+  application.GetGlAbstraction().GetUniformValue( "uVec2Dir", outValue );
+  DALI_TEST_EQUALS( outValue, Vector2( stageSize.x *.5f - 1.f, -stageSize.y * .5f + 2.f), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetEffectImage(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetEffectImage(image);
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+
+  GLuint programId, uniformId;
+  bool uniformWasSet = application.GetGlAbstraction().GetUniformIds( "sEffect", programId, uniformId );
+  // we dont care about the value of the sampler uniform as thats internal to DALi core and subject to change
+  DALI_TEST_CHECK( uniformWasSet );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodSetEffectImageAndDelete(void)
+{
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+
+  BufferImage effectImage = CreateBufferImage();
+  effect.SetEffectImage(effectImage);
+
+  ImageActor actor = ImageActor::New();
+
+  actor.SetShaderEffect(effect);
+  effect.Reset();
+
+  Stage::GetCurrent().Add(actor);
+
+  // do an update / render cycle
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+  application.SendNotification();
+  application.Render(16);
+
+  printf("removing image actor from stage and Reseting handle\n");
+  Stage::GetCurrent().Remove(actor);
+  actor.Reset();
+
+  tet_printf("### Update & Render  \n");
+
+  application.SendNotification();
+  application.Render(16);
+
+  tet_printf("#### Update Only  \n");
+
+  tet_printf("effectImage.Reset \n");
+
+  // this releases the effect texture resource,
+  // Update will send a DispatchDiscardTexture message to render
+  effectImage.Reset();
+  application.SendNotification();
+  application.UpdateOnly(16);
+
+  tet_printf("#### Update Only \n");
+
+  // at this point shader is deleted, during clear discard queue
+  // and it sends a Shader:: DispatchRemoveObserver message to render thread
+  application.UpdateOnly(16);
+
+  tet_printf("#### Render Only  \n");
+  // This is where it used to crash, there is a message in the queue to perform DispatchDiscardTexture
+  // which tries to call observer->TextureDiscarded, where observer == shader that was deleted
+  // in previous update.
+  application.RenderOnly();
+
+
+  // process the discard texture message
+  application.RenderOnly();
+  application.SendNotification();
+  application.Render(16);
+
+  tet_result(TET_PASS);
+
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodApplyConstraint(void)
+{
+  // Test whether Shader's uniform can be constrained to a stationary constraint.
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of SetUniform...
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) );
+
+  Constraint constraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 4.0f, 9.0f, 16.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodApplyConstraintOffStage(void)
+{
+  // The same test as UtcDaliShaderEffectMethodApplyConstraint,
+  // except the Actor is off-stage when the constraint is applied to the shader
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  // Note - Do not add actor to stage here
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  Constraint constraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) );
+  constraint.Apply();
+
+  // Note - Now we add the actor (after constraint was applied to the shader)
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 4.0f, 9.0f, 16.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodApplyConstraintFromActor(void)
+{
+  // Test whether Shader's uniform can be constrained to Actor's position.
+  TestApplication application;
+
+  const Vector3 targetPosition = Vector3( 100.0f, 70.0f, 20.0f);
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 50.0f, 25.0f, 0.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetPosition(targetPosition);
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  Constraint constraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintFromPositionToVector3() );
+  constraint.AddSource( Source( actor, Actor::Property::POSITION ) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", targetPosition ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodApplyConstraintFromActor2(void)
+{
+  // Test whether Shader's uniform can be constrained to Actor's position.
+  // While Actor's position is constrained to another point * 2.0f
+  TestApplication application;
+
+  const Vector3 targetPosition = Vector3( 25.0f, 36.0f, 49.0f );
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 50.0f, 25.0f, 0.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetPosition(Vector3( 100.0f, 70.0f, 20.0f));
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  Constraint shaderConstraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintFromPositionToVector3() );
+  shaderConstraint.AddSource( Source(actor, Actor::Property::POSITION) );
+  shaderConstraint.Apply();
+
+  Constraint actorConstraint = Constraint::New<Vector3>( actor, Actor::Property::POSITION, TestConstraintToVector3Double(targetPosition) );
+  actorConstraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", targetPosition * 2.0f ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodRemoveConstraints(void)
+{
+  // Test if constrains can be removed before they are ever applyed.
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of SetUniform...
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) );
+
+  Constraint constraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) );
+  constraint.Apply();
+
+  // Remove the constraints
+  effect.RemoveConstraints();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectMethodRemoveConstraints2(void)
+{
+  // Test whether Shader's uniform constrains can be removed after they are applyed.
+  TestApplication application;
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+
+  effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) );
+
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  Property::Index uVecProperty = effect.GetPropertyIndex("uVec3");
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of SetUniform...
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) );
+
+  Constraint constraint = Constraint::New<Vector3>( effect, uVecProperty, TestConstraintToVector3(Vector3(4.0f, 9.0f, 16.0f)) );
+  constraint.Apply();
+
+  application.SendNotification();
+  application.Render();
+
+  // Reset the value and remove the constraints
+  effect.SetUniform( "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) );
+  effect.RemoveConstraints();
+
+  application.SendNotification();
+  application.Render();
+
+  // Test effects of Constraint.
+  DALI_TEST_CHECK(
+      application.GetGlAbstraction().CheckUniformValue(
+          "uVec3", Vector3( 1.0f, 2.0f, 3.0f ) ) );
+  END_TEST;
+}
+
+int UtcDaliShaderEffectPropertyIndices(void)
+{
+  TestApplication application;
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+
+  Property::IndexContainer indices;
+  effect.GetPropertyIndices( indices );
+  DALI_TEST_CHECK( indices.Size() );
+  DALI_TEST_EQUALS( indices.Size(), effect.GetPropertyCount(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliShaderBinaries(void)
+{
+  TestApplication application;
+  // these will not affect the "first round" of dali render as core is already initialized and it has queried the defaults
+  application.GetGlAbstraction().SetBinaryFormats( 1 );
+  application.GetGlAbstraction().SetNumBinaryFormats( 1 );
+  application.GetGlAbstraction().SetProgramBinaryLength( 1 );
+
+  GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  ShaderEffect effect = ShaderEffect::New( VertexSource, FragmentSource );
+  DALI_TEST_CHECK( effect );
+
+  BufferImage image = CreateBufferImage();
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render(16);
+  // binary was not requested by DALi
+  DALI_TEST_CHECK( !(application.GetGlAbstraction().GetProgramBinaryCalled()) );
+
+  GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  // check that the shader was compiled
+  DALI_TEST_EQUALS( lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION );
+
+  // simulate context loss to get core to re-initialize its GL
+  application.GetCore().ContextDestroyed();
+  application.GetCore().ContextCreated();
+
+  application.SendNotification();
+  application.Render(16);
+
+  // shader is recompiled
+  GLuint finalShaderCompiled = application.GetGlAbstraction().GetLastShaderCompiled();
+  // check that the shader was compiled
+  DALI_TEST_EQUALS( lastShaderCompiledAfter + 2, finalShaderCompiled, TEST_LOCATION );
+
+  // binary was requested by DALi
+  DALI_TEST_CHECK( application.GetGlAbstraction().GetProgramBinaryCalled() );
+
+  END_TEST;
+}
+
+int UtcDaliShaderEffectFromPropertiesP(void)
+{
+  TestApplication application;
+  tet_infoline("UtcDaliShaderEffectFromProperties01()");
+
+  std::string fragmentShaderPrefix = "#define TEST_FS 1\n#extension GL_OES_standard_derivatives : enable";
+  std::string vertexShaderPrefix = "#define TEST_VS 1";
+  std::string vertexShader(VertexSource);
+  std::string fragmentShader(FragmentSource);
+
+  // Call render to compile default shaders.
+  application.SendNotification();
+  application.Render();
+
+  GLuint lastShaderCompiledBefore = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  // create from type registry
+
+  TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" );
+  DALI_TEST_CHECK( typeInfo );
+  ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() );
+  DALI_TEST_CHECK( effect );
+
+  Property::Value programValue = Property::Value(Property::MAP);
+  Property::Map* programMap = programValue.GetMap();
+  DALI_TEST_CHECK( programMap );
+
+  programMap->Insert("vertex", vertexShader);
+  programMap->Insert("fragment", fragmentShader);
+
+  programMap->Insert("vertex-prefix", vertexShaderPrefix);
+  programMap->Insert("fragment-prefix", fragmentShaderPrefix);
+
+  effect.SetProperty(effect.GetPropertyIndex("program"), programValue);
+
+  Property::Value imageValue = Property::Value(Property::MAP);
+  Property::Map* imageMap = imageValue.GetMap();
+  DALI_TEST_CHECK( imageMap );
+  imageMap->Insert("filename", Property::Value(TestImageFilename));
+  effect.SetProperty(effect.GetPropertyIndex("image"), imageValue);
+
+  // do a update & render to get the image request
+  application.SendNotification();
+  application.Render();
+
+  Integration::ResourceRequest* request = application.GetPlatform().GetRequest();
+  // create the image
+  Integration::Bitmap* bitmap = CreateBitmap( 10, 10, 0xFF );
+  Integration::ResourcePointer resourcePtr(bitmap);
+  TestPlatformAbstraction& platform = application.GetPlatform();
+  platform.SetResourceLoaded(request->GetId(), request->GetType()->id, resourcePtr);
+
+  BufferImage image(CreateBufferImage());
+  ImageActor actor = ImageActor::New( image );
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetName("TestImageFilenameActor");
+  actor.SetShaderEffect(effect);
+  Stage::GetCurrent().Add(actor);
+
+  application.SendNotification();
+  application.Render();
+  GLuint lastShaderCompiledAfter = application.GetGlAbstraction().GetLastShaderCompiled();
+
+  // we should have compiled 2 shaders.
+  DALI_TEST_EQUALS(lastShaderCompiledAfter, lastShaderCompiledBefore + 2, TEST_LOCATION );
+
+  std::string actualVertexShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 1 );
+  DALI_TEST_EQUALS( vertexShaderPrefix, actualVertexShader.substr( 0, vertexShaderPrefix.length() ), TEST_LOCATION );
+  DALI_TEST_EQUALS( vertexShader, actualVertexShader.substr( actualVertexShader.length() - vertexShader.length() ), TEST_LOCATION );
+
+  std::string actualFragmentShader = application.GetGlAbstraction().GetShaderSource( lastShaderCompiledBefore + 2 );
+  DALI_TEST_EQUALS( fragmentShaderPrefix, actualFragmentShader.substr( 0, fragmentShaderPrefix.length() ), TEST_LOCATION );
+  DALI_TEST_EQUALS( fragmentShader, actualFragmentShader.substr( actualFragmentShader.length() - fragmentShader.length() ), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliShaderEffectFromPropertiesN(void)
+{
+  try
+  {
+    TestApplication application;
+    tet_infoline("UtcDaliShaderEffectFromProperties02()");
+
+    // Call render to compile default shaders.
+    application.SendNotification();
+    application.Render();
+
+    // create from type registry (currently only way to get ShaderEffect with no shader setup in constructor
+    TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" );
+    DALI_TEST_CHECK( typeInfo );
+    ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() );
+    DALI_TEST_CHECK( effect );
+
+    Property::Value programValue = Property::Value(Property::MAP);
+    Property::Map* programMap = programValue.GetMap();
+    DALI_TEST_CHECK( programMap );
+
+    programMap->Insert("vertex",   std::string(VertexSource));
+    programMap->Insert("fragment", std::string(FragmentSource));
+
+    // use wrong index on purpose
+    effect.SetProperty(effect.GetPropertyIndex("program") + 1, programValue );
+
+    tet_result( TET_FAIL );
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+  END_TEST;
+}
+
+int UtcDaliShaderEffectFromProperties2N(void)
+{
+  try
+  {
+    TestApplication application;
+    tet_infoline("UtcDaliShaderEffectFromProperties03()");
+
+    // Call render to compile default shaders.
+    application.SendNotification();
+    application.Render();
+
+    // create from type registry (currently only way to get ShaderEffect with no shader setup in constructor
+    TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( "ShaderEffect" );
+    DALI_TEST_CHECK( typeInfo );
+    ShaderEffect effect = ShaderEffect::DownCast( typeInfo.CreateInstance() );
+    DALI_TEST_CHECK( effect );
+
+    // dont set unknown
+    effect.SetProperty( effect.GetPropertyIndex("geometry-hints"), "HINT_2" );
+
+    tet_result( TET_FAIL );
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp b/automated-tests/src/dali/utc-Dali-SignalTemplates.cpp
new file mode 100644 (file)
index 0000000..e1e20d5
--- /dev/null
@@ -0,0 +1,2228 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iostream>
+#include <stdlib.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include "signal-helper.h"
+
+using namespace Dali;
+
+bool StaticFunctionHandlers::staticFunctionHandled;
+
+void utc_dali_signal_templates_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_signal_templates_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace {
+
+
+bool wasStaticVoidCallbackVoidCalled  = false;
+bool wasStaticFloatCallbackVoidCalled = false;
+bool wasStaticVoidCallbackIntValueCalled = false;
+int staticIntValue = 0;
+bool wasStaticFloatCallbackFloatValueFloatValueCalled = false;
+float staticFloatValue1 = 0.0f;
+float staticFloatValue2 = 0.0f;
+
+void StaticVoidCallbackVoid()
+{
+  wasStaticVoidCallbackVoidCalled = true;
+}
+
+void AlternativeVoidCallbackVoid()
+{
+}
+
+float StaticFloatCallbackVoid()
+{
+  wasStaticFloatCallbackVoidCalled = true;
+  return 7.0f;
+}
+
+void StaticVoidCallbackIntValue( int value )
+{
+  wasStaticVoidCallbackIntValueCalled = true;
+  staticIntValue = value;
+}
+
+float StaticFloatCallbackFloatValueFloatValue( float value1, float value2 )
+{
+  wasStaticFloatCallbackFloatValueFloatValueCalled = true;
+  staticFloatValue1 = value1;
+  staticFloatValue2 = value2;
+  return value1 + value2;
+}
+
+} // anon namespace
+
+
+
+/*******************************************
+ *
+ * Start of Utc test cases.
+ * Test cases performed in order of API listed in dali-signal.h
+ * UtcDaliSignal + FunctionName + P=positive test, N = Negative test
+ *
+ */
+
+int UtcDaliSignalEmptyP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // Test that Empty() is true, when no slots connected to the signal
+
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+  }
+
+  // Test that Empty() is true, when a slot has connected and disconnected
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    TestSlotHandler handler;
+    signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+    signal.Disconnect( &handler, &TestSlotHandler::VoidSlotVoid );
+    DALI_TEST_CHECK( signal.Empty() );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliSignalEmptyN(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // Test that Empty() is false after signal connection
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler handler;
+  signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  END_TEST;
+}
+
+int UtcDaliSignalGetConnectionCountP(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler handler;
+  signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( signal.GetConnectionCount() == 1 );
+
+  TestSlotHandler handler2;
+  signal.Connect( &handler2, &TestSlotHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( signal.GetConnectionCount() == 2 );
+
+  END_TEST;
+}
+
+int UtcDaliSignalGetConnectionCountN(void)
+{
+  TestApplication app; // Create core for debug logging
+  TestSignals::VoidRetNoParamSignal signal;
+  DALI_TEST_CHECK( signal.GetConnectionCount() == 0 );
+  END_TEST;
+}
+
+/**
+ * there are 5 different connection functions
+ * we go through them here in order of definition in dali-signal.h
+ */
+int UtcDaliSignalConnectP01(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test static function: void Connect( void (*func)() )
+  TestSignals::VoidRetNoParamSignal signal;
+  signal.Connect( StaticVoidCallbackVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+
+  END_TEST;
+}
+
+int UtcDaliSignalConnectN01(void)
+{
+  // difficult to perform a negative test on Connect as no checks are performed
+  // when creating a callback for a null function ( during Connect).
+  // so we test an assert on Emit
+  TestApplication app; // Create core for debug logging
+
+  TestSignals::VoidRetNoParamSignal signal;
+  signal.Connect( NULL );
+  try
+  {
+    signal.Emit();
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_PASS);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliSignalConnectP02(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test member function: Connect( X* obj, void (X::*func)() ))
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler handler;
+  signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Emit();
+  DALI_TEST_CHECK( handler.mHandled == true );
+  END_TEST;
+}
+
+int UtcDaliSignalConnectN02(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  TestSignals::VoidRetNoParamSignal signal;
+  try
+  {
+    // test member function: Connect( X* obj, void (X::*func)() )) with NULL object
+    signal.Connect( static_cast<TestSlotHandler*>(NULL), &TestSlotHandler::VoidSlotVoid );
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result(TET_PASS);
+  }
+  END_TEST;
+}
+
+
+int UtcDaliSignalConnectP03(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test slot delegate: Connect( SlotDelegate<X>& delegate, void (X::*func)() )
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotDelegateHandler handler;
+  signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Emit();
+  DALI_TEST_CHECK( handler.mHandled == true );
+
+  END_TEST;
+}
+
+int UtcDaliSignalConnectN03(void)
+{
+  TestApplication app; // Create core for debug logging
+  // the delegate is passed by reference, so you can't pass null.
+  tet_result( TET_PASS );
+  END_TEST;
+}
+
+int UtcDaliSignalConnectP04(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  //  test function object: Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  TestSlotHandler handler;
+  TestSignals::VoidRetNoParamSignal signal;
+  bool functorCalled(false);
+  TestFunctor functor( functorCalled );
+  signal.Connect( &handler, functor );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Emit();
+  DALI_TEST_CHECK( functorCalled == true );
+
+  END_TEST;
+}
+
+int UtcDaliSignalConnectN04(void)
+{
+  // for negative test we try to connect a null connection tracker to the signal
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler *nullHandler( NULL );
+  try
+  {
+    signal.Connect( nullHandler , &TestSlotHandler::VoidSlotVoid  );
+  }
+  catch (Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result( TET_PASS );
+  }
+
+  END_TEST;
+
+}
+
+int UtcDaliSignalConnectP05(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test function object using FunctorDelegate.
+  // :Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    TestSlotHandler handler;
+    TestSignals::VoidRetNoParamSignal signal;
+    bool functorDelegateCalled(false);
+    signal.Connect( &handler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) ));
+    DALI_TEST_CHECK( ! signal.Empty() );
+    signal.Emit();
+    DALI_TEST_CHECK( functorDelegateCalled == true );
+  }
+  {
+    TestSlotHandler handler;
+    TestSignals::VoidRet1ValueParamSignal signal;
+    bool functorDelegateCalled(false);
+    signal.Connect( &handler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) ));
+    DALI_TEST_CHECK( ! signal.Empty() );
+    signal.Emit(1);
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalConnectN05(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // for negative test we try to connect a null connection tracker to the signal
+  // :Connect( ConnectionTrackerInterface == NULL, FunctorDelegate* delegate )
+  TestSlotHandler *nullHandler( NULL );
+  TestSignals::VoidRetNoParamSignal signal;
+  bool functorDelegateCalled(false);
+  try
+  {
+    signal.Connect( nullHandler, FunctorDelegate::New( VoidFunctorVoid(functorDelegateCalled) ));
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    tet_result( TET_PASS );
+  }
+  END_TEST;
+}
+
+
+/**
+ * there 3 different disconnect functions
+ *  we go through them here in order of definition in dali-signal.h
+ */
+int UtcDaliSignalDisconnectP01(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test static function:  Disconnect( void (*func)( Arg0 arg0 ) )
+
+  TestSignals::VoidRetNoParamSignal signal;
+  signal.Connect( StaticVoidCallbackVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Disconnect( StaticVoidCallbackVoid );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  END_TEST;
+
+ }
+int UtcDaliSignalDisconnectN01(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // 1. Disconnect using the function
+  TestSignals::VoidRetNoParamSignal signal;
+  signal.Connect( StaticVoidCallbackVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  signal.Disconnect( AlternativeVoidCallbackVoid );
+
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnectP02(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test member function: Disconnect( X* obj, void (X::*func)( Arg0 arg0 ) )
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler handler;
+  signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Disconnect( &handler, &TestSlotHandler::VoidSlotVoid  );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  END_TEST;
+
+}
+int UtcDaliSignalDisconnectN02(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // 1. Disconnect using a null connection tracker
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotHandler handler;
+
+  signal.Connect( &handler , &TestSlotHandler::VoidSlotVoid  );
+  DALI_TEST_CHECK( !signal.Empty() );
+
+  try
+  {
+    TestSlotHandler* nullHandler( NULL );
+    signal.Disconnect( nullHandler , &TestSlotHandler::VoidSlotVoid  );
+  }
+  catch(Dali::DaliException& e)
+  {
+    // Tests that a negative test of an assertion succeeds
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_CHECK( !signal.Empty() );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnectP03(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // test slot delegate: Disconnect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0 ) )
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotDelegateHandler handler;
+  signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( ! signal.Empty() );
+  signal.Disconnect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnectN03(void)
+{
+  TestApplication app; // Create core for debug logging
+
+   // try to disconnect from the wrong signal
+  TestSignals::VoidRetNoParamSignal signal;
+  TestSlotDelegateHandler handler;
+  signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+
+  // use different signal
+  signal.Disconnect( handler.mSlotDelegate , &TestSlotDelegateHandler::AlternativeVoidSlotVoid  );
+
+  DALI_TEST_CHECK( !signal.Empty() );
+
+  END_TEST;
+
+}
+
+/*******************************************
+ *
+ * End of Utc test cases for the individual API's of Signals
+ * The following testing Signals functionality as a whole
+ *
+ *
+ */
+
+int UtcDaliSignalEmptyCheckSlotDestruction(void)
+{
+  // Test that signal disconnect works when slot is destroyed (goes out of scope)
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::VoidSlotVoid );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit();
+  }
+
+  {
+    TestSignals::VoidRet1ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::VoidSlotIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit( 10 );
+  }
+
+  {
+    TestSignals::VoidRet1RefParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::VoidSlotIntRef );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    int temp( 5 );
+    signal.Emit( temp );
+  }
+
+  {
+    TestSignals::VoidRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::VoidSlotIntValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit( 1, 2 );
+  }
+
+  {
+    TestSignals::BoolRet1ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::BoolSlotFloatValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    bool blah = signal.Emit( 1.0f );
+    DALI_TEST_CHECK( ! blah );
+  }
+
+  {
+    TestSignals::BoolRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::BoolSlotFloatValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    bool blah = signal.Emit( 1.0f, 2 );
+    DALI_TEST_CHECK( ! blah );
+  }
+
+  {
+    TestSignals::IntRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::IntSlotFloatValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    int blah = signal.Emit( 10.0f, 100 );
+    DALI_TEST_CHECK( 0 == blah );
+  }
+
+  {
+    TestSignals::FloatRet0ParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect( &handler, &TestSlotHandler::FloatSlotVoid );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    float blah = signal.Emit();
+    DALI_TEST_CHECK( 0.0f == blah );
+  }
+
+  {
+    TestSignals::FloatRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotHandler handler;
+      signal.Connect(&handler, &TestSlotHandler::FloatSlotFloatValueFloatValue);
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    float blah = signal.Emit( 3.0f, 4.0f );
+    DALI_TEST_CHECK( 0.0f == blah );
+  }
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliSignalConnectAndEmit01P(void)
+{
+  // Test basic signal emission for each slot type
+
+  TestSignals signals;
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+
+    // Test double emission
+    handlers.mHandled = false;
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    int x = 7;
+    signals.EmitVoidSignalIntRef(x);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignal1IntValue(5);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 5, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid2Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignal2IntValue(6, 7);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 6, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 7, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalBool1Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+
+    handlers.mBoolReturn = true;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+
+    // repeat with opposite return value
+    handlers.mBoolReturn = false;
+    handlers.mHandled = false;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(6.0f), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 6.0f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalBool2Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 10, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalInt2Value().Connect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mIntReturn = 27;
+    int x = signals.EmitIntSignalFloatValueIntValue(33.5f, 5);
+    DALI_TEST_EQUALS( x, 27, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 33.5f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 5, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalFloat0().Connect(&handlers, &TestSlotHandler::FloatSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float f = signals.EmitFloat0Signal();
+    DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalFloat2Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float f = signals.EmitFloat2VSignal(5, 33.0f);
+    DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.VoidSignalFloatValue3().Connect(&handlers, &TestSlotHandler::VoidSlotFloatValue3);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignalFloatValue3(5, 33.0f, 100.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalFloat3Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValue3);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float returnValue = signals.EmitFloat3VSignal(5, 33.0f, 100.0f);
+    DALI_TEST_EQUALS( returnValue, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+  END_TEST;
+}
+
+int UtcDaliSignalConnectAndEmit02P(void)
+{
+  // testing connection of static functions
+  TestSignals signals;
+  StaticFunctionHandlers handlers;
+
+  // void ( void )
+  signals.SignalVoidNone().Connect( &StaticFunctionHandlers::VoidSlotVoid );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitVoidSignalVoid();
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+
+  // void ( p1 )
+  handlers.Reset();
+  signals.SignalVoid1Value().Connect( &StaticFunctionHandlers::VoidSlot1Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitVoidSignal1IntValue( 1 );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+  // void ( p1, p2 )
+  handlers.Reset();
+  signals.SignalVoid2Value().Connect( &StaticFunctionHandlers::VoidSlot2Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitVoidSignal2IntValue( 1, 2 );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+
+  // void ( p1, p2, p3 )
+  handlers.Reset();
+  signals.SignalVoid3Value().Connect( &StaticFunctionHandlers::VoidSlot3Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitVoidSignal3IntValue( 1, 2, 3 );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+  // ret ( )
+  handlers.Reset();
+  signals.SignalFloat0().Connect( &StaticFunctionHandlers::RetSlot0Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitFloat0Signal();
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+  // ret ( p1 )
+  handlers.Reset();
+  signals.SignalFloat1Value().Connect( &StaticFunctionHandlers::RetSlot1Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitFloat1VSignal( 1.f );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+  // ret ( p1, p2 )
+  handlers.Reset();
+  signals.SignalFloat2Value().Connect( &StaticFunctionHandlers::RetSlot2Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitFloat2VSignal( 1.f, 2.f );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+
+  // ret ( p1, p2, p3 )
+  handlers.Reset();
+  signals.SignalFloat3Value().Connect( &StaticFunctionHandlers::RetSlot3Param );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, false, TEST_LOCATION );
+  signals.EmitFloat3VSignal( 1.f, 2.f, 3.f );
+  DALI_TEST_EQUALS( handlers.staticFunctionHandled, true, TEST_LOCATION );
+
+  END_TEST;
+
+}
+
+
+int UtcDaliSignalDisconnect(void)
+{
+  // Test that callbacks don't occur if a signal is disconnected before emission
+
+  TestSignals signals;
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    int r = 7;
+    handlers.mIntReturn = 5;
+    signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    signals.EmitVoidSignalIntRef(r);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( r, 7, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoid1Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValue);
+    signals.EmitVoidSignal1IntValue(5);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid2Value().Connect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoid2Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue);
+    signals.EmitVoidSignal2IntValue(5, 10);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalBool1Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    signals.SignalBool1Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalBool2Value().Connect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    signals.SignalBool2Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2,   0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalInt2Value().Connect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mIntReturn = 27;
+    signals.SignalInt2Value().Disconnect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue);
+    signals.EmitIntSignalFloatValueIntValue(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalFloat0().Connect(&handlers, &TestSlotHandler::FloatSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat0().Disconnect(&handlers, &TestSlotHandler::FloatSlotVoid);
+    signals.EmitFloat0Signal();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalFloat2Value().Connect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat2Value().Disconnect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue);
+    signals.EmitFloat2VSignal(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnect2(void)
+{
+  // Test that nothing happens when attempting to disconnect an unconnected slot
+
+  TestSignals signals;
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    int r = 7;
+    signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    signals.EmitVoidSignalIntRef(r);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( r, 7, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValue);
+    signals.EmitVoidSignal1IntValue(5);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid2Value().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntValueIntValue);
+    signals.EmitVoidSignal2IntValue(5, 10);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    handlers.mBoolReturn = true;
+    signals.SignalBool1Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    handlers.mBoolReturn = true;
+    signals.SignalBool2Value().Disconnect(&handlers, &TestSlotHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2,   0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    handlers.mIntReturn = 27;
+    signals.SignalInt2Value().Disconnect(&handlers, &TestSlotHandler::IntSlotFloatValueIntValue);
+    signals.EmitIntSignalFloatValueIntValue(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat2Value().Disconnect(&handlers, &TestSlotHandler::FloatSlotFloatValueFloatValue);
+    signals.EmitFloat2VSignal(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat0().Disconnect(&handlers, &TestSlotHandler::FloatSlotVoid);
+    signals.EmitFloat0Signal();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnect3(void)
+{
+  // Test that callbacks stop after a signal is disconnected
+
+  TestSignals signals;
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoidNone().Connect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+
+    // Emit first
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+
+    // Disconnect and emit again
+    handlers.mHandled = false;
+    signals.SignalVoidNone().Disconnect(&handlers, &TestSlotHandler::VoidSlotVoid);
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handlers;
+    signals.SignalVoid1Ref().Connect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    int r = 7;
+
+    // Emit first
+    signals.EmitVoidSignalIntRef(r);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION );
+
+    // Disconnect and emit again
+    handlers.mHandled = false;
+    handlers.mIntParam1 = 0;
+    signals.SignalVoid1Ref().Disconnect(&handlers, &TestSlotHandler::VoidSlotIntRef);
+    signals.EmitVoidSignalIntRef(r);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( r, 7, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalCustomConnectionTracker(void)
+{
+  // Test slot destruction
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestBasicConnectionTrackerInterface customTracker;
+      signal.Connect( &customTracker, &TestBasicConnectionTrackerInterface::VoidSlotVoid );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit();
+  }
+
+  TestBasicConnectionTrackerInterface customTracker2;
+
+  // Test signal emission & destruction
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+    DALI_TEST_EQUALS( 0u, customTracker2.GetConnectionCount(), TEST_LOCATION );
+
+    signal.Connect( &customTracker2, &TestBasicConnectionTrackerInterface::VoidSlotVoid );
+    DALI_TEST_CHECK( ! signal.Empty() );
+    DALI_TEST_EQUALS( 1u, customTracker2.GetConnectionCount(), TEST_LOCATION );
+
+    DALI_TEST_EQUALS( customTracker2.mCallbackHandled, false, TEST_LOCATION );
+    signal.Emit();
+    DALI_TEST_EQUALS( customTracker2.mCallbackHandled, true, TEST_LOCATION );
+  }
+  DALI_TEST_EQUALS( 0u, customTracker2.GetConnectionCount(), TEST_LOCATION );
+
+  // Test for removing a null callback
+  {
+     TestBasicConnectionTrackerInterface customTracker3;
+
+     TestSignals::VoidRetNoParamSignal signal;
+     DALI_TEST_CHECK( signal.Empty() );
+     DALI_TEST_EQUALS( 0u, customTracker3.GetConnectionCount(), TEST_LOCATION );
+
+     signal.Connect( &customTracker3, &TestBasicConnectionTrackerInterface::VoidSlotVoid );
+     DALI_TEST_CHECK( ! signal.Empty() );
+     DALI_TEST_EQUALS( 1u, customTracker3.GetConnectionCount(), TEST_LOCATION );
+     try
+     {
+       // should assert
+       customTracker3.RemoveNullCallback();
+       tet_result( TET_FAIL );
+     }
+     catch (Dali::DaliException& e)
+     {
+       tet_result( TET_PASS );
+     }
+   }
+
+  END_TEST;
+}
+
+int UtcDaliSignalMultipleConnections(void)
+{
+  // Test that multiple callbacks can be connected to the same signal
+
+  TestSignals signals;
+
+  {
+    TestSlotHandler handler1;
+    signals.SignalVoidNone().Connect( &handler1, &TestSlotHandler::VoidSlotVoid );
+    DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+
+    TestSlotHandler handler2;
+    signals.SignalVoidNone().Connect( &handler2, &TestSlotHandler::VoidSlotVoid );
+    DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+
+    // Remove first connection and repeat
+    handler1.Reset();
+    handler2.Reset();
+    signals.SignalVoidNone().Disconnect( &handler1, &TestSlotHandler::VoidSlotVoid );
+
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handler1;
+    signals.SignalVoid1Ref().Connect( &handler1, &TestSlotHandler::VoidSlotIntRef );
+    DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+
+    TestSlotHandler handler2;
+    signals.SignalVoid1Ref().Connect( &handler2, &TestSlotHandler::VoidSlotIntRef );
+    DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+
+    int x = 7;
+    signals.EmitVoidSignalIntRef(x);
+    DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 7, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mIntParam1, 7, TEST_LOCATION );
+
+    // Remove second connection and repeat
+    handler1.Reset();
+    handler2.Reset();
+    x = 8;
+    signals.SignalVoid1Ref().Disconnect( &handler2, &TestSlotHandler::VoidSlotIntRef );
+
+    signals.EmitVoidSignalIntRef(x);
+    DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 8, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mIntParam1, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotHandler handler1;
+    signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue );
+    DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+
+    TestSlotHandler handler2;
+    signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue );
+    DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+
+    TestSlotHandler handler3;
+    signals.SignalVoid1Value().Connect( &handler3, &TestSlotHandler::VoidSlotIntValue );
+    DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION );
+
+    signals.EmitVoidSignal1IntValue( 5 );
+    DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 5, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mIntParam1, 5, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler3.mIntParam1, 5, TEST_LOCATION );
+
+    // Remove middle connection and repeat
+    handler1.Reset();
+    handler2.Reset();
+    handler3.Reset();
+    signals.SignalVoid1Value().Disconnect( &handler2, &TestSlotHandler::VoidSlotIntValue );
+
+    signals.EmitVoidSignal1IntValue( 6 );
+    DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 6, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler2.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler3.mIntParam1, 6, TEST_LOCATION );
+  }
+
+  // Test that multiple callbacks are disconnected when a signal is destroyed
+
+  TestSlotHandler handler4;
+  TestSlotHandler handler5;
+  TestSlotHandler handler6;
+
+  {
+    TestSignals::VoidRet1ValueParamSignal tempSignal;
+
+    DALI_TEST_EQUALS( handler4.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler5.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler6.GetConnectionCount(), 0u, TEST_LOCATION );
+
+    tempSignal.Connect( &handler4, &TestSlotHandler::VoidSlotIntValue );
+    tempSignal.Connect( &handler5, &TestSlotHandler::VoidSlotIntValue );
+    tempSignal.Connect( &handler6, &TestSlotHandler::VoidSlotIntValue );
+
+    DALI_TEST_EQUALS( handler4.GetConnectionCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler5.GetConnectionCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler6.GetConnectionCount(), 1u, TEST_LOCATION );
+  }
+  // End of tempSignal lifetime
+
+  DALI_TEST_EQUALS( handler4.GetConnectionCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler5.GetConnectionCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler6.GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalMultipleConnections2(void)
+{
+  TestSignals signals;
+
+  // Test that connecting the same callback twice is a NOOP
+  {
+    TestSlotHandler handler1;
+
+    // Note the double connection is intentional
+    signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue );
+    signals.SignalVoid1Value().Connect( &handler1, &TestSlotHandler::VoidSlotIntValue );
+    DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION );
+
+    signals.EmitVoidSignal1IntValue( 6 );
+    DALI_TEST_EQUALS( handler1.mHandledCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 6, TEST_LOCATION );
+
+    // Calling Disconnect once should be enough
+    signals.SignalVoid1Value().Disconnect( &handler1, &TestSlotHandler::VoidSlotIntValue );
+    DALI_TEST_CHECK( signals.SignalVoid1Value().Empty() );
+    handler1.mIntParam1 = 0;
+
+    signals.EmitVoidSignal1IntValue( 7 );
+    DALI_TEST_EQUALS( handler1.mHandledCount, 1/*not incremented since last check*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 0, TEST_LOCATION );
+  }
+
+  // Test automatic disconnect after multiple Connect() calls
+  {
+    TestSlotHandler handler2;
+    signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue );
+    signals.SignalVoid1Value().Connect( &handler2, &TestSlotHandler::VoidSlotIntValue );
+
+    TestSlotHandler handler3;
+    signals.SignalBool1Value().Connect( &handler3, &TestSlotHandler::BoolSlotFloatValue );
+    signals.SignalBool1Value().Connect( &handler3, &TestSlotHandler::BoolSlotFloatValue );
+
+    DALI_TEST_EQUALS( handler2.mHandledCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler3.mHandledCount, 0, TEST_LOCATION );
+    DALI_TEST_CHECK( ! signals.SignalVoid1Value().Empty() );
+    DALI_TEST_CHECK( ! signals.SignalBool1Value().Empty() );
+  }
+  DALI_TEST_CHECK( signals.SignalVoid1Value().Empty() );
+  DALI_TEST_CHECK( signals.SignalBool1Value().Empty() );
+
+  // Should be NOOP
+  signals.EmitVoidSignal1IntValue( 1 );
+  signals.EmitBoolSignalFloatValue( 1.0f );
+
+  // Test that connecting the same callback 10 times is a NOOP
+  TestSlotHandler handler4;
+  DALI_TEST_EQUALS( handler4.mHandledCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler4.mFloatParam1, 0.0f, TEST_LOCATION );
+
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  signals.SignalBool1Value().Connect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+
+  signals.EmitBoolSignalFloatValue( 2.0f );
+  DALI_TEST_EQUALS( handler4.mHandledCount, 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler4.mFloatParam1, 2.0f, TEST_LOCATION );
+
+  // Calling Disconnect once should be enough
+  signals.SignalBool1Value().Disconnect( &handler4, &TestSlotHandler::BoolSlotFloatValue );
+  DALI_TEST_CHECK( signals.SignalBool1Value().Empty() );
+
+  signals.EmitBoolSignalFloatValue( 3.0f );
+  DALI_TEST_EQUALS( handler4.mHandledCount, 1/*not incremented since last check*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler4.mFloatParam1, 2.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalMultipleConnections3(void)
+{
+  TestSignals signals;
+
+  // Test connecting two difference callbacks for the same ConnectionTracker
+
+  TestSlotHandler handler1;
+
+  {
+    TestSignals::VoidRet1ValueParamSignal tempSignal;
+
+    DALI_TEST_EQUALS( handler1.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 0, TEST_LOCATION );
+
+    // Note that the duplicate connection is deliberate
+    tempSignal.Connect( &handler1, &TestSlotHandler::VoidSlotIntValue );
+    tempSignal.Connect( &handler1, &TestSlotHandler::VoidDuplicateSlotIntValue );
+
+    DALI_TEST_EQUALS( handler1.GetConnectionCount(), 2u, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mHandledCount, 0, TEST_LOCATION );
+
+    tempSignal.Emit( 10 );
+
+    DALI_TEST_EQUALS( handler1.mHandledCount, 2, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam1, 10, TEST_LOCATION );
+    DALI_TEST_EQUALS( handler1.mIntParam2, 10, TEST_LOCATION );
+  }
+  // End of tempSignal lifetime
+
+  DALI_TEST_EQUALS( handler1.GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliSignalDisconnectStatic(void)
+{
+  // void Func()
+
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+
+    signal.Connect( StaticVoidCallbackVoid );
+    DALI_TEST_CHECK( ! signal.Empty() );
+
+    wasStaticVoidCallbackVoidCalled = false;
+    signal.Emit();
+    DALI_TEST_EQUALS( wasStaticVoidCallbackVoidCalled, true, TEST_LOCATION );
+
+    signal.Disconnect( StaticVoidCallbackVoid );
+    DALI_TEST_CHECK( signal.Empty() );
+
+    wasStaticVoidCallbackVoidCalled = false;
+    signal.Emit();
+    DALI_TEST_EQUALS( wasStaticVoidCallbackVoidCalled, false, TEST_LOCATION );
+  }
+
+  // float Func()
+
+  {
+    TestSignals::FloatRet0ParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+
+    signal.Connect( StaticFloatCallbackVoid );
+    DALI_TEST_CHECK( ! signal.Empty() );
+
+    wasStaticFloatCallbackVoidCalled = false;
+    float result = signal.Emit();
+    DALI_TEST_EQUALS( wasStaticFloatCallbackVoidCalled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( result, 7.0f, TEST_LOCATION );
+
+    signal.Disconnect( StaticFloatCallbackVoid );
+    DALI_TEST_CHECK( signal.Empty() );
+
+    wasStaticFloatCallbackVoidCalled = false;
+    result = signal.Emit();
+    DALI_TEST_EQUALS( wasStaticFloatCallbackVoidCalled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( result, 0.0f, TEST_LOCATION );
+  }
+
+  // void Func( int )
+
+  {
+    TestSignals::VoidRet1ValueParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+
+    signal.Connect( StaticVoidCallbackIntValue );
+    DALI_TEST_CHECK( ! signal.Empty() );
+
+    wasStaticVoidCallbackIntValueCalled = false;
+    staticIntValue = 0;
+    signal.Emit( 10 );
+    DALI_TEST_EQUALS( wasStaticVoidCallbackIntValueCalled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticIntValue, 10, TEST_LOCATION );
+
+    signal.Disconnect( StaticVoidCallbackIntValue );
+    DALI_TEST_CHECK( signal.Empty() );
+
+    wasStaticVoidCallbackIntValueCalled = false;
+    staticIntValue = 0;
+    signal.Emit( 11 );
+    DALI_TEST_EQUALS( wasStaticVoidCallbackIntValueCalled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticIntValue, 0, TEST_LOCATION );
+  }
+
+  // float Func( float, float )
+
+  {
+    TestSignals::FloatRet2ValueParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+
+    signal.Connect( StaticFloatCallbackFloatValueFloatValue );
+    DALI_TEST_CHECK( ! signal.Empty() );
+
+    wasStaticFloatCallbackFloatValueFloatValueCalled = false;
+    staticFloatValue1 = 0.0f;
+    staticFloatValue2 = 0.0f;
+    float result = signal.Emit( 5.0f, 6.0f );
+    DALI_TEST_EQUALS( wasStaticFloatCallbackFloatValueFloatValueCalled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticFloatValue1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticFloatValue2, 6.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( result, 5.0f+6.0f, TEST_LOCATION );
+
+    signal.Disconnect( StaticFloatCallbackFloatValueFloatValue );
+    DALI_TEST_CHECK( signal.Empty() );
+
+    wasStaticFloatCallbackFloatValueFloatValueCalled = false;
+    staticFloatValue1 = 0.0f;
+    staticFloatValue2 = 0.0f;
+    result = signal.Emit( 7.0f, 8.0f );
+    DALI_TEST_EQUALS( wasStaticFloatCallbackFloatValueFloatValueCalled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticFloatValue1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( staticFloatValue2, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( result, 0.0f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnectDuringCallback(void)
+{
+  // Test disconnection during each callback
+
+  TestSignals::VoidRetNoParamSignal signal;
+  DALI_TEST_CHECK( signal.Empty() );
+
+  TestSlotDisconnector handler1;
+  handler1.VoidConnectVoid( signal );
+  DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  signal.Emit();
+  DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  // Repeat with 2 callbacks
+
+  handler1.mHandled = false;
+
+  TestSlotDisconnector handler2;
+  handler1.VoidConnectVoid( signal );
+  handler2.VoidConnectVoid( signal );
+  DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  signal.Emit();
+  DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  // Repeat with no callbacks
+
+  handler1.mHandled = false;
+  handler2.mHandled = false;
+
+  signal.Emit();
+  DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+
+  // Repeat with 3 callbacks
+
+  TestSlotDisconnector handler3;
+  handler1.VoidConnectVoid( signal );
+  handler2.VoidConnectVoid( signal );
+  handler3.VoidConnectVoid( signal );
+  DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  signal.Emit();
+  DALI_TEST_EQUALS( handler1.mHandled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler3.mHandled, true, TEST_LOCATION );
+  DALI_TEST_CHECK( signal.Empty() );
+
+  // Repeat with no callbacks
+
+  handler1.mHandled = false;
+  handler2.mHandled = false;
+  handler3.mHandled = false;
+
+  signal.Emit();
+  DALI_TEST_EQUALS( handler1.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler2.mHandled, false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler3.mHandled, false, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalDisconnectDuringCallback2(void)
+{
+  // Test disconnection of some (but not all) callbacks during sigmal emission
+
+  TestSignals::VoidRetNoParamSignal signal;
+  DALI_TEST_CHECK( signal.Empty() );
+
+  TestSlotMultiDisconnector handler;
+  handler.ConnectAll( signal );
+  DALI_TEST_EQUALS( handler.mSlotHandled[0], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[1], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[2], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[3], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[4], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[5], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[6], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[7], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[8], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[9], false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  signal.Emit();
+
+  // Slots 5, 7, & 9 should be disconnected before being called
+  DALI_TEST_EQUALS( handler.mSlotHandled[0], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[1], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[2], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[3], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[4], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[5], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[6], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[7], false, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[8], true, TEST_LOCATION );
+  DALI_TEST_EQUALS( handler.mSlotHandled[9], false, TEST_LOCATION );
+  DALI_TEST_CHECK( ! signal.Empty() );
+
+  // Odd slots are disconnected
+  DALI_TEST_EQUALS( handler.GetConnectionCount(), 5u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalEmitDuringCallback(void)
+{
+  TestApplication app; // Create core for debug logging
+
+  // for coverage purposes we test the emit guard for each signal type (0,1,2,3 params) void / return value
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    DALI_TEST_CHECK( signal.Empty() );
+
+    TestEmitDuringCallback handler1;
+    handler1.VoidConnectVoid( signal );
+
+    // Test that this does not result in an infinite loop!
+    signal.Emit();
+  }
+  {
+    TestSignals::FloatRet0ParamSignal signal;
+
+    DALI_TEST_CHECK( signal.Empty() );
+
+    TestEmitDuringCallback handler1;
+    handler1.FloatRet0ParamConnect( signal );
+
+    // Test that this does not result in an infinite loop!
+    signal.Emit();
+  }
+  {
+    TestSignals::FloatRet1ParamSignal signal;
+
+    DALI_TEST_CHECK( signal.Empty() );
+
+    TestEmitDuringCallback handler1;
+    handler1.FloatRet1ParamConnect( signal );
+
+    // Test that this does not result in an infinite loop!
+    signal.Emit( 1.f );
+  }
+  {
+    TestSignals::FloatRet2ValueParamSignal signal;
+
+    DALI_TEST_CHECK( signal.Empty() );
+
+    TestEmitDuringCallback handler1;
+    handler1.FloatRet2ParamConnect( signal );
+
+    // Test that this does not result in an infinite loop!
+    signal.Emit( 1.f, 1.f );
+  }
+  {
+    TestSignals::FloatRet3ValueParamSignal signal;
+
+    DALI_TEST_CHECK( signal.Empty() );
+
+    TestEmitDuringCallback handler1;
+    handler1.FloatRet3ParamConnect( signal );
+
+    // Test that this does not result in an infinite loop!
+    signal.Emit( 1.f,1.f,1.f );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalDeleteDuringEmit(void)
+{
+  // testing a signal deletion during an emit
+  // need to dynamically allocate the signal for this to work
+
+  TestApplication app; // Create core for debug logging
+
+  TestSignals::VoidRetNoParamSignal* signal = new TestSignals::VoidRetNoParamSignal;
+
+  TestEmitDuringCallback handler1;
+  handler1.DeleteDuringEmitConnect( *signal );
+
+  // should just log an error
+  signal->Emit();
+
+  tet_result( TET_PASS );
+
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp01(void)
+{
+  // Test 1 signal connected to 1 Slot.
+  // Signal dies first.
+
+  TestButton* button = new TestButton(1);
+  TestApp app;
+  button->DownSignal().Connect(&app,&TestApp::OnButtonPress);
+
+  // check we have both the button, and the app have 1 connection
+  DALI_TEST_EQUALS( app.GetConnectionCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( button->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION );
+
+  delete button;  // should automatically destroy the connection
+
+  // check we have a 0 connections
+  DALI_TEST_EQUALS( app.GetConnectionCount(), 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp02(void)
+{
+  // Test 1 signal connected to 1 Slot.
+  // Slot owning object dies first.
+
+  TestButton button(1);
+  TestApp *app = new TestApp;
+  button.DownSignal().Connect( app, &TestApp::OnButtonPress);
+
+  // check we have a 1 connection
+  DALI_TEST_EQUALS( app->GetConnectionCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 1u, TEST_LOCATION );
+
+  delete app;  // should automatically destroy the connection
+
+  // check we have a 0 connections
+  DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp03(void)
+{
+  // Test 1 Signal connect to 2 slots
+  // 1 of the slot owners dies. Then the second slot owner dies
+
+  TestButton button(1);
+  TestApp *app1 = new TestApp;
+  TestApp *app2 = new TestApp;
+
+  button.DownSignal().Connect( app1, &TestApp::OnButtonPress);
+  button.DownSignal().Connect( app2, &TestApp::OnButtonPress);
+
+    // check we have a 2 connections to the signal
+  DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 2u, TEST_LOCATION );
+
+  // kill the first slot
+  delete app1;  // should automatically destroy the connection
+
+  // check we have 1 connection left
+  DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 1u, TEST_LOCATION );
+
+  button.Press();   // emit the signal (to ensure it doesn't seg fault)
+
+  // kill the second slot
+  delete app2;  // should automatically destroy the connection
+
+  // check we have 1 connection left
+  DALI_TEST_EQUALS( button.DownSignal().GetConnectionCount(), 0u, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp04(void)
+{
+  // Test 1 Signal connected to 2 slots (with different owners)
+  // The Signal dies, check the 2 slots disconnect automatically
+
+  TestButton* button = new TestButton(1);
+  TestApp app1;
+  TestApp app2;
+
+  button->DownSignal().Connect(&app1,&TestApp::OnButtonPress);
+  button->DownSignal().Connect(&app2,&TestApp::OnButtonPress);
+
+  // check the connection counts
+  DALI_TEST_EQUALS( app1.GetConnectionCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( app2.GetConnectionCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( button->DownSignal().GetConnectionCount(), 2u, TEST_LOCATION );
+
+  delete button;  // should automatically destroy the connection
+
+  // check both slot owners have zero connections
+  DALI_TEST_EQUALS( app1.GetConnectionCount(), 0u, TEST_LOCATION );
+  DALI_TEST_EQUALS( app2.GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp05(void)
+{
+  // Test 2 Signals (with different owners)  connected to 1 slots
+  // 1 Signal dies, check that the remaining connection is valid
+
+  TestButton* button1 = new TestButton(1); // use for signal 1
+  TestButton* button2 = new TestButton(2); // use for signal 2
+
+  TestApp app;
+
+  button1->DownSignal().Connect(&app,&TestApp::OnButtonPress);
+  button2->DownSignal().Connect(&app,&TestApp::OnButtonPress);
+
+  // check the connection counts
+  DALI_TEST_EQUALS( app.GetConnectionCount(), 2u, TEST_LOCATION );
+  DALI_TEST_EQUALS( button1->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION );
+  DALI_TEST_EQUALS( button2->DownSignal().GetConnectionCount(), 1u, TEST_LOCATION );
+
+  // make sure both signals emit ok
+  button2->Press();
+  DALI_TEST_EQUALS( app.GetButtonPressedId() , 2 , TEST_LOCATION );
+
+  button1->Press();
+  DALI_TEST_EQUALS( app.GetButtonPressedId() , 1 , TEST_LOCATION );
+
+  delete button1;  // should automatically destroy 1 connection
+
+  // check both slot owners have zero connections
+  DALI_TEST_EQUALS( app.GetConnectionCount(), 1u, TEST_LOCATION );
+
+  // check remaining connection still works
+  button2->Press();
+  DALI_TEST_EQUALS( app.GetButtonPressedId() , 2 , TEST_LOCATION );
+
+  // kill the last signal
+  delete button2;
+  DALI_TEST_EQUALS( app.GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalTestApp06(void)
+{
+  Signal< bool () > boolSignal;
+  TestApp app;
+  bool result(false);
+
+  // connect a slot which will return false
+  boolSignal.Connect( &app, &TestApp::BoolReturnTestFalse);
+  result = boolSignal.Emit();
+  DALI_TEST_EQUALS( result, false, TEST_LOCATION );
+
+  // disconnect last slot, and connect a slot which returns true
+  boolSignal.Disconnect( &app, &TestApp::BoolReturnTestFalse);
+  boolSignal.Connect( &app, &TestApp::BoolReturnTestTrue);
+  result = boolSignal.Emit();
+  DALI_TEST_EQUALS( result, true, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSlotDelegateConnection(void)
+{
+  TestSignals signals;
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoidNone().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+
+    // Test double emission
+    handlers.mHandled = false;
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid1Ref().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    int x = 7;
+    signals.EmitVoidSignalIntRef(x);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 7, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid1Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignal1IntValue(5);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 5, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignal2IntValue(6, 7);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 6, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 7, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalBool1Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+
+    handlers.mBoolReturn = true;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+
+    // repeat with opposite return value
+    handlers.mBoolReturn = false;
+    handlers.mHandled = false;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(6.0f), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 6.0f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalBool2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 10, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalInt2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mIntReturn = 27;
+    int x = signals.EmitIntSignalFloatValueIntValue(33.5f, 5);
+    DALI_TEST_EQUALS( x, 27, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 33.5f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 5, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalFloat0().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float f = signals.EmitFloat0Signal();
+    DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalFloat2Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float f = signals.EmitFloat2VSignal(5, 33.0f);
+    DALI_TEST_EQUALS( f, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.VoidSignalFloatValue3().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotFloatValue3 );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.EmitVoidSignalFloatValue3(5, 33.0f, 100.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalFloat3Value().Connect( handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValue3 );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    float returnValue = signals.EmitFloat3VSignal(5, 33.0f, 100.0f);
+    DALI_TEST_EQUALS( returnValue, 27.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, true, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 5.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 33.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam3, 100.0f, 0.001f, TEST_LOCATION );
+  }
+  signals.CheckNoConnections();
+  END_TEST;
+}
+
+int UtcDaliSignalSlotDelegateDestruction(void)
+{
+  // Test that signal disconnect works when slot-delegate is destroyed (goes out of scope)
+
+  {
+    TestSignals::VoidRetNoParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit();
+  }
+
+  {
+    TestSignals::VoidRet1ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit( 10 );
+  }
+
+  {
+    TestSignals::VoidRet1RefParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    int temp( 5 );
+    signal.Emit( temp );
+  }
+
+  {
+    TestSignals::VoidRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    signal.Emit( 1, 2 );
+  }
+
+  {
+    TestSignals::BoolRet1ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    bool blah = signal.Emit( 1.0f );
+    DALI_TEST_CHECK( ! blah );
+  }
+
+  {
+    TestSignals::BoolRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    bool blah = signal.Emit( 1.0f, 2 );
+    DALI_TEST_CHECK( ! blah );
+  }
+
+  {
+    TestSignals::IntRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    int blah = signal.Emit( 10.0f, 100 );
+    DALI_TEST_CHECK( 0 == blah );
+  }
+
+  {
+    TestSignals::FloatRet0ParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect( handler.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid );
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    float blah = signal.Emit();
+    DALI_TEST_CHECK( 0.0f == blah );
+  }
+
+  {
+    TestSignals::FloatRet2ValueParamSignal signal;
+    {
+      DALI_TEST_CHECK( signal.Empty() );
+      TestSlotDelegateHandler handler;
+      signal.Connect(handler.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue);
+      DALI_TEST_CHECK( ! signal.Empty() );
+    }
+    // End of slot lifetime
+    DALI_TEST_CHECK( signal.Empty() );
+
+    // Signal emission should be a NOOP
+    float blah = signal.Emit( 3.0f, 4.0f );
+    DALI_TEST_CHECK( 0.0f == blah );
+  }
+  END_TEST;
+}
+
+int UtcDaliSlotHandlerDisconnect(void)
+{
+  // Test that callbacks don't occur if a signal is disconnected before emission
+
+  TestSignals signals;
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoidNone().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoidNone().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotVoid);
+    signals.EmitVoidSignalVoid();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid1Ref().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    int r = 7;
+    handlers.mIntReturn = 5;
+    signals.SignalVoid1Ref().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntRef);
+    signals.EmitVoidSignalIntRef(r);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( r, 7, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid1Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoid1Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValue);
+    signals.EmitVoidSignal1IntValue(5);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalVoid2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    signals.SignalVoid2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::VoidSlotIntValueIntValue);
+    signals.EmitVoidSignal2IntValue(5, 10);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2, 0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalBool1Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    signals.SignalBool1Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValue(5.0f), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalBool2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mBoolReturn = true;
+    signals.SignalBool2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::BoolSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( signals.EmitBoolSignalFloatValueIntValue(5.0f, 10), false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam2,   0, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalInt2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mIntReturn = 27;
+    signals.SignalInt2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::IntSlotFloatValueIntValue);
+    signals.EmitIntSignalFloatValueIntValue(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mIntParam1, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalFloat0().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat0().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotVoid);
+    signals.EmitFloat0Signal();
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+
+  {
+    TestSlotDelegateHandler handlers;
+    signals.SignalFloat2Value().Connect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    handlers.mFloatReturn = 27.0f;
+    signals.SignalFloat2Value().Disconnect(handlers.mSlotDelegate, &TestSlotDelegateHandler::FloatSlotFloatValueFloatValue);
+    signals.EmitFloat2VSignal(5, 33.0f);
+    DALI_TEST_EQUALS( handlers.mHandled, false, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam1, 0.0f, 0.001f, TEST_LOCATION );
+    DALI_TEST_EQUALS( handlers.mFloatParam2, 0.0f, 0.001f, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+
+int UtcDaliCallbackBase(void)
+{
+  // simple constructor for coverage
+  CallbackBase base;
+  tet_result( TET_PASS );
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp b/automated-tests/src/dali/utc-Dali-SignalTemplatesFunctors.cpp
new file mode 100644 (file)
index 0000000..d66aa29
--- /dev/null
@@ -0,0 +1,513 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iostream>
+#include <stdlib.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_signal_templates_functors_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_signal_templates_functors_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+class TestSignals
+{
+public:
+
+  typedef Signal<void ()> VoidSignalVoid;
+  typedef Signal<void (float)> VoidSignalFloat;
+
+  typedef Signal<float ()> FloatSignalVoid;
+  typedef Signal<float (float)> FloatSignalFloat;
+
+  TestSignals()
+  {
+  }
+
+  void CheckNoConnections()
+  {
+    DALI_TEST_EQUALS( mVoidSignalVoid.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mVoidSignalFloat.GetConnectionCount(), 0u, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( mFloatSignalVoid.GetConnectionCount(), 0u, TEST_LOCATION );
+    DALI_TEST_EQUALS( mFloatSignalFloat.GetConnectionCount(), 0u, TEST_LOCATION );
+  }
+
+  VoidSignalVoid mVoidSignalVoid;
+  VoidSignalFloat mVoidSignalFloat;
+
+  FloatSignalVoid mFloatSignalVoid;
+  FloatSignalFloat mFloatSignalFloat;
+};
+
+class TestConnectionTracker : public ConnectionTracker
+{
+public:
+
+  TestConnectionTracker()
+  {
+  }
+};
+
+struct VoidFunctorVoid
+{
+  VoidFunctorVoid()
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  VoidFunctorVoid( const VoidFunctorVoid& copyMe )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  ~VoidFunctorVoid()
+  {
+    --mCurrentInstanceCount;
+  }
+
+  void operator()()
+  {
+    ++mCallbackCount;
+  }
+
+  static int mTotalInstanceCount;
+  static int mCurrentInstanceCount;
+  static int mCallbackCount;
+};
+
+struct VoidFunctorFloat
+{
+  VoidFunctorFloat( float* lastReceivedValue )
+  : mLastReceivedValue( lastReceivedValue )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  VoidFunctorFloat( const VoidFunctorFloat& copyMe )
+  : mLastReceivedValue( copyMe.mLastReceivedValue )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  ~VoidFunctorFloat()
+  {
+    --mCurrentInstanceCount;
+  }
+
+  void operator()(float value)
+  {
+    ++mCallbackCount;
+
+    if( mLastReceivedValue )
+    {
+      *mLastReceivedValue = value;
+    }
+  }
+
+  float* mLastReceivedValue;
+
+  static int mTotalInstanceCount;
+  static int mCurrentInstanceCount;
+  static int mCallbackCount;
+};
+
+struct FloatFunctorVoid
+{
+  static float DEFAULT_RETURN_VALUE;
+
+  FloatFunctorVoid()
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  FloatFunctorVoid( const FloatFunctorVoid& copyMe )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  ~FloatFunctorVoid()
+  {
+    --mCurrentInstanceCount;
+  }
+
+  float operator()()
+  {
+    ++mCallbackCount;
+
+    return DEFAULT_RETURN_VALUE;
+  }
+
+  static int mTotalInstanceCount;
+  static int mCurrentInstanceCount;
+  static int mCallbackCount;
+};
+
+float FloatFunctorVoid::DEFAULT_RETURN_VALUE = 5.0f;
+
+struct FloatFunctorFloat
+{
+  FloatFunctorFloat()
+  : mLastReceivedValue()
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  FloatFunctorFloat( const FloatFunctorFloat& copyMe )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  ~FloatFunctorFloat()
+  {
+    --mCurrentInstanceCount;
+  }
+
+  float operator()(float value)
+  {
+    ++mCallbackCount;
+
+    return value + 1.0f;
+  }
+
+  float* mLastReceivedValue;
+
+  static int mTotalInstanceCount;
+  static int mCurrentInstanceCount;
+  static int mCallbackCount;
+};
+
+static void ResetFunctorCounts()
+{
+  VoidFunctorVoid::mTotalInstanceCount   = 0;
+  VoidFunctorVoid::mCurrentInstanceCount = 0;
+  VoidFunctorVoid::mCallbackCount        = 0;
+
+  VoidFunctorFloat::mTotalInstanceCount   = 0;
+  VoidFunctorFloat::mCurrentInstanceCount = 0;
+  VoidFunctorFloat::mCallbackCount        = 0;
+
+  FloatFunctorVoid::mTotalInstanceCount   = 0;
+  FloatFunctorVoid::mCurrentInstanceCount = 0;
+  FloatFunctorVoid::mCallbackCount        = 0;
+
+  FloatFunctorFloat::mTotalInstanceCount   = 0;
+  FloatFunctorFloat::mCurrentInstanceCount = 0;
+  FloatFunctorFloat::mCallbackCount        = 0;
+}
+
+int VoidFunctorVoid::mTotalInstanceCount   = 0;
+int VoidFunctorVoid::mCurrentInstanceCount = 0;
+int VoidFunctorVoid::mCallbackCount        = 0;
+
+int VoidFunctorFloat::mTotalInstanceCount   = 0;
+int VoidFunctorFloat::mCurrentInstanceCount = 0;
+int VoidFunctorFloat::mCallbackCount        = 0;
+
+int FloatFunctorVoid::mTotalInstanceCount   = 0;
+int FloatFunctorVoid::mCurrentInstanceCount = 0;
+int FloatFunctorVoid::mCallbackCount        = 0;
+
+int FloatFunctorFloat::mTotalInstanceCount   = 0;
+int FloatFunctorFloat::mCurrentInstanceCount = 0;
+int FloatFunctorFloat::mCallbackCount        = 0;
+
+} // anon namespace
+
+
+int UtcDaliSignalFunctorsEmptyCheck(void)
+{
+  // Test that Empty() check works before & after signal connection
+
+  ResetFunctorCounts();
+
+  {
+    TestSignals::VoidSignalVoid signal;
+    DALI_TEST_CHECK( signal.Empty() );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+    TestConnectionTracker tracker;
+    signal.Connect( &tracker, VoidFunctorVoid() );
+    DALI_TEST_CHECK( ! signal.Empty() );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+  {
+    TestSignals::VoidSignalFloat signal;
+    DALI_TEST_CHECK( signal.Empty() );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+    TestConnectionTracker tracker;
+    signal.Connect( &tracker, VoidFunctorFloat(NULL) );
+    DALI_TEST_CHECK( ! signal.Empty() );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalFunctorsEmit(void)
+{
+  // Test basic signal emission for each functor type
+
+  ResetFunctorCounts();
+
+  TestSignals signals;
+
+  {
+    TestConnectionTracker tracker;
+
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION );
+
+    // Test double emission
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+  signals.CheckNoConnections();
+
+  {
+    TestConnectionTracker tracker;
+    float lastReceivedValue( 0.0f );
+
+    DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalFloat.Connect( &tracker, VoidFunctorFloat(&lastReceivedValue) );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalFloat.Emit( 3.5f );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( lastReceivedValue, 3.5f, TEST_LOCATION );
+
+    // Test double emission
+    signals.mVoidSignalFloat.Emit( 7.0f );
+    DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 2, TEST_LOCATION );
+    DALI_TEST_EQUALS( lastReceivedValue, 7.0f, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( VoidFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorFloat::mCallbackCount, 2, TEST_LOCATION );
+  signals.CheckNoConnections();
+  END_TEST;
+}
+
+int UtcDaliSignalFunctorsEmitReturn(void)
+{
+  // Test signals with return values
+
+  ResetFunctorCounts();
+
+  TestSignals signals;
+
+  {
+    TestConnectionTracker tracker;
+
+    DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mFloatSignalVoid.Connect( &tracker, FloatFunctorVoid() );
+    DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 0, TEST_LOCATION );
+
+    float returnValue = signals.mFloatSignalVoid.Emit();
+    DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( returnValue, FloatFunctorVoid::DEFAULT_RETURN_VALUE, TEST_LOCATION );
+
+    // Test double emission
+    returnValue = 0.0f;
+    returnValue = signals.mFloatSignalVoid.Emit();
+    DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+    DALI_TEST_EQUALS( returnValue, FloatFunctorVoid::DEFAULT_RETURN_VALUE, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( FloatFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( FloatFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( FloatFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+  signals.CheckNoConnections();
+
+  {
+    TestConnectionTracker tracker;
+
+    DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mFloatSignalFloat.Connect( &tracker, FloatFunctorFloat() );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 0, TEST_LOCATION );
+
+    float returnValue = signals.mFloatSignalFloat.Emit( 0.1f );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( returnValue, 1.0f + 0.1f, TEST_LOCATION );
+
+    // Test double emission
+    returnValue = signals.mFloatSignalFloat.Emit( 0.2f );
+    DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 2, TEST_LOCATION );
+    DALI_TEST_EQUALS( returnValue, 1.0f + 0.2f, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( FloatFunctorFloat::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( FloatFunctorFloat::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( FloatFunctorFloat::mCallbackCount, 2, TEST_LOCATION );
+  signals.CheckNoConnections();
+  END_TEST;
+}
+
+int UtcDaliSignalFunctorsDisconnectBeforeEmit(void)
+{
+  // Test explicit disconnect using ConnectionTracker
+
+  ResetFunctorCounts();
+
+  TestSignals signals;
+
+  {
+    TestConnectionTracker tracker;
+
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+
+    tracker.DisconnectAll();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION );
+
+    // Test double emission
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliSignalFunctorsDestroySignal(void)
+{
+  // Test destruction of signal before slot
+
+  ResetFunctorCounts();
+
+  TestConnectionTracker tracker;
+
+  {
+    TestSignals signals;
+
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Connect( &tracker, VoidFunctorVoid() );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount,1, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( tracker.GetConnectionCount(), 1u, TEST_LOCATION );
+  }
+
+  // Functor should have been deleted with signal
+  DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( tracker.GetConnectionCount(), 0u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliSignalConnectVoidFunctor(void)
+{
+  // Test connecting a functor using the VoidFunctor wrapper
+
+  ResetFunctorCounts();
+
+  TestSignals signals;
+
+  {
+    TestConnectionTracker tracker;
+
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 0, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Connect( &tracker, FunctorDelegate::New( VoidFunctorVoid() ) );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 0, TEST_LOCATION );
+
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 1, TEST_LOCATION );
+
+    // Test double emission
+    signals.mVoidSignalVoid.Emit();
+    DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+  }
+  // TestConnectionTracker should auto-disconnect
+  DALI_TEST_EQUALS( VoidFunctorVoid::mTotalInstanceCount, 2/*temporary copy + signal copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCurrentInstanceCount, 0, TEST_LOCATION );
+  DALI_TEST_EQUALS( VoidFunctorVoid::mCallbackCount, 2, TEST_LOCATION );
+  signals.CheckNoConnections();
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Stage.cpp b/automated-tests/src/dali/utc-Dali-Stage.cpp
new file mode 100644 (file)
index 0000000..3c5ef7b
--- /dev/null
@@ -0,0 +1,1323 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/context-notifier.h>
+#include <dali/integration-api/events/key-event-integ.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void stage_test_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void stage_test_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+namespace
+{
+
+// Functor for EventProcessingFinished signal
+struct EventProcessingFinishedFunctor
+{
+  /**
+   * @param[in] eventProcessingFinished reference to a boolean variable used to check if signal has been called.
+   */
+  EventProcessingFinishedFunctor( bool& eventProcessingFinished )
+  : mEventProcessingFinished( eventProcessingFinished )
+  {}
+
+  void operator()()
+  {
+    mEventProcessingFinished = true;
+  }
+
+  bool& mEventProcessingFinished;
+};
+
+// Stores data that is populated in the key-event callback and will be read by the TET cases
+struct KeyEventSignalData
+{
+  KeyEventSignalData()
+  : functorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    receivedKeyEvent.keyModifier = 0;
+    receivedKeyEvent.keyPressedName.clear();
+    receivedKeyEvent.keyPressed.clear();
+  }
+
+  bool functorCalled;
+  KeyEvent receivedKeyEvent;
+};
+
+// Functor that sets the data when called
+struct KeyEventReceivedFunctor
+{
+  KeyEventReceivedFunctor( KeyEventSignalData& data ) : signalData( data ) { }
+
+  bool operator()( const KeyEvent& keyEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.receivedKeyEvent = keyEvent;
+
+    return true;
+  }
+
+  KeyEventSignalData& signalData;
+};
+
+// Stores data that is populated in the touched signal callback and will be read by the TET cases
+struct TouchedSignalData
+{
+  TouchedSignalData()
+  : functorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    receivedTouchEvent.points.clear();
+    receivedTouchEvent.time = 0;
+  }
+
+  bool functorCalled;
+  TouchEvent receivedTouchEvent;
+};
+
+// Functor that sets the data when touched signal is received
+struct TouchedFunctor
+{
+  TouchedFunctor( TouchedSignalData& data ) : signalData( data ) { }
+
+  void operator()( const TouchEvent& touch )
+  {
+    signalData.functorCalled = true;
+    signalData.receivedTouchEvent = touch;
+  }
+
+  TouchedSignalData& signalData;
+};
+
+// Stores data that is populated in the wheel-event callback and will be read by the TET cases
+struct WheelEventSignalData
+{
+  WheelEventSignalData()
+  : functorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+  }
+
+  bool functorCalled;
+  WheelEvent receivedWheelEvent;
+};
+
+// Functor that sets the data when wheel-event signal is received
+struct WheelEventReceivedFunctor
+{
+  WheelEventReceivedFunctor( WheelEventSignalData& data ) : signalData( data ) { }
+
+  bool operator()( const WheelEvent& wheelEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.receivedWheelEvent = wheelEvent;
+
+    return true;
+  }
+
+  WheelEventSignalData& signalData;
+};
+
+bool DummyTouchCallback( Actor actor, const TouchEvent& touch )
+{
+  return true;
+}
+
+struct ContextStatusFunctor
+{
+  ContextStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag )
+  {
+    mCalledFlag = false;
+  }
+
+  void operator()()
+  {
+    mCalledFlag = true;
+  }
+  void Reset()
+  {
+    mCalledFlag = false;
+  }
+
+  bool& mCalledFlag;
+};
+
+struct SceneCreatedStatusFunctor
+{
+  SceneCreatedStatusFunctor(bool& calledFlag) : mCalledFlag( calledFlag )
+  {
+    mCalledFlag = false;
+  }
+
+  void operator()()
+  {
+    mCalledFlag = true;
+  }
+  void Reset()
+  {
+    mCalledFlag = false;
+  }
+
+  bool& mCalledFlag;
+};
+
+struct ActorCreatedFunctor
+{
+  ActorCreatedFunctor( bool& signalReceived )
+  : mSignalVerified( signalReceived )
+  {
+  }
+
+  void operator()( BaseHandle object )
+  {
+    tet_infoline( "Verifying TestActorCallback()" );
+    Actor actor = Actor::DownCast( object );
+    if( actor )
+    {
+      mSignalVerified = true;
+    }
+  }
+
+  bool& mSignalVerified;
+};
+
+} // unnamed namespace
+
+
+int UtcDaliStageDefaultConstructorP(void)
+{
+  TestApplication application;
+  Stage stage;
+
+  DALI_TEST_CHECK( !stage );
+  END_TEST;
+}
+
+// Note: No negative test for default constructor.
+
+int UtcDaliStageDestructorP(void)
+{
+  TestApplication application;
+  Stage* stage = new Stage();
+  delete stage;
+  stage = NULL;
+
+  DALI_TEST_CHECK( true );
+  END_TEST;
+}
+
+// Note: No negative test for default destructor.
+
+int UtcDaliStageGetCurrentP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  DALI_TEST_CHECK( stage );
+  END_TEST;
+}
+
+int UtcDaliStageGetCurrentN(void)
+{
+  bool asserted = false;
+  try
+  {
+    Stage stage = Stage::GetCurrent();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage doesn't exist\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliStageIsInstalledP(void)
+{
+  TestApplication application;
+
+  Stage::GetCurrent();
+
+  DALI_TEST_CHECK( Stage::IsInstalled() );
+  END_TEST;
+}
+
+int UtcDaliStageIsInstalledN(void)
+{
+  DALI_TEST_CHECK( !Stage::IsInstalled() );
+
+  END_TEST;
+}
+
+int UtcDaliStageCopyConstructorP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Stage copyStage( stage );
+
+  DALI_TEST_CHECK( copyStage );
+  DALI_TEST_CHECK( copyStage.GetRootLayer() == stage.GetRootLayer() );
+
+  END_TEST;
+}
+
+// Note: no negative test for UtcDaliStageCopyConstructor.
+
+int UtcDaliStageAssignmentOperatorP(void)
+{
+  TestApplication application;
+  const Stage stage = Stage::GetCurrent();
+
+  Stage copyStage = stage;
+
+  DALI_TEST_CHECK( copyStage );
+  DALI_TEST_CHECK( copyStage.GetRootLayer() == stage.GetRootLayer() );
+
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliStageAssignmentOperator.
+
+int UtcDaliStageAddP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( !actor.OnStage() );
+
+  stage.Add( actor );
+  DALI_TEST_CHECK( actor.OnStage() );
+  END_TEST;
+}
+
+int UtcDaliStageAddN(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+  Actor actor;
+
+  bool asserted = false;
+  try
+  {
+    stage.Add( actor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "actor && \"Actor handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliStageRemoveP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( !actor.OnStage() );
+
+  stage.Add( actor );
+  DALI_TEST_CHECK( actor.OnStage() );
+
+  stage.Remove(actor);
+  DALI_TEST_CHECK( !actor.OnStage() );
+  END_TEST;
+}
+
+int UtcDaliStageRemoveN1(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+  Actor actor;
+
+  bool asserted = false;
+  try
+  {
+    // Actor is not valid, confirm a removal attempt does assert.
+    stage.Remove( actor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "actor && \"Actor handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliStageRemoveN2(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( !actor.OnStage() );
+
+  bool asserted = false;
+  try
+  {
+    // Actor is not on stage, confirm a removal attempt does not assert / segfault.
+    stage.Remove( actor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( !asserted );
+  END_TEST;
+}
+
+int UtcDaliStageRemoveN3(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  // Initially we have a default layer
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION );
+
+  // Check we cannot remove the root layer from the stage.
+  Layer layer = stage.GetRootLayer();
+  bool asserted = true;
+  try
+  {
+    stage.Remove( layer );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "this != &child && \"Cannot remove actor from itself\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetSizeP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Vector2 size = stage.GetSize();
+
+  DALI_TEST_EQUALS( size.width,  static_cast<float>( TestApplication::DEFAULT_SURFACE_WIDTH ),  TEST_LOCATION );
+  DALI_TEST_EQUALS( size.height, static_cast<float>( TestApplication::DEFAULT_SURFACE_HEIGHT ), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetSizeN(void)
+{
+  TestApplication application;
+
+  Stage stage;
+
+  bool asserted = false;
+  Vector2 size;
+  try
+  {
+    size = stage.GetSize();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliStageGetDpiP1(void)
+{
+  TestApplication application; // Initializes core DPI to default values
+
+  Stage stage = Stage::GetCurrent();
+
+  // Test the default DPI.
+  Vector2 dpi = stage.GetDpi();
+  DALI_TEST_EQUALS( dpi.x, static_cast<float>( TestApplication::DEFAULT_HORIZONTAL_DPI ), TEST_LOCATION );
+  DALI_TEST_EQUALS( dpi.y, static_cast<float>( TestApplication::DEFAULT_VERTICAL_DPI ),   TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetDpiP2(void)
+{
+  TestApplication application; // Initializes core DPI to default values
+
+  // Test that setting core DPI explicitly also sets up the Stage's DPI.
+  application.GetCore().SetDpi( 200, 180 );
+
+  Stage stage = Stage::GetCurrent();
+  Vector2 dpi = stage.GetDpi();
+  DALI_TEST_EQUALS( dpi.x, 200.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( dpi.y, 180.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetDpiP3(void)
+{
+  TestApplication application( 480, 800, 72.0f, 120.0f ); // Initializes core DPI with specific values
+
+  Stage stage = Stage::GetCurrent();
+
+  // Test that setting core DPI explicitly also sets up the Stage's DPI.
+  Vector2 dpi = stage.GetDpi();
+  DALI_TEST_EQUALS( dpi.x, 72.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( dpi.y, 120.0f, TEST_LOCATION) ;
+  END_TEST;
+}
+
+/*
+ * This is not a true negative test, we are checking the DPI if it has not been set.
+ * A test for setting negative DPI values would be part of the application core utc tests.
+ */
+int UtcDaliStageGetDpiN(void)
+{
+  TestApplication application; // Initializes core DPI to default values
+
+  Stage stage = Stage::GetCurrent();
+  Vector2 dpi = stage.GetDpi();
+
+  DALI_TEST_EQUALS( dpi.x, 220.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( dpi.y, 217.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetLayerCountP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  // Initially we have a default layer
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION );
+
+  Layer layer = Layer::New();
+  stage.Add( layer );
+
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 2u, TEST_LOCATION );
+  END_TEST;
+}
+
+/*
+ * Not a true negative test, but confirms layer count is not affected by an invalid removal.
+ */
+int UtcDaliStageGetLayerCountN(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  // Initially we have a default layer
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION );
+
+  Layer layer = Layer::New();
+  stage.Remove( layer );
+
+  // Still have 1 layer.
+  DALI_TEST_EQUALS( stage.GetLayerCount(), 1u, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliStageGetLayerP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Layer rootLayer = stage.GetLayer( 0 );
+  DALI_TEST_CHECK( rootLayer );
+
+  Layer layer = Layer::New();
+  stage.Add( layer );
+
+  Layer sameLayer = stage.GetLayer( 1 );
+  DALI_TEST_CHECK( layer == sameLayer );
+  END_TEST;
+}
+
+int UtcDaliStageGetLayerN(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  bool asserted = false;
+  try
+  {
+    // Try to get a layer that doesn't exist (note: 0 is the root layer).
+    Layer layer = stage.GetLayer( 1 );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "depth < mLayers.size()", TEST_LOCATION );
+    asserted = true;
+  }
+
+  DALI_TEST_CHECK( asserted );
+  END_TEST;
+}
+
+int UtcDaliStageGetRootLayerP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Layer layer = stage.GetLayer( 0 );
+  DALI_TEST_CHECK( layer );
+
+  // Check that GetRootLayer() correctly retreived layer 0.
+  DALI_TEST_CHECK( stage.GetRootLayer() == layer );
+
+  END_TEST;
+}
+
+int UtcDaliStageGetRootLayerN(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Layer rootLayer = stage.GetLayer( 0 );
+  DALI_TEST_CHECK( rootLayer );
+  DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer );
+
+  // Create a new layer and attempt to lower it below the root layer.
+  Layer layer = Layer::New();
+  stage.Add( layer );
+  layer.LowerToBottom();
+
+  // Check that GetRootLayer still retrieves the same original layer.
+  DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer );
+
+  // Check modifying the root layer is also blocked.
+  rootLayer.RaiseToTop();
+  DALI_TEST_CHECK( stage.GetRootLayer() == rootLayer );
+
+  END_TEST;
+}
+
+int UtcDaliStageSetBackgroundColorP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  Vector4 testColor( 0.1f, 0.2f, 0.3f, 1.0f );
+  stage.SetBackgroundColor( testColor );
+
+  DALI_TEST_EQUALS( testColor, stage.GetBackgroundColor(), TEST_LOCATION );
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliStageSetBackgroundColor as we do not wish to implement
+// range checking for colors due to speed. Colors are clamped with glclampf within GL anyway.
+
+int UtcDaliStageGetBackgroundColorP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  DALI_TEST_EQUALS( Stage::DEFAULT_BACKGROUND_COLOR, stage.GetBackgroundColor(), TEST_LOCATION );
+  END_TEST;
+}
+
+// Note: No negative test for UtcDaliStageGetBackgroundColor as this is covered by UtcDaliStageSetBackgroundColorN.
+
+int UtcDaliStageKeepRenderingP(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  // Run core until it wants to sleep
+  bool keepUpdating( true );
+  while ( keepUpdating )
+  {
+    application.SendNotification();
+    keepUpdating = application.Render( 1000.0f /*1 second*/ );
+  }
+
+  // Force rendering for the next 5 seconds
+  stage.KeepRendering( 5.0f );
+
+  application.SendNotification();
+
+  // Test that core wants to sleep after 10 seconds
+  keepUpdating = application.Render( 1000.0f /*1 second*/ );
+  DALI_TEST_CHECK( keepUpdating );
+  keepUpdating = application.Render( 1000.0f /*2 seconds*/ );
+  DALI_TEST_CHECK( keepUpdating );
+  keepUpdating = application.Render( 1000.0f /*3 seconds*/ );
+  DALI_TEST_CHECK( keepUpdating );
+  keepUpdating = application.Render( 1000.0f /*4 seconds*/ );
+  DALI_TEST_CHECK( keepUpdating );
+  keepUpdating = application.Render( 1000.0f /*5 seconds*/ );
+  DALI_TEST_CHECK( !keepUpdating );
+  END_TEST;
+}
+
+int UtcDaliStageKeepRenderingN(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+
+  // Run core until it wants to sleep
+  bool keepUpdating( true );
+  while ( keepUpdating )
+  {
+    application.SendNotification();
+    keepUpdating = application.Render( 1000.0f /*1 second*/ );
+  }
+
+  // Force rendering for the next 5 seconds
+  stage.KeepRendering( -1.0f );
+
+  application.SendNotification();
+
+  // Test that core wants to sleep after 10 seconds
+  keepUpdating = application.Render( 1000.0f /*1 second*/ );
+  DALI_TEST_CHECK( !keepUpdating );
+
+  END_TEST;
+}
+
+int UtcDaliStageEventProcessingFinishedP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  bool eventProcessingFinished = false;
+  EventProcessingFinishedFunctor functor( eventProcessingFinished );
+  stage.EventProcessingFinishedSignal().Connect( &application, functor );
+
+  Actor actor( Actor::New() );
+  stage.Add( actor );
+
+  application.SendNotification();
+  application.Render();
+
+  DALI_TEST_CHECK( eventProcessingFinished );
+
+  END_TEST;
+}
+
+int UtcDaliStageEventProcessingFinishedN(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  bool eventProcessingFinished = false;
+  EventProcessingFinishedFunctor functor( eventProcessingFinished );
+  stage.EventProcessingFinishedSignal().Connect( &application, functor );
+
+  Actor actor( Actor::New() );
+  stage.Add( actor );
+
+  // Do not complete event processing and confirm the signal has not been emitted.
+  DALI_TEST_CHECK( !eventProcessingFinished );
+
+  END_TEST;
+}
+
+int UtcDaliStageSignalKeyEventP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  KeyEventSignalData data;
+  KeyEventReceivedFunctor functor( data );
+  stage.KeyEventSignal().Connect( &application, functor );
+
+  Integration::KeyEvent event( "i", "i", 0, 0, 0, Integration::KeyEvent::Down );
+  application.ProcessEvent( event );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( event.keyModifier == data.receivedKeyEvent.keyModifier );
+  DALI_TEST_CHECK( event.keyName == data.receivedKeyEvent.keyPressedName );
+  DALI_TEST_CHECK( event.keyString == data.receivedKeyEvent.keyPressed );
+  DALI_TEST_CHECK( event.state == static_cast<Integration::KeyEvent::State>( data.receivedKeyEvent.state ) );
+
+  data.Reset();
+
+  Integration::KeyEvent event2( "i", "i", 0, 0, 0, Integration::KeyEvent::Up );
+  application.ProcessEvent( event2 );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( event2.keyModifier == data.receivedKeyEvent.keyModifier );
+  DALI_TEST_CHECK( event2.keyName == data.receivedKeyEvent.keyPressedName );
+  DALI_TEST_CHECK( event2.keyString == data.receivedKeyEvent.keyPressed );
+  DALI_TEST_CHECK( event2.state == static_cast<Integration::KeyEvent::State>( data.receivedKeyEvent.state ) );
+
+  data.Reset();
+
+  Integration::KeyEvent event3( "a", "a", 0, 0, 0, Integration::KeyEvent::Down );
+  application.ProcessEvent( event3 );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( event3.keyModifier == data.receivedKeyEvent.keyModifier );
+  DALI_TEST_CHECK( event3.keyName == data.receivedKeyEvent.keyPressedName );
+  DALI_TEST_CHECK( event3.keyString == data.receivedKeyEvent.keyPressed );
+  DALI_TEST_CHECK( event3.state == static_cast<Integration::KeyEvent::State>( data.receivedKeyEvent.state ) );
+
+  data.Reset();
+
+  Integration::KeyEvent event4( "a", "a", 0, 0, 0, Integration::KeyEvent::Up );
+  application.ProcessEvent( event4 );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( event4.keyModifier == data.receivedKeyEvent.keyModifier );
+  DALI_TEST_CHECK( event4.keyName == data.receivedKeyEvent.keyPressedName );
+  DALI_TEST_CHECK( event4.keyString == data.receivedKeyEvent.keyPressed );
+  DALI_TEST_CHECK( event4.state == static_cast<Integration::KeyEvent::State>( data.receivedKeyEvent.state ) );
+  END_TEST;
+}
+
+int UtcDaliStageSignalKeyEventN(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  KeyEventSignalData data;
+  KeyEventReceivedFunctor functor( data );
+  stage.KeyEventSignal().Connect( &application, functor );
+
+  // Check that a non-pressed key events data is not modified.
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliStageTouchedSignalP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  TouchedSignalData data;
+  TouchedFunctor functor( data );
+  stage.TouchedSignal().Connect( &application, functor );
+
+  // Render and notify.
+  application.SendNotification();
+  application.Render();
+
+  // Basic test: No actors, single touch (down then up).
+  {
+    Integration::TouchEvent touchEvent;
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    data.Reset();
+
+    touchEvent.points[0].state = TouchPoint::Up;
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    data.Reset();
+  }
+
+  // Add an actor to the scene.
+  Actor actor = Actor::New();
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.TouchedSignal().Connect( &DummyTouchCallback );
+  stage.Add( actor );
+
+  // Render and notify.
+  application.SendNotification();
+  application.Render();
+
+  // Actor on scene, single touch, down in actor, motion, then up outside actor.
+  {
+    Integration::TouchEvent touchEvent;
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( data.receivedTouchEvent.points[0].hitActor == actor );
+    data.Reset();
+
+    touchEvent.points[0].state = TouchPoint::Motion;
+    touchEvent.points[0].screen.x = 150.0f; // Some motion
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+    data.Reset();
+
+    touchEvent.points[0].state = TouchPoint::Up;
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    data.Reset();
+  }
+
+  // Multiple touch. Should only receive a touch on first down and last up.
+  {
+    Integration::TouchEvent touchEvent;
+
+    // 1st point
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+    application.ProcessEvent( touchEvent );
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    data.Reset();
+
+    // 2nd point
+    touchEvent.points[0].state = TouchPoint::Stationary;
+    touchEvent.points.push_back( TouchPoint( 1, TouchPoint::Down, 50.0f, 50.0f ) );
+    application.ProcessEvent( touchEvent );
+    DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION );
+    data.Reset();
+
+    // Primary point is up
+    touchEvent.points[0].state = TouchPoint::Up;
+    touchEvent.points[1].state = TouchPoint::Stationary;
+    application.ProcessEvent( touchEvent );
+    DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION );
+    data.Reset();
+
+    // Remove 1st point now, 2nd point is now in motion
+    touchEvent.points.erase( touchEvent.points.begin() );
+    touchEvent.points[0].state = TouchPoint::Motion;
+    touchEvent.points[0].screen.x = 150.0f;
+    application.ProcessEvent( touchEvent );
+    DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 0u, TEST_LOCATION );
+    data.Reset();
+
+    // Final point Up
+    touchEvent.points[0].state = TouchPoint::Up;
+    application.ProcessEvent( touchEvent );
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    data.Reset();
+  }
+  END_TEST;
+}
+
+int UtcDaliStageTouchedSignalN(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  TouchedSignalData data;
+  TouchedFunctor functor( data );
+  stage.TouchedSignal().Connect( &application, functor );
+
+  // Render and notify.
+  application.SendNotification();
+  application.Render();
+
+  // Confirm functor not called before there has been any touch event.
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+
+  // No actors, single touch, down, motion then up.
+  {
+    Integration::TouchEvent touchEvent;
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Down, 10.0f, 10.0f ) );
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    data.Reset();
+
+    // Confirm there is no signal when the touchpoint is only moved.
+    touchEvent.points[0].state = TouchPoint::Motion;
+    touchEvent.points[0].screen.x = 1200.0f; // Some motion
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+    data.Reset();
+
+    // Confirm a following up event generates a signal.
+    touchEvent.points[0].state = TouchPoint::Up;
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    data.Reset();
+  }
+
+  // Add an actor to the scene.
+  Actor actor = Actor::New();
+  actor.SetSize( 100.0f, 100.0f );
+  actor.SetAnchorPoint( AnchorPoint::TOP_LEFT );
+  actor.SetParentOrigin( ParentOrigin::TOP_LEFT );
+  actor.TouchedSignal().Connect( &DummyTouchCallback );
+  stage.Add( actor );
+
+  // Render and notify.
+  application.SendNotification();
+  application.Render();
+
+  // Actor on scene. Interrupted before down and interrupted after down.
+  {
+    Integration::TouchEvent touchEvent;
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Interrupted, 10.0f, 10.0f ) );
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Interrupted );
+    data.Reset();
+
+    touchEvent.points[0].state = TouchPoint::Down;
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( data.receivedTouchEvent.points[0].hitActor == actor );
+    DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Down );
+    data.Reset();
+
+    touchEvent.points[0].state = TouchPoint::Interrupted;
+    application.ProcessEvent( touchEvent );
+
+    DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+    DALI_TEST_CHECK( data.receivedTouchEvent.GetPointCount() != 0u );
+    DALI_TEST_CHECK( !data.receivedTouchEvent.points[0].hitActor );
+    DALI_TEST_CHECK( data.receivedTouchEvent.points[0].state == TouchPoint::Interrupted );
+
+    DALI_TEST_EQUALS( data.receivedTouchEvent.GetPointCount(), 1u, TEST_LOCATION );
+
+    // Check that getting info about a non-existent point causes an assert.
+    bool asserted = false;
+    try
+    {
+      data.receivedTouchEvent.GetPoint( 1 );
+    }
+    catch( Dali::DaliException& e )
+    {
+      DALI_TEST_PRINT_ASSERT( e );
+      DALI_TEST_ASSERT( e, "point < points.size() && \"No point at index\"", TEST_LOCATION );
+      asserted = true;
+    }
+    DALI_TEST_CHECK( asserted );
+
+    data.Reset();
+  }
+
+  END_TEST;
+}
+
+int UtcDaliStageSignalWheelEventP(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  WheelEventSignalData data;
+  WheelEventReceivedFunctor functor( data );
+  stage.WheelEventSignal().Connect( &application, functor );
+
+  Integration::WheelEvent event( Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2( 0.0f, 0.0f ), 1, 1000u );
+  application.ProcessEvent( event );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( static_cast< WheelEvent::Type >(event.type) == data.receivedWheelEvent.type );
+  DALI_TEST_CHECK( event.direction == data.receivedWheelEvent.direction );
+  DALI_TEST_CHECK( event.modifiers == data.receivedWheelEvent.modifiers );
+  DALI_TEST_CHECK( event.point == data.receivedWheelEvent.point );
+  DALI_TEST_CHECK( event.z == data.receivedWheelEvent.z );
+  DALI_TEST_CHECK( event.timeStamp == data.receivedWheelEvent.timeStamp );
+
+  data.Reset();
+
+  Integration::WheelEvent event2( Integration::WheelEvent::CUSTOM_WHEEL, 0, 0u, Vector2( 0.0f, 0.0f ), -1, 1000u );
+  application.ProcessEvent( event2 );
+
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( static_cast< WheelEvent::Type >(event2.type) == data.receivedWheelEvent.type );
+  DALI_TEST_CHECK( event2.direction == data.receivedWheelEvent.direction );
+  DALI_TEST_CHECK( event2.modifiers == data.receivedWheelEvent.modifiers );
+  DALI_TEST_CHECK( event2.point == data.receivedWheelEvent.point );
+  DALI_TEST_CHECK( event2.z == data.receivedWheelEvent.z );
+  DALI_TEST_CHECK( event2.timeStamp == data.receivedWheelEvent.timeStamp );
+  END_TEST;
+}
+
+int UtcDaliStageContextLostSignalP(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  bool contextLost = false;
+  ContextStatusFunctor contextLostFunctor( contextLost );
+  stage.ContextLostSignal().Connect( &app, contextLostFunctor );
+
+  Integration::ContextNotifierInterface* notifier = app.GetCore().GetContextNotifier();
+  notifier->NotifyContextLost();
+  DALI_TEST_EQUALS( contextLost, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliStageContextLostSignalN(void)
+{
+  TestApplication app;
+  Stage stage;
+
+  // Check that connecting to the signal with a bad stage instance causes an assert.
+  bool asserted = false;
+  bool contextLost = false;
+  ContextStatusFunctor contextLostFunctor( contextLost );
+  try
+  {
+    stage.ContextLostSignal().Connect( &app, contextLostFunctor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliStageContextRegainedSignalP(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  bool contextRegained = false;
+  ContextStatusFunctor contextRegainedFunctor( contextRegained );
+  stage.ContextRegainedSignal().Connect( &app, contextRegainedFunctor );
+
+  Integration::ContextNotifierInterface* notifier = app.GetCore().GetContextNotifier();
+  notifier->NotifyContextLost();
+  notifier->NotifyContextRegained();
+  DALI_TEST_EQUALS( contextRegained, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliStageContextRegainedSignalN(void)
+{
+  TestApplication app;
+  Stage stage;
+
+  // Check that connecting to the signal with a bad stage instance causes an assert.
+  bool asserted = false;
+  bool contextRegained = false;
+  ContextStatusFunctor contextRegainedFunctor( contextRegained );
+  try
+  {
+    stage.ContextRegainedSignal().Connect( &app, contextRegainedFunctor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliStageSceneCreatedSignalP(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  bool signalCalled = false;
+  SceneCreatedStatusFunctor sceneCreatedFunctor( signalCalled );
+  stage.SceneCreatedSignal().Connect( &app, sceneCreatedFunctor );
+
+  Integration::Core& core = app.GetCore();
+  core.SceneCreated();
+  DALI_TEST_EQUALS( signalCalled, true, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliStageSceneCreatedSignalN(void)
+{
+  TestApplication app;
+  Stage stage;
+
+  // Check that connecting to the signal with a bad stage instance causes an assert.
+  bool asserted = false;
+  bool signalCalled = false;
+  SceneCreatedStatusFunctor sceneCreatedFunctor( signalCalled );
+  try
+  {
+    stage.SceneCreatedSignal().Connect( &app, sceneCreatedFunctor );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliStageGetRenderTaskListP(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  // Check we get a valid instance.
+  const RenderTaskList& tasks = stage.GetRenderTaskList();
+
+  // There should be 1 task by default.
+  DALI_TEST_EQUALS( tasks.GetTaskCount(), 1u, TEST_LOCATION );
+
+  // RenderTaskList has it's own UTC tests.
+  // But we can confirm that GetRenderTaskList in Stage retrieves the same RenderTaskList each time.
+  RenderTask newTask = stage.GetRenderTaskList().CreateTask();
+
+  DALI_TEST_EQUALS( stage.GetRenderTaskList().GetTask( 1 ), newTask, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliStageGetRenderTaskListN(void)
+{
+  TestApplication app;
+  Stage stage;
+
+  // Check that getting the render task list with a bad stage instance causes an assert.
+  bool asserted = false;
+  try
+  {
+    stage.GetRenderTaskList();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "stage && \"Stage handle is empty\"", TEST_LOCATION );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( asserted );
+
+  END_TEST;
+}
+
+int UtcDaliStageGetObjectRegistryP(void)
+{
+  TestApplication app;
+  Stage stage = Stage::GetCurrent();
+
+  ObjectRegistry objectRegistry = stage.GetObjectRegistry();
+
+  // Object registry tests are covered in their own module.
+  // However we want a basic test to confirm the returned registry is valid and works.
+  bool verified = false;
+  ActorCreatedFunctor test( verified );
+  objectRegistry.ObjectCreatedSignal().Connect( &app, test );
+
+  Actor actor = Actor::New();
+  DALI_TEST_CHECK( test.mSignalVerified );
+
+  END_TEST;
+}
+
+int UtcDaliStageGetObjectRegistryN(void)
+{
+  TestApplication app;
+  Stage stage;
+
+  // Check that getting the object registry with a bad stage instance DOES NOT cause an assert.
+  // This is because GetCurrent() is used, always creating a stage if one does not exist.
+  bool asserted = false;
+  try
+  {
+    stage.GetObjectRegistry();
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    asserted = true;
+  }
+  DALI_TEST_CHECK( !asserted );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-TapGesture.cpp b/automated-tests/src/dali/utc-Dali-TapGesture.cpp
new file mode 100644 (file)
index 0000000..e53dcbb
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_tap_gesture_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_tap_gesture_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+// Positive test case for a method
+int UtcDaliTapGestureConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  TapGesture gesture;
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Tap, gesture.type, TEST_LOCATION);
+
+  // Test Copy constructor
+  gesture.numberOfTouches = 5u;
+  gesture.numberOfTaps = 2u;
+
+  TapGesture gesture2(gesture);
+  DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(2u, gesture2.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Tap, gesture2.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureAssignment(void)
+{
+  // Test Assignment operator
+  TapGesture gesture;
+  DALI_TEST_EQUALS(1u, gesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Tap, gesture.type, TEST_LOCATION);
+
+  gesture.numberOfTouches = 5u;
+  gesture.numberOfTaps = 2u;
+
+  TapGesture gesture2;
+  gesture2 = gesture;
+  DALI_TEST_EQUALS(5u, gesture2.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(2u, gesture2.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Tap, gesture2.type, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureDynamicAllocation(void)
+{
+  TapGesture* gesture = new TapGesture;
+  DALI_TEST_EQUALS(1u, gesture->numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, gesture->numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(Gesture::Tap, gesture->type, TEST_LOCATION);
+  delete gesture;
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp b/automated-tests/src/dali/utc-Dali-TapGestureDetector.cpp
new file mode 100644 (file)
index 0000000..eed11ca
--- /dev/null
@@ -0,0 +1,1387 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+#include <test-touch-utils.h>
+
+using namespace Dali;
+
+void utc_dali_tap_gesture_detector_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_tap_gesture_detector_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled(false),
+    voidFunctorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+    voidFunctorCalled = false;
+
+    receivedGesture.numberOfTaps = 0u;
+    receivedGesture.numberOfTouches = 0u;
+    receivedGesture.screenPoint = Vector2(0.0f, 0.0f);
+    receivedGesture.localPoint = Vector2(0.0f, 0.0f);
+
+    tappedActor.Reset();
+  }
+
+  bool functorCalled;
+  bool voidFunctorCalled;
+  TapGesture receivedGesture;
+  Actor tappedActor;
+};
+
+// Functor that sets the data when called
+struct GestureReceivedFunctor
+{
+  GestureReceivedFunctor(SignalData& data) : signalData(data) { }
+
+  void operator()(Actor actor, const TapGesture& tap)
+  {
+    signalData.functorCalled = true;
+    signalData.receivedGesture = tap;
+    signalData.tappedActor = actor;
+  }
+
+  void operator()()
+  {
+    signalData.voidFunctorCalled = true;
+  }
+
+  SignalData& signalData;
+};
+
+// Functor that removes the gestured actor from stage
+struct UnstageActorFunctor : public GestureReceivedFunctor
+{
+  UnstageActorFunctor( SignalData& data ) : GestureReceivedFunctor( data ) { }
+
+  void operator()(Actor actor, const TapGesture& tap)
+  {
+    GestureReceivedFunctor::operator()( actor, tap );
+    Stage::GetCurrent().Remove( actor );
+  }
+};
+
+// Functor for receiving a touch event
+struct TouchEventFunctor
+{
+  bool operator()(Actor actor, const TouchEvent& touch)
+  {
+    //For line coverage
+    unsigned int points = touch.GetPointCount();
+    if( points > 0)
+    {
+      const TouchPoint& touchPoint = touch.GetPoint(0);
+      tet_printf("Touch Point state = %d\n", touchPoint.state);
+    }
+    return false;
+  }
+};
+
+// Generate a TapGestureEvent to send to Core
+Integration::TapGestureEvent GenerateTap(
+    Gesture::State state,
+    unsigned int numberOfTaps,
+    unsigned int numberOfTouches,
+    Vector2 point)
+{
+  Integration::TapGestureEvent tap( state );
+
+  tap.numberOfTaps = numberOfTaps;
+  tap.numberOfTouches = numberOfTouches;
+  tap.point = point;
+
+  return tap;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+// Positive test case for a method
+int UtcDaliTapGestureDetectorConstructor(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector;
+  DALI_TEST_CHECK(!detector);
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorCopyConstructorP(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector = TapGestureDetector::New();
+
+  TapGestureDetector copy( detector );
+  DALI_TEST_CHECK( detector );
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector = TapGestureDetector::New();;
+
+  TapGestureDetector assign;
+  assign = detector;
+  DALI_TEST_CHECK( detector );
+
+  DALI_TEST_CHECK( detector == assign );
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorNew(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  DALI_TEST_CHECK(detector);
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION);
+
+  TapGestureDetector detector2 = TapGestureDetector::New( 5u );
+  DALI_TEST_CHECK(detector2);
+  DALI_TEST_EQUALS(5u, detector2.GetMinimumTapsRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(5u, detector2.GetMaximumTapsRequired(), TEST_LOCATION);
+
+  //Scoped test to test destructor
+  {
+    TapGestureDetector detector3 = TapGestureDetector::New();
+    DALI_TEST_CHECK(detector3);
+  }
+
+  // Attach an actor and emit a touch event on the actor to ensure complete line coverage
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  detector.Attach(actor);
+
+  TouchEventFunctor touchFunctor;
+  actor.TouchedSignal().Connect( &application, touchFunctor );
+
+  Integration::TouchEvent touchEvent(1);
+  TouchPoint point(1, TouchPoint::Down, 20.0f, 20.0f);
+  touchEvent.AddPoint(point);
+  application.ProcessEvent(touchEvent);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // For line coverage, Initialise default constructor
+  TouchEvent touchEvent2;
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorDownCast(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::TapGestureDetector::DownCast()");
+
+  TapGestureDetector detector = TapGestureDetector::New();
+
+  BaseHandle object(detector);
+
+  TapGestureDetector detector2 = TapGestureDetector::DownCast(object);
+  DALI_TEST_CHECK(detector2);
+
+  TapGestureDetector detector3 = DownCast< TapGestureDetector >(object);
+  DALI_TEST_CHECK(detector3);
+
+  BaseHandle unInitializedObject;
+  TapGestureDetector detector4 = TapGestureDetector::DownCast(unInitializedObject);
+  DALI_TEST_CHECK(!detector4);
+
+  TapGestureDetector detector5 = DownCast< TapGestureDetector >(unInitializedObject);
+  DALI_TEST_CHECK(!detector5);
+
+  GestureDetector detector6 = TapGestureDetector::New();
+  TapGestureDetector detector7 = TapGestureDetector::DownCast(detector6);
+  DALI_TEST_CHECK(detector7);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSetTapsRequired(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector = TapGestureDetector::New();
+
+  const unsigned int minTaps = 3;
+  const unsigned int maxTaps = 7;
+
+  DALI_TEST_CHECK( minTaps != detector.GetMinimumTapsRequired() );
+  DALI_TEST_CHECK( maxTaps != detector.GetMaximumTapsRequired() );
+
+  detector.SetMinimumTapsRequired( minTaps );
+  detector.SetMaximumTapsRequired( maxTaps );
+
+  DALI_TEST_EQUALS( minTaps, detector.GetMinimumTapsRequired(), TEST_LOCATION );
+  DALI_TEST_EQUALS( maxTaps, detector.GetMaximumTapsRequired(), TEST_LOCATION );
+
+  // Attach an actor and change the required touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Ensure signal is emitted if minimum taps received
+  application.ProcessEvent(GenerateTap(Gesture::Possible, minTaps, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, minTaps, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( minTaps, data.receivedGesture.numberOfTaps, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure signal is emitted if maximum taps received
+  application.ProcessEvent(GenerateTap(Gesture::Possible, maxTaps, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, maxTaps, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( maxTaps, data.receivedGesture.numberOfTaps, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure signal is NOT emitted if outside the range
+  application.ProcessEvent(GenerateTap(Gesture::Possible, minTaps - 1, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, minTaps - 1, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, maxTaps + 1, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, maxTaps + 1, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  TestGestureManager& gestureManager = application.GetGestureManager();
+  gestureManager.Initialize();
+
+  detector.SetMinimumTapsRequired(4);
+
+  // Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  detector.SetMaximumTapsRequired(maxTaps);
+
+  // Gesture detection should NOT have been updated
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Create a second gesture detector that requires even less maximum touches
+  TapGestureDetector secondDetector = TapGestureDetector::New();
+  secondDetector.Attach(actor);
+
+  // Gesture detection should have been updated
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Reset values
+  gestureManager.Initialize();
+
+  // Delete the second detector so that our detection is updated again
+  secondDetector.Reset();
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+  // Set the minimum to be greater than the maximum, should Assert
+  try
+  {
+    detector.SetMinimumTapsRequired( maxTaps );
+    detector.SetMaximumTapsRequired( minTaps );
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTapGestureSetTapsRequiredMinMaxCheck(void)
+{
+  TestApplication application;
+
+  // Attach an actor and change the required touches
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set the minimum to be greater than the maximum, should Assert
+
+  try
+  {
+    TapGestureDetector detector = TapGestureDetector::New();
+    detector.SetMinimumTapsRequired( 7u );
+    detector.SetMaximumTapsRequired( 3u );
+    detector.Attach(actor);
+    DALI_TEST_CHECK( false ); // Should not get here
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_CHECK( true );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTapGestureGetTapsRequired(void)
+{
+  TestApplication application;
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  DALI_TEST_EQUALS(1u, detector.GetMinimumTapsRequired(), TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, detector.GetMaximumTapsRequired(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionNegative(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Do a tap outside actor's area
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(112.0f, 112.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(112.0f, 112.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionPositive(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Do a tap inside actor's area
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionDetach(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Start tap within the actor's area
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(20.0f, 20.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+
+  // repeat the tap within the actor's area - we should still receive the signal
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(50.0f, 50.0f), data.receivedGesture.localPoint, 0.1, TEST_LOCATION);
+
+  // Detach actor
+  detector.DetachAll();
+
+  // Ensure we are no longer signalled
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionActorDestroyedWhileTapping(void)
+{
+  TestApplication application;
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Actor lifetime is scoped
+  {
+    Actor actor = Actor::New();
+    actor.SetSize(100.0f, 100.0f);
+    actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+    Stage::GetCurrent().Add(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+
+    detector.Attach(actor);
+
+    // Start tap within the actor's area
+    application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f)));
+    application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+    // Remove the actor from stage and reset the data
+    Stage::GetCurrent().Remove(actor);
+
+    // Render and notify
+    application.SendNotification();
+    application.Render();
+  }
+
+  // Actor should now have been destroyed
+
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 20.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 20.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionRotatedActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do tap, only check finished value
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(5.0f, 5.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION);
+
+  // Rotate actor again and render
+  actor.SetOrientation(Dali::Degree(180.0f), Vector3::ZAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do tap, should still receive event
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(5.0f, 5.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(5.0f, 5.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTaps, TEST_LOCATION);
+  DALI_TEST_EQUALS(1u, data.receivedGesture.numberOfTouches, TEST_LOCATION);
+  DALI_TEST_EQUALS( Vector2(5.0f, 5.0f), data.receivedGesture.screenPoint, 0.1, TEST_LOCATION);
+
+  // Rotate actor again and render
+  actor.SetOrientation(Dali::Degree(90.0f), Vector3::YAXIS);
+  application.SendNotification();
+  application.Render();
+
+  // Do tap, inside the actor's area (area if it is not rotated), Should not receive the event
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(70.0f, 70.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(70.0f, 70.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionChildHit(void)
+{
+  TestApplication application;
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  // Set child to completely cover parent.
+  // Change rotation of child to be different from parent so that we can check if our local coordinate
+  // conversion of the parent actor is correct.
+  Actor child = Actor::New();
+  child.SetSize(100.0f, 100.0f);
+  child.SetAnchorPoint(AnchorPoint::CENTER);
+  child.SetParentOrigin(ParentOrigin::CENTER);
+  child.SetOrientation(Dali::Degree(90.0f), Vector3::ZAXIS);
+  parent.Add(child);
+
+  TouchEventFunctor touchFunctor;
+  child.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(parent);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Do tap - hits child area but parent should still receive it
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 50.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 50.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, parent == data.tappedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(50.0f, 50.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION);
+
+  // Attach child and generate same touch points
+  // (Also proves that you can detach and then re-attach another actor)
+  detector.Attach(child);
+  detector.Detach(parent);
+
+  // Do an entire tap, only check finished value
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(51.0f, 51.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(51.0f, 51.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, child == data.tappedActor, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector2(51.0f, 51.0f), data.receivedGesture.screenPoint, 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionAttachDetachMany(void)
+{
+  TestApplication application;
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetX(100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(first);
+  detector.Attach(second);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Tap within second actor's area
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION);
+
+  // Tap within first actor's area
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION);
+
+  // Detach the second actor
+  detector.Detach(second);
+
+  // second actor shouldn't receive event
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(120.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(120.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // first actor should continue receiving event
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(20.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionActorBecomesUntouchable(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  // Tap in actor's area
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+
+  // Actor become invisible - actor should not receive the next pan
+  actor.SetVisible(false);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Tap in the same area, shouldn't receive event
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionMultipleGestureDetectors(void)
+{
+  TestApplication application;
+  Dali::TestGestureManager& gestureManager = application.GetGestureManager();
+
+  Actor first = Actor::New();
+  first.SetSize(100.0f, 100.0f);
+  first.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(first);
+
+  Actor second = Actor::New();
+  second.SetSize(100.0f, 100.0f);
+  second.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  second.SetX(100.0f);
+  first.Add(second);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector firstDetector = TapGestureDetector::New();
+  firstDetector.Attach(first);
+  firstDetector.DetectedSignal().Connect(&application, functor);
+
+  // secondDetector is scoped
+  {
+    // Reset gestureManager statistics
+    gestureManager.Initialize();
+
+    TapGestureDetector secondDetector = TapGestureDetector::New( 2 );
+    secondDetector.Attach(second);
+    secondDetector.DetectedSignal().Connect(&application, functor);
+
+    DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+    DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+
+    // Tap within second actor's area
+    application.ProcessEvent(GenerateTap(Gesture::Possible, 2u, 1u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateTap(Gesture::Started, 2u, 1u, Vector2(150.0f, 10.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, second == data.tappedActor, TEST_LOCATION);
+
+    // Tap continues as single touch gesture - we should not receive any gesture
+    data.Reset();
+    application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(150.0f, 10.0f)));
+    application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(150.0f, 10.0f)));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Single touch tap starts - first actor should be panned
+    data.Reset();
+    application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+    DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+    DALI_TEST_EQUALS(true, first == data.tappedActor, TEST_LOCATION);
+
+    // Pan changes to double-touch - we shouldn't receive event
+    data.Reset();
+    application.ProcessEvent(GenerateTap(Gesture::Possible, 2u, 2u, Vector2(50.0f, 10.0f)));
+    application.ProcessEvent(GenerateTap(Gesture::Started, 2u, 2u, Vector2(50.0f, 10.0f)));
+    DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+    // Reset gesture manager statistics
+    gestureManager.Initialize();
+  }
+
+  // secondDetector has now been deleted.  Gesture detection should have been updated only
+  DALI_TEST_EQUALS(true, gestureManager.WasCalled(TestGestureManager::UpdateType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::RegisterType), TEST_LOCATION);
+  DALI_TEST_EQUALS(false, gestureManager.WasCalled(TestGestureManager::UnregisterType), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionMultipleDetectorsOnActor(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to one detector
+  SignalData firstData;
+  GestureReceivedFunctor firstFunctor(firstData);
+  TapGestureDetector firstDetector = TapGestureDetector::New();
+  firstDetector.Attach(actor);
+  firstDetector.DetectedSignal().Connect(&application, firstFunctor);
+
+  // Attach actor to another detector
+  SignalData secondData;
+  GestureReceivedFunctor secondFunctor(secondData);
+  TapGestureDetector secondDetector = TapGestureDetector::New();
+  secondDetector.Attach(actor);
+  secondDetector.DetectedSignal().Connect(&application, secondFunctor);
+
+  // Tap in actor's area - both detector's functors should be called
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, firstData.functorCalled, TEST_LOCATION);
+  DALI_TEST_EQUALS(true, secondData.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSignalReceptionDifferentPossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Gesture possible in actor's area.
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor somewhere else
+  actor.SetPosition( 100.0f, 100.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the tap.
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Tap possible in empty area.
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Move actor in to the tap position.
+  actor.SetPosition( 0.0f, 0.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit Started event, we should not receive the tap.
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Normal tap in actor's area for completeness.
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureEmitIncorrectStateClear(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Clear state
+  try
+  {
+    application.ProcessEvent(GenerateTap(Gesture::Clear, 1u, 1u, Vector2(50.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTapGestureEmitIncorrectStateContinuing(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Continuing state
+  try
+  {
+    application.ProcessEvent(GenerateTap(Gesture::Continuing, 1u, 1u, Vector2(50.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTapGestureEmitIncorrectStateFinished(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Try a Finished state
+  try
+  {
+    application.ProcessEvent(GenerateTap(Gesture::Finished, 1u, 1u, Vector2(50.0f, 10.0f)));
+    tet_result(TET_FAIL);
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "false", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTapGestureActorUnstaged(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  UnstageActorFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Tap in Actor's area, actor removed in signal handler, should be handled gracefully.
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  tet_result( TET_PASS ); // If we get here, then the actor removal on signal handler was handled gracefully.
+  END_TEST;
+}
+
+int UtcDaliTapGestureRepeatedState(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit two possibles
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Send a couple of Started states, only first one should be received.
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+
+  // Send a couple of cancelled states, no reception
+  application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGesturePossibleCancelled(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit a possible and then a cancelled, no reception
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Cancelled, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorRemovedWhilePossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit a possible
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+
+  // Detach actor and send a Started state, no signal.
+  detector.DetachAll();
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureActorRemovedWhilePossible(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Emit a possible
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+
+  // Remove, render and delete actor
+  Stage::GetCurrent().Remove(actor);
+  application.SendNotification();
+  application.Render();
+  actor.Reset();
+
+  // Send a Started state, no signal.
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+
+  // Do a tap inside actor's area
+  application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTapGestureBehindTouchableSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set system-overlay actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  systemOverlayActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set stage actor to receive the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(stageActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+
+  // Do a tap inside both actors' area
+  application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTapGestureTouchBehindGesturedSystemOverlay(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core = application.GetCore();
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // SystemOverlay actor
+  Actor systemOverlayActor = Actor::New();
+  systemOverlayActor.SetSize(100.0f, 100.0f);
+  systemOverlayActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add(systemOverlayActor);
+
+  // Stage actor
+  Actor stageActor = Actor::New();
+  stageActor.SetSize(100.0f, 100.0f);
+  stageActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(stageActor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Set stage actor to touchable
+  TouchEventData touchData;
+  TouchEventDataFunctor touchFunctor( touchData );
+  stageActor.TouchedSignal().Connect(&application, touchFunctor);
+
+  // Set system-overlay actor to have the gesture
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(systemOverlayActor);
+  detector.DetectedSignal().Connect(&application, functor);
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+
+  // Do a tap inside both actors' area
+  application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, touchData.functorCalled, TEST_LOCATION );
+
+  data.Reset();
+  touchData.Reset();
+
+  // Do touch in the same area
+  application.ProcessEvent( touchFunctor.GenerateSingleTouch( TouchPoint::Down, screenCoords ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, touchData.functorCalled, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTapGestureLayerConsumesTouch(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Add a detector
+  SignalData data;
+  GestureReceivedFunctor functor(data);
+  TapGestureDetector detector = TapGestureDetector::New();
+  detector.Attach(actor);
+  detector.DetectedSignal().Connect( &application, functor );
+
+  // Add a layer to overlap the actor
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseToTop();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  Vector2 screenCoords( 50.0f, 50.0f );
+
+  // Emit signals, should receive
+  application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+  DALI_TEST_EQUALS(true, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  // Set layer to consume all touch
+  layer.SetTouchConsumed( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit the same signals again, should not receive
+  application.ProcessEvent( GenerateTap( Gesture::Possible, 1u, 1u, screenCoords ) );
+  application.ProcessEvent( GenerateTap( Gesture::Started, 1u, 1u, screenCoords ) );
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp b/automated-tests/src/dali/utc-Dali-TouchEventCombiner.cpp
new file mode 100644 (file)
index 0000000..fb1eafa
--- /dev/null
@@ -0,0 +1,902 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-combiner.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+using namespace Dali::Integration;
+
+void utc_dali_touch_event_combiner_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_touch_event_combiner_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+
+int UtcDaliTouchEventCombinerConstructors(void)
+{
+  TouchEventCombiner combiner1;
+  DALI_TEST_EQUALS( combiner1.GetMinimumMotionTimeThreshold(), static_cast<long unsigned>(1), TEST_LOCATION );
+  DALI_TEST_EQUALS( combiner1.GetMinimumMotionDistanceThreshold(), Vector2( 1.0f, 1.0f ), TEST_LOCATION );
+
+  TouchEventCombiner combiner2( 10, 20.0f, 31.0f );
+  DALI_TEST_EQUALS( combiner2.GetMinimumMotionTimeThreshold(), static_cast<long unsigned>(10), TEST_LOCATION );
+  DALI_TEST_EQUALS( combiner2.GetMinimumMotionDistanceThreshold(), Vector2( 20.0f, 31.0f ), TEST_LOCATION );
+
+  TouchEventCombiner combiner3( 10, Vector2( 20.0f, 31.0f ) );
+  DALI_TEST_EQUALS( combiner3.GetMinimumMotionTimeThreshold(), static_cast<long unsigned>(10), TEST_LOCATION );
+  DALI_TEST_EQUALS( combiner3.GetMinimumMotionDistanceThreshold(), Vector2( 20.0f, 31.0f ), TEST_LOCATION );
+
+  // Boundary Checks
+
+  TouchEventCombiner combiner4( 10, 0.0f, 0.0f );
+  DALI_TEST_EQUALS( combiner4.GetMinimumMotionDistanceThreshold(), Vector2( 0.0f, 0.0f ), TEST_LOCATION );
+
+  TouchEventCombiner combiner5( 10, Vector2( 0.0f, 0.0f ) );
+  DALI_TEST_EQUALS( combiner5.GetMinimumMotionDistanceThreshold(), Vector2( 0.0f, 0.0f ), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerConstructorsNegative(void)
+{
+  try
+  {
+    TouchEventCombiner combiner( 10, -20.0f, 31.0f );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    TouchEventCombiner combiner( 10, 20.0f, -31.0f );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    TouchEventCombiner combiner( 10, Vector2( -20.0f, 31.0f ) );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    TouchEventCombiner combiner( 10, Vector2( 20.0f, -31.0f ) );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSettersAndGetters(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 10u );
+  Vector2 distance( 40.0f, 30.0f );
+
+  DALI_TEST_CHECK( combiner.GetMinimumMotionTimeThreshold() != time );
+  DALI_TEST_CHECK( combiner.GetMinimumMotionDistanceThreshold() != distance );
+
+  combiner.SetMinimumMotionTimeThreshold( time );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionTimeThreshold(), time, TEST_LOCATION );
+
+  combiner.SetMinimumMotionDistanceThreshold( distance.x );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2( distance.x, distance.x ), TEST_LOCATION );
+
+  distance.x = 20.0f;
+  distance.y = 50.0f;
+  combiner.SetMinimumMotionDistanceThreshold( distance.x, distance.y );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), distance, TEST_LOCATION );
+
+  distance.x = 100.0f;
+  distance.y = 20.0f;
+  combiner.SetMinimumMotionDistanceThreshold( distance );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), distance, TEST_LOCATION );
+
+  // Boundary Checks
+
+  combiner.SetMinimumMotionDistanceThreshold( 0.0f );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION );
+
+  combiner.SetMinimumMotionDistanceThreshold( 0.0f, 0.0f );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION );
+
+  combiner.SetMinimumMotionDistanceThreshold( Vector2::ZERO );
+  DALI_TEST_EQUALS( combiner.GetMinimumMotionDistanceThreshold(), Vector2::ZERO, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSettersNegative(void)
+{
+  TouchEventCombiner combiner;
+
+  try
+  {
+    combiner.SetMinimumMotionDistanceThreshold( -100.0f );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    combiner.SetMinimumMotionDistanceThreshold( -100.0f, 20.0f );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    combiner.SetMinimumMotionDistanceThreshold( 100.0f, -20.0f );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    combiner.SetMinimumMotionDistanceThreshold( Vector2( -100.0f, 20.0f ) );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+
+  try
+  {
+    combiner.SetMinimumMotionDistanceThreshold( Vector2( 100.0f, -20.0f ) );
+    tet_printf( "%s: Should have asserted\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    tet_result( TET_PASS );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchNormal(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion in X direction
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion in Y direction
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 101.0f, 101.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  // Motion event, but same time
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event, both X and Y movement
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event, no movement
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+
+  // Up event, no time diff, no movement
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchMotionWithoutDown(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchMotionFollowedByDown(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 103.0f, 103.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 103.0f, 103.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Finished, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchTwoDowns(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Another down with the same ID
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchUpWithoutDown(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+
+  time++;
+
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchTwoUps(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Another up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchUpWithDifferentId(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Up event with different ID
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+
+  time++;
+
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchMotionWithDifferentId(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event with different ID
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Motion, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchHover, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, TouchPoint::Started, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Motion event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 102.0f, 102.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerMultiTouchNormal(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // 1st point down
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // 2nd point down
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Down, 200.0f, 200.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // 1st point motion
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Motion, 101.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].state, TouchPoint::Stationary, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  // 2nd point motion, no time diff
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Motion, 200.0f, 200.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+
+  time++;
+
+  // 2nd point motion
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Motion, 201.0f, 201.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, TouchPoint::Stationary, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // 1st point up
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 101.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 2u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[1].state, TouchPoint::Stationary, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // 2nd point motion
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Motion, 202.0f, 202.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // 2nd point up
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 2, TouchPoint::Up, 202.0f, 202.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSeveralPoints(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+  unsigned int const maximum( 200u );
+
+  // Several downs
+  for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount )
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
+  }
+
+  // Several Ups
+  for ( unsigned int pointCount = maximum - 1; pointCount > 0; --pointCount )
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( pointCount, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time++, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerReset(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Reset combiner, no more events should be sent to core.
+  combiner.Reset();
+
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerSingleTouchInterrupted(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Down event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].deviceId, point.deviceId, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].screen, point.screen, TEST_LOCATION );
+  }
+
+  time++;
+
+  // Interrupted event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+  }
+
+  // Send up, should not be able to send as combiner has been reset.
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerMultiTouchInterrupted(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+  unsigned int const maximum( 200u );
+
+  // Several downs
+  for ( unsigned int pointCount = 1u; pointCount < maximum; ++pointCount )
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( pointCount, TouchPoint::Down, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchTouch, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), pointCount, TEST_LOCATION );
+  }
+
+  // Interrupted event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Interrupted, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchBoth, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( touchEvent.points[0].state, point.state, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.GetPointCount(), 1u, TEST_LOCATION );
+    DALI_TEST_EQUALS( hoverEvent.points[0].state, point.state, TEST_LOCATION );
+  }
+
+  // Send up, should not be able to send as combiner has been reset.
+  // Up event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Up, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchEventCombinerInvalidState(void)
+{
+  TouchEventCombiner combiner;
+  unsigned long time( 0u );
+
+  // Stationary event
+  {
+    Integration::TouchEvent touchEvent;
+    Integration::HoverEvent hoverEvent;
+    TouchPoint point( 1, TouchPoint::Stationary, 100.0f, 100.0f );
+
+    DALI_TEST_EQUALS( Integration::TouchEventCombiner::DispatchNone, combiner.GetNextTouchEvent( point, time, touchEvent, hoverEvent ), TEST_LOCATION );
+  }
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp b/automated-tests/src/dali/utc-Dali-TouchProcessing.cpp
new file mode 100644 (file)
index 0000000..f38084b
--- /dev/null
@@ -0,0 +1,1368 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_touch_processing_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_touch_processing_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled( false ),
+    touchEvent(),
+    touchedActor()
+  {
+  }
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    touchEvent.time = 0u;
+    touchEvent.points.clear();
+
+    touchedActor.Reset();
+  }
+
+  bool functorCalled;
+  TouchEvent touchEvent;
+  Actor touchedActor;
+};
+
+// Functor that sets the data when called
+struct TouchEventFunctor
+{
+  /**
+   * Constructor.
+   * @param[in]  data         Reference to the data to store callback information.
+   * @param[in]  returnValue  What the functor should return.
+   */
+  TouchEventFunctor( SignalData& data, bool returnValue = true )
+  : signalData( data ),
+    returnValue( returnValue )
+  {
+  }
+
+  bool operator()( Actor actor, const TouchEvent& touchEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.touchedActor = actor;
+    signalData.touchEvent = touchEvent;
+
+    return returnValue;
+  }
+
+  SignalData& signalData;
+  bool returnValue;
+};
+
+// Functor that removes the actor when called.
+struct RemoveActorFunctor : public TouchEventFunctor
+{
+  /**
+   * Constructor.
+   * @param[in]  data         Reference to the data to store callback information.
+   * @param[in]  returnValue  What the functor should return.
+   */
+  RemoveActorFunctor( SignalData& data, bool returnValue = true )
+  : TouchEventFunctor( data, returnValue )
+  {
+  }
+
+  bool operator()( Actor actor, const TouchEvent& touchEvent )
+  {
+    Actor parent( actor.GetParent() );
+    if ( parent )
+    {
+      parent.Remove( actor );
+    }
+
+    return TouchEventFunctor::operator()( actor, touchEvent );
+  }
+};
+
+Integration::TouchEvent GenerateSingleTouch( TouchPoint::State state, Vector2 screenPosition )
+{
+  Integration::TouchEvent touchEvent;
+  touchEvent.points.push_back( TouchPoint ( 0, state, screenPosition.x, screenPosition.y ) );
+  return touchEvent;
+}
+
+} // anon namespace
+
+///////////////////////////////////////////////////////////////////////////////
+
+int UtcDaliTouchNormalProcessing(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Vector2 localCoordinates;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  const TouchPoint *point1 = &data.touchEvent.GetPoint(0);
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, point1->state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, point1->screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, point1->local, 0.1f, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a motion signal
+  screenCoordinates.x = screenCoordinates.y = 11.0f;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, screenCoordinates ) );
+  const TouchPoint *point2 = &data.touchEvent.GetPoint(0);
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, point2->state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, point2->screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, point2->local, 0.1f, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an up signal
+  screenCoordinates.x = screenCoordinates.y = 12.0f;
+  actor.ScreenToLocal( localCoordinates.x, localCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, screenCoordinates ) );
+  const TouchPoint *point3 = &data.touchEvent.GetPoint(0);
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Up, point3->state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, point3->screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( localCoordinates, point3->local, 0.1f, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal where the actor is not present
+  screenCoordinates.x = screenCoordinates.y = 200.0f;
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchOutsideCameraNearFarPlanes(void)
+{
+  TestApplication application;
+
+  Stage stage = Stage::GetCurrent();
+  Vector2 stageSize = stage.GetSize();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::CENTER);
+  actor.SetParentOrigin(ParentOrigin::CENTER);
+  stage.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Get the camera's near and far planes
+  RenderTaskList taskList = stage.GetRenderTaskList();
+  Dali::RenderTask task = taskList.GetTask(0);
+  CameraActor camera = task.GetCameraActor();
+  float nearPlane = camera.GetNearClippingPlane();
+  float farPlane = camera.GetFarClippingPlane();
+
+  // Calculate the current distance of the actor from the camera
+  float tanHalfFov = tanf(camera.GetFieldOfView() * 0.5f);
+  float distance = (stageSize.y * 0.5f) / tanHalfFov;
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  Vector2 screenCoordinates( stageSize.x * 0.5f, stageSize.y * 0.5f );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal where actor is just at the camera's near plane
+  actor.SetZ(distance - nearPlane);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal where actor is closer than the camera's near plane
+  actor.SetZ((distance - nearPlane) + 1.0f);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal where actor is just at the camera's far plane
+  actor.SetZ(distance - farPlane);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal where actor is further than the camera's far plane
+  actor.SetZ((distance - farPlane) - 1.0f);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchEmitEmpty(void)
+{
+  TestApplication application;
+
+  try
+  {
+    // Emit an empty TouchEvent
+    Integration::TouchEvent event;
+    application.ProcessEvent( event );
+    tet_result( TET_FAIL );
+  }
+  catch ( Dali::DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "!event.points.empty()", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliTouchInterrupted(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an interrupted signal, we should be signalled regardless of whether there is a hit or not.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit another interrupted signal, our signal handler should not be called.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to root actor's touched signal
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Vector2 actorCoordinates, rootCoordinates;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a motion signal
+  screenCoordinates.x = screenCoordinates.y = 11.0f;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit an up signal
+  screenCoordinates.x = screenCoordinates.y = 12.0f;
+  actor.ScreenToLocal( actorCoordinates.x, actorCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, screenCoordinates ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, data.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Up, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Up, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, data.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( actorCoordinates, data.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a down signal where the actor is not present, will hit the root actor though
+  screenCoordinates.x = screenCoordinates.y = 200.0f;
+  rootActor.ScreenToLocal( rootCoordinates.x, rootCoordinates.y, screenCoordinates.x, screenCoordinates.y );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, screenCoordinates ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, rootData.touchEvent.GetPointCount(), TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( screenCoordinates, rootData.touchEvent.points[0].screen, TEST_LOCATION );
+  DALI_TEST_EQUALS( rootCoordinates, rootData.touchEvent.points[0].local, 0.1f, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor );
+  END_TEST;
+}
+
+int UtcDaliTouchInterruptedParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to root actor's touched signal
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit an interrupted signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit another down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  rootData.Reset();
+
+  // Remove actor from Stage
+  Stage::GetCurrent().Remove( actor );
+  data.Reset();
+  rootData.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit an interrupted signal, only root actor's signal should be called.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f /* Outside actor */ ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit another interrupted state, none of the signal's should be called.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, rootData.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchLeave(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Set actor to require leave events
+  actor.SetLeaveRequired( true );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a motion signal outside of actor, should be signalled with a Leave
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Another motion outside of actor, no signalling
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Another motion event inside actor, signalled with motion
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // We do not want to listen to leave events anymore
+  actor.SetLeaveRequired( false );
+
+  // Another motion event outside of actor, no signalling
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchLeaveParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to root actor's touched signal
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  // Set actor to require leave events
+  actor.SetLeaveRequired( true );
+  rootActor.SetLeaveRequired( true );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Emit a motion signal outside of actor, should be signalled with a Leave
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Another motion outside of actor, only rootActor signalled
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 201.0f, 201.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Another motion event inside actor, signalled with motion
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 10.0f, 10.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Motion, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // We do not want to listen to leave events of actor anymore
+  actor.SetLeaveRequired( false );
+
+  // Another motion event outside of root actor, only root signalled
+  Vector2 stageSize( Stage::GetCurrent().GetSize() );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( stageSize.width + 10.0f, stageSize.height + 10.0f )) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchActorBecomesInsensitive(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  // Change actor to insensitive
+  actor.SetSensitive( false );
+
+  // Emit a motion signal, signalled with an interrupted
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchActorBecomesInsensitiveParentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to root actor's touched signal
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  data.Reset();
+  rootData.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Make root actor insensitive
+  rootActor.SetSensitive( false );
+
+  // Emit a motion signal, signalled with an interrupted (should get interrupted even if within root actor)
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2 ( 200.0f, 200.0f )) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchMultipleLayers(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+
+  Layer layer1 ( Layer::New() );
+  layer1.SetSize(100.0f, 100.0f);
+  layer1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer1 );
+
+  Actor actor1 ( Actor::New() );
+  actor1.SetSize( 100.0f, 100.0f );
+  actor1.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor1.SetZ( 1.0f ); // Should hit actor1 in this layer
+  layer1.Add( actor1 );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer1 and actor1
+  layer1.TouchedSignal().Connect( &application, functor );
+  actor1.TouchedSignal().Connect( &application, functor );
+
+  // Hit in hittable area, actor1 should be hit
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.touchedActor == actor1 );
+  data.Reset();
+
+  // Make layer1 insensitive, nothing should be hit
+  layer1.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Make layer1 sensitive again, again actor1 will be hit
+  layer1.SetSensitive( true );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.touchedActor == actor1 );
+  data.Reset();
+
+  // Make rootActor insensitive, nothing should be hit
+  rootActor.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Make rootActor sensitive
+  rootActor.SetSensitive( true );
+
+  // Add another layer
+  Layer layer2 ( Layer::New() );
+  layer2.SetSize(100.0f, 100.0f );
+  layer2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  layer2.SetZ( 10.0f ); // Should hit layer2 in this layer rather than actor2
+  Stage::GetCurrent().Add( layer2 );
+
+  Actor actor2 ( Actor::New() );
+  actor2.SetSize(100.0f, 100.0f);
+  actor2.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  layer2.Add( actor2 );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer2 and actor2
+  layer2.TouchedSignal().Connect( &application, functor );
+  actor2.TouchedSignal().Connect( &application, functor );
+
+  // Emit an event, should hit layer2
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+  data.Reset();
+
+  // Make layer2 insensitive, should hit actor1
+  layer2.SetSensitive( false );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.touchedActor == actor1 );
+  data.Reset();
+
+  // Make layer2 sensitive again, should hit layer2
+  layer2.SetSensitive( true );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  //DALI_TEST_CHECK( data.touchedActor == layer2 ); // TODO: Uncomment this after removing renderable hack!
+  data.Reset();
+
+  // Make layer2 invisible, render and notify
+  layer2.SetVisible( false );
+  application.SendNotification();
+  application.Render();
+
+  // Should hit actor1
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( data.touchedActor == actor1 );
+  data.Reset();
+
+  // Make rootActor invisible, render and notify
+  rootActor.SetVisible( false );
+  application.SendNotification();
+  application.Render();
+
+  // Should not hit anything
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchMultipleRenderTasks(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  // Create render task
+  Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+  RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+  renderTask.SetViewport( viewport );
+  renderTask.SetInputEnabled( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure renderTask actor can be hit too.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Disable input on renderTask, should not be hittable
+  renderTask.SetInputEnabled( false );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchMultipleRenderTasksWithChildLayer(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.Add(layer);
+
+  // Create render task
+  Viewport viewport( stageSize.width * 0.5f, stageSize.height * 0.5f, stageSize.width * 0.5f, stageSize.height * 0.5f );
+  RenderTask renderTask ( Stage::GetCurrent().GetRenderTaskList().CreateTask() );
+  renderTask.SetViewport( viewport );
+  renderTask.SetInputEnabled( true );
+  renderTask.SetSourceActor( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+  layer.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Ensure renderTask actor can be hit too.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Disable input on renderTask, should not be hittable
+  renderTask.SetInputEnabled( false );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( viewport.x + 5.0f, viewport.y + 5.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchOffscreenRenderTasks(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  // FrameBufferImage for offscreen RenderTask
+  FrameBufferImage frameBufferImage( FrameBufferImage::New( stageSize.width, stageSize.height, Pixel::RGBA8888 ) );
+
+  // Create an image actor to display the FrameBufferImage
+  ImageActor imageActor ( ImageActor::New( frameBufferImage ) );
+  imageActor.SetParentOrigin(ParentOrigin::CENTER);
+  imageActor.SetSize( stageSize.x, stageSize.y );
+  imageActor.ScaleBy( Vector3(1.0f, -1.0f, 1.0f) ); // FIXME
+  stage.Add( imageActor );
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add( actor );
+  application.GetGlAbstraction().SetCheckFramebufferStatusResult( GL_FRAMEBUFFER_COMPLETE ); // Ensure framebuffer connects
+
+  stage.GetRenderTaskList().GetTask( 0u ).SetScreenToFrameBufferFunction( RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION );
+
+  // Create a RenderTask
+  RenderTask renderTask = stage.GetRenderTaskList().CreateTask();
+  renderTask.SetSourceActor( actor );
+  renderTask.SetTargetFrameBuffer( frameBufferImage );
+  renderTask.SetInputEnabled( true );
+
+  // Create another RenderTask
+  RenderTask renderTask2( stage.GetRenderTaskList().CreateTask() );
+  renderTask2.SetInputEnabled( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
+
+int UtcDaliTouchMultipleRenderableActors(void)
+{
+  TestApplication application;
+  Stage stage ( Stage::GetCurrent() );
+  Vector2 stageSize ( stage.GetSize() );
+
+  ImageActor parent = ImageActor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(parent);
+
+  ImageActor actor = ImageActor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  actor.SetSortModifier( 1.0f );
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to layer's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  parent.TouchedSignal().Connect( &application, functor );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchedActor );
+  END_TEST;
+}
+
+int UtcDaliTouchActorRemovedInSignal(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  RemoveActorFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Register for leave events
+  actor.SetLeaveRequired( true );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Re-add, render and notify
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit another signal outside of actor's area, should not get anything as the scene has changed.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Re-add actor back to stage, render and notify
+  Stage::GetCurrent().Add(actor);
+  application.SendNotification();
+  application.Render();
+
+  // Emit another down event
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Completely delete the actor
+  actor.Reset();
+
+  // Emit event, should not crash and should not receive an event.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 210.0f, 210.0f ) ) );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchActorSignalNotConsumed(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTouchSystemOverlayActor(void)
+{
+  TestApplication application;
+  Dali::Integration::Core& core( application.GetCore() );
+  Dali::Integration::SystemOverlay& systemOverlay( core.GetSystemOverlay() );
+  systemOverlay.GetOverlayRenderTasks().CreateTask();
+
+  // Create an actor and add it to the system overlay.
+  Actor systemActor = Actor::New();
+  systemActor.SetSize(100.0f, 100.0f);
+  systemActor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  systemOverlay.Add( systemActor );
+
+  // Create an actor and add it to the stage as per normal, same position and size as systemActor
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Connect to the touch signals.
+  SignalData data;
+  TouchEventFunctor functor( data );
+  systemActor.TouchedSignal().Connect( &application, functor );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a down signal, the system overlay is drawn last so is at the top, should hit the systemActor.
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( systemActor == data.touchedActor );
+  END_TEST;
+}
+
+int UtcDaliTouchLayerConsumesTouch(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Add a layer to overlap the actor
+  Layer layer = Layer::New();
+  layer.SetSize(100.0f, 100.0f);
+  layer.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add( layer );
+  layer.RaiseToTop();
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a few touch signals
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Set layer to consume all touch
+  layer.SetTouchConsumed( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit the same signals again, should not receive
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Up, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS(false, data.functorCalled, TEST_LOCATION);
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchLeaveActorReadded(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  // Set actor to receive touch-events
+  actor.SetLeaveRequired( true );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit a down and motion
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 11.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Remove actor from stage and add again
+  stage.Remove( actor );
+  stage.Add( actor );
+
+  // Emit a motion within the actor's bounds
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 12.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit a motion outside the actor's bounds
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Motion, Vector2( 200.0f, 200.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Leave, data.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchStencilNonRenderableActor(void)
+{
+  TestApplication application;
+  Stage stage = Stage::GetCurrent();
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stage.Add(actor);
+
+  Actor stencil = Actor::New();
+  stencil.SetSize(50.0f, 50.0f);
+  stencil.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  stencil.SetDrawMode( DrawMode::STENCIL );
+  stage.Add(stencil);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Emit an event within stencil area
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  // Emit an event outside the stencil area but within the actor area, we should have a hit!
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 60.0f, 60.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+
+  END_TEST;
+}
+
+int UtcDaliTouchInterruptedDifferentConsumer(void)
+{
+  TestApplication application;
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  Actor parent = Actor::New();
+  parent.SetSize(100.0f, 100.0f);
+  parent.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(parent);
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  parent.Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's touched signal
+  SignalData data;
+  TouchEventFunctor functor( data, false /* Do not consume */ );
+  actor.TouchedSignal().Connect( &application, functor );
+
+  // Connect to parent's touched signal
+  SignalData parentData;
+  TouchEventFunctor parentFunctor( parentData, false /* Do not consume */ );
+  parent.TouchedSignal().Connect( &application, parentFunctor );
+
+  // Connect to root's touched signal and consume
+  SignalData rootData;
+  TouchEventFunctor rootFunctor( rootData );
+  rootActor.TouchedSignal().Connect( &application, rootFunctor );
+
+  // Emit a down signal
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Down, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( actor == data.touchedActor );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == parentData.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( parent == parentData.touchedActor );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Down, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == rootData.touchEvent.points[0].hitActor );
+  DALI_TEST_CHECK( rootActor == rootData.touchedActor );
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  // Root is now consumer, connect to the touched signal of the parent so that it becomes the consumer
+  SignalData secondData;
+  TouchEventFunctor secondFunctor( secondData /* Consume */ );
+  parent.TouchedSignal().Connect( &application, secondFunctor );
+
+  // Emit an interrupted signal, all three should STILL be called
+  application.ProcessEvent( GenerateSingleTouch( TouchPoint::Interrupted, Vector2( 10.0f, 10.0f ) ) );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, data.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, parentData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, parentData.touchEvent.points[0].state, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( TouchPoint::Interrupted, rootData.touchEvent.points[0].state, TEST_LOCATION );
+  data.Reset();
+  parentData.Reset();
+  rootData.Reset();
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp b/automated-tests/src/dali/utc-Dali-TypeRegistry.cpp
new file mode 100644 (file)
index 0000000..8280e4a
--- /dev/null
@@ -0,0 +1,1749 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <limits>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+#include <dali/integration-api/events/long-press-gesture-event.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/integration-api/events/pinch-gesture-event.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+
+using namespace Dali;
+
+
+namespace
+{
+
+// Stores data that is populated in the callback and will be read by the Test cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled( false ),
+    voidFunctorCalled( false ),
+    receivedGesture( Gesture::Clear ),
+    pressedActor()
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+    voidFunctorCalled = false;
+
+    receivedGesture.numberOfTouches = 0u;
+    receivedGesture.screenPoint = Vector2(0.0f, 0.0f);
+    receivedGesture.localPoint = Vector2(0.0f, 0.0f);
+
+    pressedActor.Reset();
+  }
+
+  bool functorCalled;
+  bool voidFunctorCalled;
+  LongPressGesture receivedGesture;
+  Actor pressedActor;
+};
+
+// Functor that sets the data when called
+struct GestureReceivedFunctor
+{
+  GestureReceivedFunctor(SignalData& data) : signalData(data) { }
+
+  void operator()(Actor actor, LongPressGesture longPress)
+  {
+    signalData.functorCalled = true;
+    signalData.receivedGesture = longPress;
+    signalData.pressedActor = actor;
+  }
+
+  void operator()()
+  {
+    signalData.voidFunctorCalled = true;
+  }
+
+  SignalData& signalData;
+};
+
+// Generate a LongPressGestureEvent to send to Core
+Integration::LongPressGestureEvent GenerateLongPress(
+    Gesture::State state,
+    unsigned int numberOfTouches,
+    Vector2 point)
+{
+  Integration::LongPressGestureEvent longPress( state );
+
+  longPress.numberOfTouches = numberOfTouches;
+  longPress.point = point;
+
+  return longPress;
+}
+
+// Generate a PanGestureEvent to send to Core
+Integration::PanGestureEvent GeneratePan(
+    Gesture::State state,
+    Vector2 previousPosition,
+    Vector2 currentPosition,
+    unsigned long timeDelta,
+    unsigned int numberOfTouches = 1,
+    unsigned int time = 1u)
+{
+  Integration::PanGestureEvent pan(state);
+
+  pan.previousPosition = previousPosition;
+  pan.currentPosition = currentPosition;
+  pan.timeDelta = timeDelta;
+  pan.numberOfTouches = numberOfTouches;
+  pan.time = time;
+
+  return pan;
+}
+// Generate a PinchGestureEvent to send to Core
+Integration::PinchGestureEvent GeneratePinch(
+    Gesture::State state,
+    float scale,
+    float speed,
+    Vector2 centerpoint)
+{
+  Integration::PinchGestureEvent pinch(state);
+
+  pinch.scale = scale;
+  pinch.speed = speed;
+  pinch.centerPoint = centerpoint;
+
+  return pinch;
+}
+// Generate a TapGestureEvent to send to Core
+Integration::TapGestureEvent GenerateTap(
+    Gesture::State state,
+    unsigned int numberOfTaps,
+    unsigned int numberOfTouches,
+    Vector2 point)
+{
+  Integration::TapGestureEvent tap( state );
+
+  tap.numberOfTaps = numberOfTaps;
+  tap.numberOfTouches = numberOfTouches;
+  tap.point = point;
+
+  return tap;
+}
+
+//
+// Create function as Init function called
+//
+static bool CreateCustomInitCalled = false;
+BaseHandle CreateCustomInit(void)
+{
+  CreateCustomInitCalled = true;
+  return BaseHandle();
+}
+
+static bool CreateCustomNamedInitCalled = false;
+BaseHandle CreateCustomNamedInit(void)
+{
+  CreateCustomNamedInitCalled = true;
+  return BaseHandle();
+}
+
+const std::string scriptedName("PopupStyle");
+static TypeRegistration scriptedType( scriptedName, typeid(Dali::CustomActor), CreateCustomNamedInit );
+
+// Property Registration
+bool setPropertyCalled = false;
+bool getPropertyCalled = false;
+void SetProperty( BaseObject* object, Property::Index propertyIndex, const Property::Value& value )
+{
+  setPropertyCalled = true;
+}
+Property::Value GetProperty( BaseObject* object, Property::Index propertyIndex )
+{
+  getPropertyCalled = true;
+  return Property::Value( true );
+}
+
+
+
+/*******************************************************************************
+ *
+ * Custom Actor
+ *
+ ******************************************************************************/
+namespace Impl
+{
+struct MyTestCustomActor : public CustomActorImpl
+{
+  typedef Signal< void ()> SignalType;
+  typedef Signal< void (float)> SignalTypeFloat;
+
+  MyTestCustomActor() : CustomActorImpl( ActorFlags( REQUIRES_TOUCH_EVENTS ) )
+  { }
+
+  virtual ~MyTestCustomActor()
+  { }
+
+  void ResetCallStack()
+  {
+  }
+
+  // From CustomActorImpl
+  virtual void OnStageConnection( int depth )
+  {
+  }
+  virtual void OnStageDisconnection()
+  {
+  }
+  virtual void OnChildAdd(Actor& child)
+  {
+  }
+  virtual void OnChildRemove(Actor& child)
+  {
+  }
+  virtual void OnSizeSet(const Vector3& targetSize)
+  {
+  }
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+  {
+  }
+  virtual bool OnTouchEvent(const TouchEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnHoverEvent(const HoverEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnWheelEvent(const WheelEvent& event)
+  {
+    return true;
+  }
+  virtual bool OnKeyEvent(const KeyEvent& event)
+  {
+    return true;
+  }
+  virtual void OnKeyInputFocusGained()
+  {
+  }
+  virtual void OnKeyInputFocusLost()
+  {
+  }
+  virtual Vector3 GetNaturalSize()
+  {
+    return Vector3( 0.0f, 0.0f, 0.0f );
+  }
+
+  virtual float GetHeightForWidth( float width )
+  {
+    return 0.0f;
+  }
+
+  virtual float GetWidthForHeight( float height )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+  }
+
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+  {
+  }
+
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+  }
+
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return 0.0f;
+  }
+
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+  }
+
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS )
+  {
+    return false;
+  }
+
+public:
+
+  SignalType mSignal;
+};
+
+}; // namespace Impl
+
+class MyTestCustomActor : public CustomActor
+{
+public:
+
+  typedef Signal< void ()> SignalType;
+  typedef Signal< void (float)> SignalTypeFloat;
+
+  MyTestCustomActor()
+  {
+  }
+
+  static MyTestCustomActor New()
+  {
+    Impl::MyTestCustomActor* p = new Impl::MyTestCustomActor;
+    return MyTestCustomActor( *p ); // takes ownership
+  }
+
+  virtual ~MyTestCustomActor()
+  {
+  }
+
+  static MyTestCustomActor DownCast( BaseHandle handle )
+  {
+    MyTestCustomActor result;
+
+    CustomActor custom = Dali::CustomActor::DownCast( handle );
+    if ( custom )
+    {
+      CustomActorImpl& customImpl = custom.GetImplementation();
+
+      Impl::MyTestCustomActor* impl = dynamic_cast<Impl::MyTestCustomActor*>(&customImpl);
+
+      if (impl)
+      {
+        result = MyTestCustomActor(customImpl.GetOwner());
+      }
+    }
+
+    return result;
+  }
+
+  SignalType& GetCustomSignal()
+  {
+    Dali::RefObject& obj = GetImplementation();
+    return static_cast<Impl::MyTestCustomActor&>( obj ).mSignal;
+  }
+
+private:
+
+  MyTestCustomActor(Internal::CustomActor* internal)
+  : CustomActor(internal)
+  {
+  }
+
+  MyTestCustomActor( Impl::MyTestCustomActor& impl )
+  : CustomActor( impl )
+  {
+  }
+};
+
+
+class MyTestCustomActor2 : public CustomActor
+{
+public:
+
+  MyTestCustomActor2()
+  {
+  }
+
+  static MyTestCustomActor2 New()
+  {
+    return MyTestCustomActor2(); // takes ownership
+  }
+
+  virtual ~MyTestCustomActor2()
+  {
+  }
+
+  static MyTestCustomActor2 DownCast( BaseHandle handle )
+  {
+    MyTestCustomActor2 result;
+
+    CustomActor custom = Dali::CustomActor::DownCast( handle );
+    if ( custom )
+    {
+      CustomActorImpl& customImpl = custom.GetImplementation();
+
+      Impl::MyTestCustomActor* impl = dynamic_cast<Impl::MyTestCustomActor*>(&customImpl);
+
+      if (impl)
+      {
+        result = MyTestCustomActor2(customImpl.GetOwner());
+      }
+    }
+
+    return result;
+  }
+
+private:
+
+  MyTestCustomActor2(Internal::CustomActor* internal)
+  : CustomActor(internal)
+  {
+  }
+
+  MyTestCustomActor2( Impl::MyTestCustomActor& impl )
+  : CustomActor( impl )
+  {
+  }
+};
+
+static TypeRegistration customTypeInit( typeid(MyTestCustomActor2), typeid(Dali::CustomActor), CreateCustomInit, true );
+
+
+BaseHandle CreateCustom(void)
+{
+  return MyTestCustomActor::New();
+}
+
+static std::string lastSignalConnectionCustom;
+
+bool DoConnectSignalCustom( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  lastSignalConnectionCustom = signalName;
+
+  bool connected( true );
+
+  Dali::BaseHandle handle(object);
+  MyTestCustomActor customActor = MyTestCustomActor::DownCast(handle);
+
+  if( "sig1" == signalName )
+  {
+    customActor.GetCustomSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+bool DoConnectSignalCustomFailure( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  lastSignalConnectionCustom = "failed";
+
+  return false; // This is supposed to fail
+}
+
+struct CustomTestFunctor
+{
+  CustomTestFunctor()
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  CustomTestFunctor( const CustomTestFunctor& copyMe )
+  {
+    ++mTotalInstanceCount;
+    ++mCurrentInstanceCount;
+  }
+
+  ~CustomTestFunctor()
+  {
+    --mCurrentInstanceCount;
+  }
+
+  void operator()()
+  {
+    ++mCallbackCount;
+  }
+
+  static int mTotalInstanceCount;
+  static int mCurrentInstanceCount;
+  static int mCallbackCount;
+};
+
+int CustomTestFunctor::mTotalInstanceCount = 0;
+int CustomTestFunctor::mCurrentInstanceCount = 0;
+int CustomTestFunctor::mCallbackCount = 0;
+
+static void ResetFunctorCounts()
+{
+  CustomTestFunctor::mTotalInstanceCount   = 0;
+  CustomTestFunctor::mCurrentInstanceCount = 0;
+  CustomTestFunctor::mCallbackCount        = 0;
+}
+
+static std::string lastActionCustom;
+bool DoActionCustom(BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/)
+{
+  lastActionCustom = actionName;
+  return true;
+}
+
+// Custom type registration
+static TypeRegistration customType1( typeid(MyTestCustomActor), typeid(Dali::CustomActor), CreateCustom );
+
+// Custom signals
+static SignalConnectorType customSignalConnector1( customType1, "sig1", DoConnectSignalCustom );
+static SignalConnectorType customSignalConnector2( customType1, "sig2", DoConnectSignalCustomFailure );
+static const int TEST_SIGNAL_COUNT = 2;
+
+// Custom actions
+static TypeAction customAction1( customType1, "act1", DoActionCustom);
+static const int TEST_ACTION_COUNT = 1;
+
+class TestConnectionTracker : public ConnectionTracker
+{
+public:
+
+  TestConnectionTracker()
+  {
+  }
+};
+
+BaseHandle CreateNamedActorType()
+{
+  Actor actor = Actor::New();
+  actor.SetName( "NamedActor" );
+  return actor;
+}
+
+TypeRegistration namedActorType( "MyNamedActor", typeid(Dali::Actor), CreateNamedActorType );
+PropertyRegistration namedActorPropertyOne( namedActorType, "prop-name", PROPERTY_REGISTRATION_START_INDEX, Property::BOOLEAN, &SetProperty, &GetProperty );
+
+} // Anonymous namespace
+
+// Note: No negative test case for UtcDaliTypeRegistryGet can be implemented.
+int UtcDaliTypeRegistryGetP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+  DALI_TEST_CHECK( registry );
+
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryConstructor can be implemented.
+int UtcDaliTypeRegistryConstructorP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry;
+  DALI_TEST_CHECK( !registry );
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryCopyConstructor can be implemented.
+int UtcDaliTypeRegistryCopyConstructorP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+  DALI_TEST_CHECK( registry );
+
+  TypeRegistry copy( registry );
+  DALI_TEST_CHECK( copy );
+
+  DALI_TEST_CHECK( registry.GetTypeInfo( "Actor" ).GetName() == copy.GetTypeInfo( "Actor" ).GetName() );
+
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryAssignmentOperator can be implemented.
+int UtcDaliTypeRegistryAssignmentOperatorP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+  DALI_TEST_CHECK( registry );
+
+  TypeRegistry copy = registry;
+  DALI_TEST_CHECK( copy );
+  DALI_TEST_CHECK( registry == copy );
+
+  DALI_TEST_CHECK( registry.GetTypeInfo( "Actor" ).GetName() == copy.GetTypeInfo( "Actor" ).GetName() );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryAssignP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+  TypeRegistry registry2;
+  registry2 = registry;
+  DALI_TEST_CHECK( registry2 );
+
+  DALI_TEST_CHECK( registry2.GetTypeInfo( "Actor" ).GetName() == registry2.GetTypeInfo( "Actor" ).GetName() );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryGetTypeInfoFromTypeNameP(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+
+  TypeInfo type;
+
+  // image actor
+  type = registry.GetTypeInfo( "ImageActor" );
+  DALI_TEST_CHECK( type );
+  DALI_TEST_CHECK( type.GetCreator() );
+  DALI_TEST_CHECK( ImageActor::DownCast( type.GetCreator()() ) );
+  ImageActor ia = ImageActor::DownCast(type.CreateInstance());
+  DALI_TEST_CHECK( ia );
+  Stage::GetCurrent().Add( ia );
+  application.Render();
+
+  // camera actor
+  type = registry.GetTypeInfo( "CameraActor" );
+  DALI_TEST_CHECK( type );
+  CameraActor ca = CameraActor::DownCast(type.CreateInstance());
+  DALI_TEST_CHECK( ca );
+  Stage::GetCurrent().Add( ca );
+  application.Render();
+
+  // animations
+  type = registry.GetTypeInfo( "Animation" );
+  DALI_TEST_CHECK( type );
+  Animation an = Animation::DownCast(type.CreateInstance());
+  DALI_TEST_CHECK( an );
+  an.Play();
+  application.Render();
+
+  // shader effect
+  type = registry.GetTypeInfo( "ShaderEffect" );
+  DALI_TEST_CHECK( type );
+  ShaderEffect ef = ShaderEffect::DownCast(type.CreateInstance());
+  DALI_TEST_CHECK( ef );
+  application.Render();
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryGetTypeInfoFromTypeNameN(void)
+{
+  TestApplication application;
+
+  TypeRegistry registry = TypeRegistry::Get();
+
+  TypeInfo type;
+
+  type = registry.GetTypeInfo( "MyDummyActor" );
+  DALI_TEST_CHECK( !type );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryGetTypeInfoFromTypeIdP(void)
+{
+  TypeInfo named_type = TypeRegistry::Get().GetTypeInfo( "ImageActor" );
+  TypeInfo typeinfo_type = TypeRegistry::Get().GetTypeInfo( typeid(Dali::ImageActor) );
+
+  DALI_TEST_CHECK( named_type );
+  DALI_TEST_CHECK( typeinfo_type );
+
+  // Check named and typeid are equivalent
+  DALI_TEST_CHECK( named_type == typeinfo_type );
+
+  DALI_TEST_CHECK( named_type.GetName() == typeinfo_type.GetName() );
+  DALI_TEST_CHECK( named_type.GetBaseName() == typeinfo_type.GetBaseName() );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryGetTypeInfoFromTypeIdN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(Vector2) );
+  DALI_TEST_CHECK( !typeInfo );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryGetTypeNameCountP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  TypeInfo type;
+
+  for(size_t i = 0; i < typeRegistry.GetTypeNameCount(); i++)
+  {
+    type = typeRegistry.GetTypeInfo( typeRegistry.GetTypeName(i) );
+    DALI_TEST_CHECK( type );
+  }
+
+  END_TEST;
+}
+
+
+int UtcDaliTypeRegistryGetTypeNamesP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+  TypeInfo type;
+
+  for(size_t i = 0; i < typeRegistry.GetTypeNameCount(); i++)
+  {
+    type = typeRegistry.GetTypeInfo( typeRegistry.GetTypeName(i) );
+    DALI_TEST_CHECK( type );
+  }
+
+  END_TEST;
+}
+
+
+// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented.
+int UtcDaliTypeRegistryTypeRegistrationNotCallingCreateOnInitP(void)
+{
+  ResetFunctorCounts();
+
+  TestApplication application;
+
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" );
+  DALI_TEST_CHECK( type );
+
+  TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( "CustomActor" );
+  DALI_TEST_CHECK( baseType );
+
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle );
+  DALI_TEST_CHECK( customHandle );
+
+  DALI_TEST_EQUALS( type.GetActionCount(), TEST_ACTION_COUNT + baseType.GetActionCount(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( type.GetSignalCount(), TEST_SIGNAL_COUNT + baseType.GetSignalCount(), TEST_LOCATION );
+
+  {
+    TestConnectionTracker tracker;
+
+    bool connected = handle.ConnectSignal( &tracker, "sig1", CustomTestFunctor() );
+    DALI_TEST_EQUALS( connected, true, TEST_LOCATION );
+    DALI_TEST_CHECK( lastSignalConnectionCustom == "sig1" );
+    DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION );
+    customHandle.GetCustomSignal().Emit();
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION );
+  }
+  // tracker should automatically disconnect here
+  DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+  // Test that functor is disconnected
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION );
+  customHandle.GetCustomSignal().Emit();
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1/*not incremented*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+  Property::Map attributes;
+  handle.DoAction("act1", attributes);
+  DALI_TEST_CHECK( lastActionCustom == "act1" );
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented.
+int UtcDaliTypeRegistryTypeRegistrationCallingCreateOnInitP(void)
+{
+  TestApplication application;
+
+  DALI_TEST_CHECK( "MyTestCustomActor2" == customTypeInit.RegisteredName() );
+
+  DALI_TEST_CHECK( true == CreateCustomInitCalled );
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor2" );
+  DALI_TEST_CHECK( type );
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryTypeRegistration can be implemented.
+int UtcDaliTypeRegistryTypeRegistrationForNamedTypeP(void)
+{
+  TestApplication application;
+
+  // Create Named Actor Type
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyNamedActor" );
+  DALI_TEST_CHECK( type );
+
+  BaseHandle namedHandle = type.CreateInstance();
+  DALI_TEST_CHECK( namedHandle );
+  Actor namedActor( Actor::DownCast( namedHandle ) );
+  DALI_TEST_CHECK( namedActor );
+
+  DALI_TEST_CHECK( namedActor.GetName() == "NamedActor" );
+  DALI_TEST_CHECK( type.GetName() == "MyNamedActor" );
+  DALI_TEST_CHECK( type.GetBaseName() == "Actor" );
+
+  END_TEST;
+}
+
+// Note: No negative test case for UtcDaliTypeRegistryRegisteredName can be implemented.
+int UtcDaliTypeRegistryRegisteredNameP(void)
+{
+  TestApplication application;
+
+  DALI_TEST_CHECK( scriptedName == scriptedType.RegisteredName() );
+
+  TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( scriptedName );
+  DALI_TEST_CHECK( baseType );
+
+  BaseHandle handle = baseType.CreateInstance();
+
+  DALI_TEST_CHECK( true == CreateCustomNamedInitCalled );
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( scriptedName );
+  DALI_TEST_CHECK( type );
+  END_TEST;
+}
+
+int UtcDaliTypeRegistrySignalConnectorTypeP(void)
+{
+  ResetFunctorCounts();
+
+  TestApplication application;
+
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" );
+  DALI_TEST_CHECK( type );
+
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle );
+  DALI_TEST_CHECK( customHandle );
+
+  {
+    TestConnectionTracker tracker;
+
+    bool connected = handle.ConnectSignal( &tracker, "sig1", CustomTestFunctor() );
+    DALI_TEST_EQUALS( connected, true, TEST_LOCATION );
+    DALI_TEST_CHECK( lastSignalConnectionCustom == "sig1" );
+    DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION );
+
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION );
+    customHandle.GetCustomSignal().Emit();
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 1, TEST_LOCATION );
+  }
+  // tracker should automatically disconnect here
+  DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+  // Test that functor is disconnected
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1, TEST_LOCATION );
+  customHandle.GetCustomSignal().Emit();
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 1/*not incremented*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+  DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistrySignalConnectorTypeN(void)
+{
+  // Test what happens when signal connnector (DoConnectSignalFailure method) returns false
+
+  ResetFunctorCounts();
+
+  TestApplication application;
+
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" );
+  DALI_TEST_CHECK( type );
+
+  TypeInfo baseType = TypeRegistry::Get().GetTypeInfo( "CustomActor" );
+  DALI_TEST_CHECK( baseType );
+
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  MyTestCustomActor customHandle = MyTestCustomActor::DownCast( handle );
+  DALI_TEST_CHECK( customHandle );
+
+  DALI_TEST_EQUALS( type.GetActionCount(), TEST_ACTION_COUNT + baseType.GetActionCount(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( type.GetSignalCount(), TEST_SIGNAL_COUNT + baseType.GetSignalCount(), TEST_LOCATION );
+
+  {
+    TestConnectionTracker tracker;
+
+    bool connected = handle.ConnectSignal( &tracker, "sig2", CustomTestFunctor() );
+    DALI_TEST_EQUALS( connected, false/*This is supposed to fail*/, TEST_LOCATION );
+    DALI_TEST_CHECK( lastSignalConnectionCustom == "failed" );
+    DALI_TEST_EQUALS( CustomTestFunctor::mTotalInstanceCount, 2/*temporary copy + FunctorDelegate copy*/, TEST_LOCATION );
+    DALI_TEST_EQUALS( CustomTestFunctor::mCurrentInstanceCount, 0/*deleted along with FunctorDelegate*/, TEST_LOCATION );
+
+    // Should be a NOOP
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION );
+    customHandle.GetCustomSignal().Emit();
+    DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0/*never called*/, TEST_LOCATION );
+  }
+  // tracker should have nothing to disconnect here
+
+  // Should be a NOOP
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0, TEST_LOCATION );
+  customHandle.GetCustomSignal().Emit();
+  DALI_TEST_EQUALS( CustomTestFunctor::mCallbackCount, 0/*never called*/, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryTypeActionP(void)
+{
+  ResetFunctorCounts();
+
+  TestApplication application;
+
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" );
+  DALI_TEST_CHECK( type );
+
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  Property::Map attributes;
+  DALI_TEST_CHECK( handle.DoAction("act1", attributes) );
+  DALI_TEST_CHECK( lastActionCustom == "act1" );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryTypeActionN(void)
+{
+  ResetFunctorCounts();
+
+  TestApplication application;
+
+  TypeInfo type = TypeRegistry::Get().GetTypeInfo( "MyTestCustomActor" );
+  DALI_TEST_CHECK( type );
+
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+
+  Property::Map attributes;
+  DALI_TEST_CHECK( !handle.DoAction( "unknown-action", attributes ) );
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryPropertyRegistrationP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Check property count before property registration
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+  unsigned int initialPropertyCount( customActor.GetPropertyCount() );
+
+  std::string propertyName( "prop-1" );
+  int propertyIndex( PROPERTY_REGISTRATION_START_INDEX );
+  Property::Type propertyType( Property::BOOLEAN );
+  PropertyRegistration property1( customType1, propertyName, propertyIndex, propertyType, &SetProperty, &GetProperty );
+
+  // Check property count after registration
+  unsigned int postRegistrationPropertyCount( customActor.GetPropertyCount() );
+  DALI_TEST_EQUALS( initialPropertyCount + 1u, postRegistrationPropertyCount, TEST_LOCATION );
+
+  // Add custom property and check property count
+  customActor.RegisterProperty( "custom-prop-1", true );
+  unsigned int customPropertyCount( customActor.GetPropertyCount() );
+  DALI_TEST_EQUALS( postRegistrationPropertyCount + 1u, customPropertyCount, TEST_LOCATION );
+
+  // Set the property, ensure SetProperty called
+  DALI_TEST_CHECK( !setPropertyCalled );
+  customActor.SetProperty( propertyIndex, false );
+  DALI_TEST_CHECK( setPropertyCalled );
+
+  // Get the property, ensure GetProperty called
+  DALI_TEST_CHECK( !getPropertyCalled );
+  (void)customActor.GetProperty< bool >( propertyIndex );
+  DALI_TEST_CHECK( getPropertyCalled );
+
+  // Check the property name
+  DALI_TEST_EQUALS( customActor.GetPropertyName( propertyIndex ), propertyName, TEST_LOCATION );
+  DALI_TEST_EQUALS( typeInfo.GetPropertyName( propertyIndex ), propertyName, TEST_LOCATION );
+
+  // Check the property index
+  DALI_TEST_EQUALS( customActor.GetPropertyIndex( propertyName ), propertyIndex, TEST_LOCATION );
+
+  // Check the property type
+  DALI_TEST_EQUALS( customActor.GetPropertyType( propertyIndex ), propertyType, TEST_LOCATION );
+
+  // Check property count of type-info is 1
+  Property::IndexContainer indices;
+  typeInfo.GetPropertyIndices( indices );
+  DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION );
+
+  // Ensure indices returned from actor and customActor differ by two
+  Actor actor = Actor::New();
+  actor.GetPropertyIndices( indices );
+  unsigned int actorIndices = indices.Size();
+  customActor.GetPropertyIndices( indices );
+  unsigned int customActorIndices = indices.Size();
+  DALI_TEST_EQUALS( actorIndices + 2u, customActorIndices, TEST_LOCATION ); // Custom property + registered property
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryPropertyRegistrationN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Attempt to register a property type out-of-bounds index (less than)
+  try
+  {
+    PropertyRegistration property1( customType1, "prop-name", PROPERTY_REGISTRATION_START_INDEX - 1, Property::BOOLEAN, &SetProperty, &GetProperty );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  // Attempt to register a property type out-of-bounds index (greater than)
+  try
+  {
+    PropertyRegistration property1( customType1, "prop-name", PROPERTY_REGISTRATION_MAX_INDEX + 1, Property::BOOLEAN, &SetProperty, &GetProperty );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryAnimatablePropertyRegistrationP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Check property count before property registration
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+
+  unsigned int customPropertyCount( customActor.GetPropertyCount() );
+
+  // Register animatable property
+  std::string animatablePropertyName( "animatable-prop-1" );
+  int animatablePropertyIndex( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX );
+  Property::Type animatablePropertyType( Property::FLOAT );
+  AnimatablePropertyRegistration animatableProperty1( customType1, animatablePropertyName, animatablePropertyIndex, animatablePropertyType );
+
+  // Check property count after registration
+  DALI_TEST_EQUALS( customPropertyCount + 1u, customActor.GetPropertyCount(), TEST_LOCATION );
+
+  // Set the animatable property value
+  customActor.SetProperty( animatablePropertyIndex, 25.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Check the animatable property value
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyIndex ), 25.0f, TEST_LOCATION );
+
+  // Check the animatable property name
+  DALI_TEST_EQUALS( customActor.GetPropertyName( animatablePropertyIndex ), animatablePropertyName, TEST_LOCATION );
+
+  // Check the animatable property index
+  DALI_TEST_EQUALS( customActor.GetPropertyIndex( animatablePropertyName ), animatablePropertyIndex, TEST_LOCATION );
+
+  // Check the animatable property type
+  DALI_TEST_EQUALS( customActor.GetPropertyType( animatablePropertyIndex ), animatablePropertyType, TEST_LOCATION );
+
+  // Check property count of type-info is 1
+  Property::IndexContainer indices;
+  typeInfo.GetPropertyIndices( indices );
+  DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION );
+
+  // Ensure indices returned from actor and customActor differ by one
+  Actor actor = Actor::New();
+  actor.GetPropertyIndices( indices );
+  unsigned int actorIndices = indices.Size();
+  customActor.GetPropertyIndices( indices );
+  unsigned int customActorIndices = indices.Size();
+  DALI_TEST_EQUALS( actorIndices + 1u, customActorIndices, TEST_LOCATION ); // Custom property + registered property
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryAnimatablePropertyRegistrationN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Attempt to register an animatable property type out-of-bounds index (less than)
+  try
+  {
+    AnimatablePropertyRegistration property1( customType1, "anim-prop-name", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX - 1, Property::BOOLEAN );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  // Attempt to register an animatable property type out-of-bounds index (greater than)
+  try
+  {
+    AnimatablePropertyRegistration property1( customType1, "anim-prop-name", ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX + 1, Property::BOOLEAN );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryAnimatablePropertyComponentRegistrationP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Check property count before property registration
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+
+  unsigned int customPropertyCount( customActor.GetPropertyCount() );
+
+  // Register animatable property
+  std::string animatablePropertyName( "animatable-prop-1" );
+  int animatablePropertyIndex( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX );
+  Property::Type animatablePropertyType( Property::VECTOR2 );
+  AnimatablePropertyRegistration animatableProperty1( customType1, animatablePropertyName, animatablePropertyIndex, animatablePropertyType );
+
+  // Check property count after registration
+  DALI_TEST_EQUALS( customPropertyCount + 1u, customActor.GetPropertyCount(), TEST_LOCATION );
+
+  // Set the animatable property value
+  customActor.SetProperty( animatablePropertyIndex, Vector2(25.0f, 50.0f) );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Check the animatable property value
+  DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(25.0f, 50.0f), TEST_LOCATION );
+
+  // Check the animatable property name
+  DALI_TEST_EQUALS( customActor.GetPropertyName( animatablePropertyIndex ), animatablePropertyName, TEST_LOCATION );
+
+  // Check the animatable property index
+  DALI_TEST_EQUALS( customActor.GetPropertyIndex( animatablePropertyName ), animatablePropertyIndex, TEST_LOCATION );
+
+  // Check the animatable property type
+  DALI_TEST_EQUALS( customActor.GetPropertyType( animatablePropertyIndex ), animatablePropertyType, TEST_LOCATION );
+
+  // Check property count of type-info is 1
+  Property::IndexContainer indices;
+  typeInfo.GetPropertyIndices( indices );
+  DALI_TEST_EQUALS( indices.Size(), 1u, TEST_LOCATION );
+
+  // Register animatable property components
+  std::string animatablePropertyComponentName1( "animatable-prop-1-x" );
+  int animatablePropertyComponentIndex1( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1 );
+  AnimatablePropertyComponentRegistration animatablePropertyComponent1( customType1, animatablePropertyComponentName1, animatablePropertyComponentIndex1, animatablePropertyIndex, 0 );
+
+  std::string animatablePropertyComponentName2( "animatable-prop-1-y" );
+  int animatablePropertyComponentIndex2( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2 );
+  AnimatablePropertyComponentRegistration animatablePropertyComponent2( customType1, animatablePropertyComponentName2, animatablePropertyComponentIndex2, animatablePropertyIndex, 1 );
+
+  // Check property count after registration
+  DALI_TEST_EQUALS( customPropertyCount + 3u, customActor.GetPropertyCount(), TEST_LOCATION );
+
+  // Check the animatable property component value
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 25.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 50.0f, TEST_LOCATION );
+
+  // Set the animatable property component value
+  customActor.SetProperty( animatablePropertyComponentIndex1, 150.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Check the animatable property value
+  DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(150.0f, 50.0f), TEST_LOCATION );
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 150.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 50.0f, TEST_LOCATION );
+
+  // Set the animatable property component value
+  customActor.SetProperty( animatablePropertyComponentIndex2, 225.0f );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Check the animatable property value
+  DALI_TEST_EQUALS( customActor.GetProperty< Vector2 >( animatablePropertyIndex ), Vector2(150.0f, 225.0f), TEST_LOCATION );
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex1 ), 150.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( customActor.GetProperty< float >( animatablePropertyComponentIndex2 ), 225.0f, TEST_LOCATION );
+
+  // Ensure indices returned from actor and customActor differ by three
+  Actor actor = Actor::New();
+  actor.GetPropertyIndices( indices );
+  unsigned int actorIndices = indices.Size();
+  customActor.GetPropertyIndices( indices );
+  unsigned int customActorIndices = indices.Size();
+  DALI_TEST_EQUALS( actorIndices + 3u, customActorIndices, TEST_LOCATION ); // Custom property + registered property
+
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryAnimatablePropertyComponentRegistrationN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Register animatable property with the type of Vector2
+  int animatablePropertyIndex1( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX );
+  AnimatablePropertyRegistration animatableProperty1( customType1, "animatable-prop-1", animatablePropertyIndex1, Property::VECTOR2 );
+
+  // Attempt to register an animatable property component out-of-bounds index (less than)
+  try
+  {
+    AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX - 1, animatablePropertyIndex1, 0 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  // Attempt to register an animatable property component out-of-bounds index (greater than)
+  try
+  {
+    AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX + 1, animatablePropertyIndex1, 0 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )", TEST_LOCATION );
+  }
+
+  // Register an animatable property component
+  AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-1-x", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 1, animatablePropertyIndex1, 0 );
+
+  // Attempt to register another animatable property component with the same component index
+  try
+  {
+    AnimatablePropertyComponentRegistration propertyComponent2( customType1, "animatable-prop-1-y", ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2, animatablePropertyIndex1, 0 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "Property component already registered", TEST_LOCATION );
+  }
+
+  // Register animatable property with the type of boolean
+  int animatablePropertyIndex2( ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2 );
+  AnimatablePropertyRegistration animatableProperty2( customType1, "animatable-prop-2", animatablePropertyIndex2, Property::BOOLEAN );
+
+  // Attempt to register an animatable property component for the above property with boolean type
+  try
+  {
+    AnimatablePropertyComponentRegistration propertyComponent1( customType1, "animatable-prop-2-x", animatablePropertyIndex2 + 1, animatablePropertyIndex2, 0 );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "Base property does not support component", TEST_LOCATION );
+  }
+
+  END_TEST;
+}
+
+
+/*******************************************************************************
+ *
+ * Action through the base handle
+ *
+ ******************************************************************************/
+int UtcDaliTypeRegistryActionViaBaseHandle(void)
+{
+  TestApplication application;
+
+  TypeInfo type;
+
+  type = TypeRegistry::Get().GetTypeInfo( "Actor" );
+  DALI_TEST_CHECK( type );
+
+  BaseHandle hdl = type.CreateInstance();
+  DALI_TEST_CHECK( hdl );
+
+  Actor a = Actor::DownCast(hdl);
+  DALI_TEST_CHECK( a );
+
+  a.SetVisible(false);
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK(!a.IsVisible());
+
+  Property::Map attributes;
+
+  DALI_TEST_CHECK(hdl.DoAction("show", attributes));
+
+  application.SendNotification();
+  application.Render(0);
+  DALI_TEST_CHECK(a.IsVisible());
+
+  DALI_TEST_CHECK(!hdl.DoAction("unknown-action", attributes));
+  END_TEST;
+}
+
+int UtcDaliPropertyRegistrationFunctions(void)
+{
+  TestApplication application;
+  int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 10;
+
+  // Attempt to register a property without a setter
+  try
+  {
+    PropertyRegistration property1( customType1, "prop-name", propertyIndex++, Property::BOOLEAN, NULL, &GetProperty );
+    tet_result( TET_PASS );
+  }
+  catch ( DaliException& e )
+  {
+    tet_result( TET_FAIL );
+  }
+
+  // Attempt to register a property without a getter
+  try
+  {
+    PropertyRegistration property1( customType1, "prop-name", propertyIndex++, Property::BOOLEAN, NULL, NULL );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"GetProperty", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPropertyRegistrationAddSameIndex(void)
+{
+  TestApplication application;
+  int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 100;
+
+  // Add one property with a valid property index
+  PropertyRegistration property1( customType1, "prop-name", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty );
+
+  // Attempt to add another property with the same index
+  try
+  {
+    PropertyRegistration property2( customType1, "prop-name-2", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Property index already added", TEST_LOCATION );
+  }
+
+  int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 100;
+
+  // Add one property with a valid property index
+  AnimatablePropertyRegistration property3( customType1, "anim-prop-name", animatablePropertyIndex, Property::BOOLEAN );
+
+  // Attempt to add another property with the same index
+  try
+  {
+    AnimatablePropertyRegistration property4( customType1, "anim-prop-name-2", animatablePropertyIndex, Property::BOOLEAN );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Property index already added", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliPropertyRegistrationPropertyWritable(void)
+{
+  TestApplication application;
+  int propertyIndex1 = PROPERTY_REGISTRATION_START_INDEX + 200;
+  int propertyIndex2 = PROPERTY_REGISTRATION_START_INDEX + 201;
+
+  // Add two properties, one with SetProperty, one without
+  PropertyRegistration property1( customType1, "prop-name-readwrite", propertyIndex1, Property::BOOLEAN, &SetProperty, &GetProperty );
+  PropertyRegistration property2( customType1, "prop-name-readonly",  propertyIndex2, Property::BOOLEAN, NULL, &GetProperty );
+
+  // Create custom-actor
+  TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+
+  // Check whether properties are writable
+  DALI_TEST_CHECK(   customActor.IsPropertyWritable( propertyIndex1 ) );
+  DALI_TEST_CHECK( ! customActor.IsPropertyWritable( propertyIndex2 ) );
+  END_TEST;
+}
+
+int UtcDaliPropertyRegistrationPropertyAnimatable(void)
+{
+  TestApplication application;
+  int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 400;
+  int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 400;
+
+  // These properties are not animatable
+  PropertyRegistration property1( customType1, "prop-name", propertyIndex, Property::BOOLEAN, &SetProperty, &GetProperty );
+
+  // These properties are animatable
+  AnimatablePropertyRegistration property2( customType1, "anim-prop-name", animatablePropertyIndex, Property::BOOLEAN );
+
+  // Create custom-actor
+  TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+
+  // Check if animatable
+  DALI_TEST_CHECK( ! customActor.IsPropertyAnimatable( propertyIndex ) );
+  DALI_TEST_CHECK( customActor.IsPropertyAnimatable( animatablePropertyIndex ) );
+
+  // Create another instance of custom-actor
+  BaseHandle handle2 = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle2 );
+  Actor customActor2 = Actor::DownCast( handle2 );
+  DALI_TEST_CHECK( customActor2 );
+
+  // Check if animatable
+  DALI_TEST_CHECK( ! customActor2.IsPropertyAnimatable( propertyIndex ) );
+  DALI_TEST_CHECK( customActor2.IsPropertyAnimatable( animatablePropertyIndex ) );
+  END_TEST;
+}
+
+int UtcDaliPropertyRegistrationInvalidGetAndSet(void)
+{
+  TestApplication application;
+  int propertyIndex = PROPERTY_REGISTRATION_START_INDEX + 2000;
+  int animatablePropertyIndex = ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX + 2000;
+
+  // Create custom-actor
+  TypeInfo typeInfo = TypeRegistry::Get().GetTypeInfo( typeid(MyTestCustomActor) );
+  DALI_TEST_CHECK( typeInfo );
+  BaseHandle handle = typeInfo.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  Actor customActor = Actor::DownCast( handle );
+  DALI_TEST_CHECK( customActor );
+
+  // Try to set an index that hasn't been added
+  try
+  {
+    customActor.SetProperty( propertyIndex, true );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION );
+  }
+
+  try
+  {
+    customActor.SetProperty( animatablePropertyIndex, true );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION );
+  }
+
+  // Try to get an index that hasn't been added
+  try
+  {
+    (void) customActor.GetProperty< bool >( propertyIndex );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION );
+  }
+
+  try
+  {
+    (void) customActor.GetProperty< bool >( animatablePropertyIndex );
+    tet_result( TET_FAIL );
+  }
+  catch ( DaliException& e )
+  {
+    DALI_TEST_ASSERT( e, "! \"Cannot find property index", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+
+int UtcDaliLongPressGestureDetectorTypeRegistry(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "LongPressGestureDetector" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  LongPressGestureDetector detector = LongPressGestureDetector::DownCast( handle );
+  DALI_TEST_CHECK( detector );
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.Attach(actor);
+
+  // Connect to signal through type
+  handle.ConnectSignal( &application, "long-press-detected", functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit gesture
+  application.ProcessEvent(GenerateLongPress(Gesture::Possible, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Started, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateLongPress(Gesture::Finished, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPanGestureDetectorTypeRegistry(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "PanGestureDetector" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  PanGestureDetector detector = PanGestureDetector::DownCast( handle );
+  DALI_TEST_CHECK( detector );
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.Attach(actor);
+
+  // Connect to signal through type
+  handle.ConnectSignal( &application, "pan-detected", functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit gesture
+  application.ProcessEvent(GeneratePan(Gesture::Possible, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Started, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  application.ProcessEvent(GeneratePan(Gesture::Finished, Vector2(10.0f, 20.0f), Vector2(20.0f, 20.0f), 10));
+  DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliPinchGestureDetectorTypeRegistry(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "PinchGestureDetector" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  PinchGestureDetector detector = PinchGestureDetector::DownCast( handle );
+  DALI_TEST_CHECK( detector );
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.Attach(actor);
+
+  // Connect to signal through type
+  handle.ConnectSignal( &application, "pinch-detected", functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit gesture
+  application.ProcessEvent(GeneratePinch(Gesture::Started, 10.0f, 50.0f, Vector2(20.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTapGestureDetectorTypeRegistry(void)
+{
+  TestApplication application;
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Register Type
+  TypeInfo type;
+  type = TypeRegistry::Get().GetTypeInfo( "TapGestureDetector" );
+  DALI_TEST_CHECK( type );
+  BaseHandle handle = type.CreateInstance();
+  DALI_TEST_CHECK( handle );
+  TapGestureDetector detector = TapGestureDetector::DownCast( handle );
+  DALI_TEST_CHECK( detector );
+
+  // Attach actor to detector
+  SignalData data;
+  GestureReceivedFunctor functor( data );
+  detector.Attach(actor);
+
+  // Connect to signal through type
+  handle.ConnectSignal( &application, "tap-detected", functor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit gesture
+  application.ProcessEvent(GenerateTap(Gesture::Possible, 1u, 1u, Vector2(50.0f, 10.0f)));
+  application.ProcessEvent(GenerateTap(Gesture::Started, 1u, 1u, Vector2(50.0f, 10.0f)));
+  DALI_TEST_EQUALS(true, data.voidFunctorCalled, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliTypeRegistryNamedType(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  // Create a normal actor
+  BaseHandle actorHandle = typeRegistry.GetTypeInfo( "Actor" ).CreateInstance();
+  DALI_TEST_CHECK( actorHandle );
+  Actor actor( Actor::DownCast( actorHandle ) );
+  DALI_TEST_CHECK( actor );
+  unsigned int actorPropertyCount( actor.GetPropertyCount() );
+
+  // Create Named Actor Type
+  BaseHandle namedHandle = typeRegistry.GetTypeInfo( "MyNamedActor" ).CreateInstance();
+  DALI_TEST_CHECK( namedHandle );
+  Actor namedActor( Actor::DownCast( namedHandle ) );
+  DALI_TEST_CHECK( namedActor );
+  unsigned int namedActorPropertyCount( namedActor.GetPropertyCount() );
+
+  DALI_TEST_CHECK( namedActorPropertyCount > actorPropertyCount );
+  END_TEST;
+}
+
+int UtcDaliTypeInfoGetActionNameP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" );
+  DALI_TEST_CHECK( typeInfo );
+
+  DALI_TEST_CHECK( 0 != typeInfo.GetActionCount() );
+
+  std::string name = typeInfo.GetActionName(0);
+
+  DALI_TEST_EQUALS( name, "show", TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTypeInfoGetActionNameN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" );
+  DALI_TEST_CHECK( typeInfo );
+
+  DALI_TEST_CHECK( 0 != typeInfo.GetActionCount() );
+
+  std::string name = typeInfo.GetActionName(std::numeric_limits<size_t>::max());
+
+  DALI_TEST_EQUALS( 0u, name.size(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTypeInfoGetSignalNameP(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" );
+  DALI_TEST_CHECK( typeInfo );
+
+  DALI_TEST_CHECK( 0 != typeInfo.GetSignalCount() );
+
+  std::string name = typeInfo.GetSignalName(0);
+
+  DALI_TEST_EQUALS( name, "touched", TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliTypeInfoGetSignalNameN(void)
+{
+  TestApplication application;
+  TypeRegistry typeRegistry = TypeRegistry::Get();
+
+  TypeInfo typeInfo = typeRegistry.GetTypeInfo( "Actor" );
+  DALI_TEST_CHECK( typeInfo );
+
+  DALI_TEST_CHECK( 0 != typeInfo.GetSignalCount() );
+
+  std::string name = typeInfo.GetSignalName(std::numeric_limits<size_t>::max());
+
+  DALI_TEST_EQUALS( 0u, name.size(), TEST_LOCATION );
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Uint16Pair.cpp b/automated-tests/src/dali/utc-Dali-Uint16Pair.cpp
new file mode 100644 (file)
index 0000000..d372a2b
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+
+int UtcDaliUint16PairConstructor01P(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v;
+
+  DALI_TEST_EQUALS(v.GetX(), 0u, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.GetY(), 0u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairConstructor02P(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(10,10);
+
+  DALI_TEST_EQUALS(v.GetX(), 10u, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.GetY(), 10u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairCopyConstructor01P(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair u(5,5);
+  Uint16Pair v(u);
+  DALI_TEST_EQUALS(v.GetX(), 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.GetY(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairGetWidthP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  DALI_TEST_EQUALS(v.GetWidth(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairGetHeightP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  DALI_TEST_EQUALS(v.GetHeight(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairGetXP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  DALI_TEST_EQUALS(v.GetX(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairGetYP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  DALI_TEST_EQUALS(v.GetY(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairEqualsP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  Uint16Pair u(5,5);
+  DALI_TEST_EQUALS(v == u, true, TEST_LOCATION);
+
+  v = Uint16Pair(5,4);
+  u = Uint16Pair(5,5);
+  DALI_TEST_EQUALS(v == u, false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairNotEqualsP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair v(5,5);
+  Uint16Pair u(5,5);
+  DALI_TEST_EQUALS(v != u, false, TEST_LOCATION);
+
+  v = Uint16Pair(5,4);
+  u = Uint16Pair(5,5);
+  DALI_TEST_EQUALS(v != u, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairLessThanP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair u(5,5);
+  Uint16Pair v(6,6);
+  DALI_TEST_EQUALS(u < v, true, TEST_LOCATION);
+
+  u = Uint16Pair(0,1);
+  v = Uint16Pair(1,0);
+  DALI_TEST_EQUALS(v < u, true, TEST_LOCATION);
+
+  u = Uint16Pair(1,0);
+  v = Uint16Pair(0,1);
+  DALI_TEST_EQUALS(v < u, false, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairGreaterThanP(void)
+{
+  Dali::TestApplication testApp;
+
+  Uint16Pair u;
+  Uint16Pair v;
+
+  u = Uint16Pair(0,1);
+  v = Uint16Pair(1,0);
+  DALI_TEST_EQUALS(u > v, true, TEST_LOCATION);
+
+  u = Uint16Pair(1,0);
+  v = Uint16Pair(0,1);
+  DALI_TEST_EQUALS(v > u, true, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairFromFloatVecP(void)
+{
+  Dali::TestApplication testApp;
+
+  Dali::Vector2 v2(5.f, 5.f);
+
+  Uint16Pair u = Uint16Pair::FromFloatVec2(v2);
+  DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION);
+
+  Dali::Vector3 v3(5.f, 5.f, 5.f);
+
+  u = Uint16Pair::FromFloatVec2(v3);
+  DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliUint16PairFromFloatArrayP(void)
+{
+  Dali::TestApplication testApp;
+
+  float array[] = {5.f, 5.f};
+
+  Uint16Pair u = Uint16Pair::FromFloatArray(array);
+  DALI_TEST_EQUALS(u.GetX(), 5u, TEST_LOCATION);
+  DALI_TEST_EQUALS(u.GetY(), 5u, TEST_LOCATION);
+
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-Vector.cpp b/automated-tests/src/dali/utc-Dali-Vector.cpp
new file mode 100644 (file)
index 0000000..0cf200d
--- /dev/null
@@ -0,0 +1,1371 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#define ENABLE_VECTOR_ASSERTS
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+const Dali::VectorBase::SizeType ZERO(0);
+}
+
+int UtcDaliEmptyVectorInt(void)
+{
+  tet_infoline("Testing Dali::Vector<int>");
+
+  Vector< int > intvector;
+
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+
+  intvector.Clear();
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+
+  intvector.Release();
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorInt(void)
+{
+  tet_infoline("Testing Dali::Vector<int>");
+
+  Vector< int > intvector;
+
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+
+  intvector.PushBack( 11 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), intvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION );
+
+  intvector.PushBack( 99 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), intvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 99, intvector[ 1 ], TEST_LOCATION );
+
+  intvector.PushBack( 34 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(6), intvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 99, intvector[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 34, intvector[ 2 ], TEST_LOCATION );
+
+  intvector.Clear();
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(6), intvector.Capacity(), TEST_LOCATION );
+  intvector.PushBack( 123 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 123, intvector[ 0 ], TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorIntCopy(void)
+{
+  tet_infoline("Testing Dali::Vector<int>::Copy");
+
+  Vector< int > intvector;
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+
+  intvector.PushBack( 99 );
+  intvector.PushBack( 11 );
+  intvector.PushBack( 34 );
+
+  // copy construct
+  Vector< int > intvector2( intvector );
+
+  DALI_TEST_EQUALS( intvector2.Count(), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( intvector2.Capacity(), intvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( intvector2[ 0 ], intvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( intvector2[ 1 ], intvector[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( intvector2[ 2 ], intvector[ 2 ], TEST_LOCATION );
+
+  // assign
+  Vector< int > intvector3;
+  DALI_TEST_EQUALS( ZERO, intvector3.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector3.Capacity(), TEST_LOCATION );
+  intvector2 = intvector3;
+  DALI_TEST_EQUALS( intvector2.Count(), intvector3.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( intvector2.Capacity(), intvector3.Capacity(), TEST_LOCATION );
+
+  // copy empty
+  Vector< int > intvector4;
+  intvector4.Reserve( 100 );
+  DALI_TEST_EQUALS( ZERO, intvector4.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(100), intvector4.Capacity(), TEST_LOCATION );
+  intvector3 = intvector4;
+  DALI_TEST_EQUALS( ZERO, intvector3.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(100), intvector3.Capacity(), TEST_LOCATION );
+
+  // self copy
+  intvector4 = intvector4;
+  DALI_TEST_EQUALS( ZERO, intvector4.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(100), intvector4.Capacity(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorIntResize(void)
+{
+  tet_infoline("Testing Dali::Vector<short>::Resize");
+
+  Vector< short > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+
+  vector.Resize( 10u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(10), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(10), vector.Capacity(), TEST_LOCATION );
+
+  vector.Resize( 4u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(10), vector.Capacity(), TEST_LOCATION );
+
+  vector.Resize( 4u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(10), vector.Capacity(), TEST_LOCATION );
+
+  vector.Resize( 0u );
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(10), vector.Capacity(), TEST_LOCATION );
+
+  vector.Resize( 12u, 123 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(12), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(12), vector.Capacity(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( vector[ 0 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 5 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 6 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 7 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 8 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 9 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 10 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 11 ], 123, TEST_LOCATION );
+
+  vector.Resize( 13u, 321 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(13), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(13), vector.Capacity(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( vector[ 0 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 5 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 6 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 7 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 8 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 9 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 10 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 11 ], 123, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 12 ], 321, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorIntErase(void)
+{
+  tet_infoline("Testing Dali::Vector<short>::Erase");
+
+  Vector< char > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+  vector.PushBack( 1 );
+  vector.PushBack( 2 );
+  vector.PushBack( 3 );
+  vector.PushBack( 4 );
+  vector.PushBack( 5 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(5), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION );
+
+  vector.Erase( vector.Begin() );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 5, TEST_LOCATION );
+
+  Vector< char >::Iterator ret = vector.Erase( std::find( vector.Begin(), vector.End(), 4 ) );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( *ret, 5, TEST_LOCATION );
+
+  // try erasing last
+  vector.PushBack( 99 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 99, TEST_LOCATION );
+  ret = vector.Erase( vector.End() - 1 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION );
+
+  try
+  {
+    // illegal erase, one past the end
+    vector.Erase( vector.End() );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    // illegal erase, one before the begin
+    vector.Erase( vector.Begin() - 1u );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 5, TEST_LOCATION );
+
+  vector.Erase( vector.Begin() + 1 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 5, TEST_LOCATION );
+
+  vector.Erase( vector.Begin() + 1 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+
+  try
+  {
+    // illegal erase, one past the end
+    vector.Erase( vector.Begin() + 1 );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 2, TEST_LOCATION );
+
+  vector.Erase( vector.Begin() );
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+
+  try
+  {
+    // illegal erase, one before the beginning
+    vector.Erase( vector.Begin() - 1 );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector.Begin(), vector.End(), TEST_LOCATION );
+
+  Vector< char >::Iterator endIter = vector.End();
+  for( Vector< char >::Iterator iter = vector.Begin(); iter != endIter; ++iter )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  vector.PushBack( 3 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+
+  vector.Clear();
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector.Begin(), vector.End(), TEST_LOCATION );
+
+  endIter = vector.End();
+  for( Vector< char >::Iterator iter = vector.Begin(); iter != endIter; ++iter )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  // test a vector of pointers
+  Vector< int* > ptrVector;
+  DALI_TEST_EQUALS( ZERO, ptrVector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ptrVector.Begin(), ptrVector.End(), TEST_LOCATION );
+
+  int* pointer = NULL;
+  ptrVector.PushBack( pointer );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), ptrVector.Count(), TEST_LOCATION );
+
+  Vector< int* >::Iterator ptriter = std::find( ptrVector.Begin(), ptrVector.End(), pointer );
+  ptriter = ptrVector.Erase( ptriter );
+  DALI_TEST_EQUALS( ZERO, ptrVector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ptrVector.Begin(), ptrVector.End(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ptrVector.Begin(), ptriter, TEST_LOCATION );
+  END_TEST;
+}
+
+
+int UtcDaliVectorDoubleRemove(void)
+{
+  tet_infoline("Testing Dali::Vector<double>::Remove");
+
+  Vector< double > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+
+  vector.PushBack( 11.1 );
+  vector.PushBack( 22.2 );
+  vector.PushBack( 33.3 );
+  vector.PushBack( 44.4 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 22.2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 33.3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 44.4, TEST_LOCATION );
+
+  Vector< double >::Iterator res = std::find( vector.Begin(), vector.End(), 22.2 );
+  DALI_TEST_EQUALS( 22.2, *res, TEST_LOCATION );
+  vector.Remove( res );
+  res = std::find( vector.Begin(), vector.End(), 22.2 );
+  DALI_TEST_EQUALS( vector.End(), res, TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 44.4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 33.3, TEST_LOCATION );
+
+  vector.Remove( vector.End() - 1 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 11.1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 44.4, TEST_LOCATION );
+
+  vector.Remove( vector.Begin() );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 44.4, TEST_LOCATION );
+
+  try
+  {
+    // illegal erase, one past the end
+    vector.Remove( vector.Begin() + 1 );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 44.4, TEST_LOCATION );
+
+  vector.Remove( vector.Begin() );
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+
+  try
+  {
+    // illegal erase, one before the beginning
+    vector.Remove( vector.Begin() - 1 );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVectorIntSwap(void)
+{
+  tet_infoline("Testing Dali::Vector<int>::Swap");
+
+  Vector< int > intvector;
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+
+  intvector.PushBack( 11 );
+  intvector.PushBack( 22 );
+  intvector.PushBack( 33 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), intvector.Count(), TEST_LOCATION );
+
+  Vector< int > intvector2;
+  DALI_TEST_EQUALS( ZERO, intvector2.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector2.Capacity(), TEST_LOCATION );
+
+  intvector2.Swap( intvector );
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), intvector2.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 11, intvector2[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 22, intvector2[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 33, intvector2[ 2 ], TEST_LOCATION );
+
+  intvector.PushBack( 99 );
+  intvector.PushBack( 88 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), intvector.Count(), TEST_LOCATION );
+
+  intvector.Swap( intvector2 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), intvector2.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 99, intvector2[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 88, intvector2[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 11, intvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 22, intvector[ 1 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( 33, intvector[ 2 ], TEST_LOCATION );
+
+  Vector< int > empty;
+  intvector.Swap( empty );
+  DALI_TEST_EQUALS( ZERO, intvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intvector.Capacity(), TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorIterate(void)
+{
+  tet_infoline("Testing Dali::Vector<float>::Begin");
+
+  Vector< float > floatvector;
+  DALI_TEST_EQUALS( ZERO, floatvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, floatvector.Capacity(), TEST_LOCATION );
+
+  floatvector.PushBack( 0.9f );
+  floatvector.PushBack( 1.1f );
+  floatvector.PushBack( 1.2f );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), floatvector.Count(), TEST_LOCATION );
+
+  Vector< float >::Iterator iter = floatvector.Begin();
+  int index = 0;
+  for( ; iter != floatvector.End(); ++iter, ++index )
+  {
+    std::cout << "value " << *iter << std::endl;
+    DALI_TEST_EQUALS( *iter, floatvector[ index ], TEST_LOCATION );
+  }
+  DALI_TEST_EQUALS( 3, index, TEST_LOCATION );
+
+  iter = std::find( floatvector.Begin(), floatvector.End(), 1.1f );
+  DALI_TEST_EQUALS( 1.1f, *iter, TEST_LOCATION );
+
+  floatvector.Clear();
+  iter = std::find( floatvector.Begin(), floatvector.End(), 1.1f );
+  DALI_TEST_EQUALS( floatvector.End(), iter, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorPair(void)
+{
+  tet_infoline("Testing Dali::Vector< std::pair< int, float > >");
+
+  Vector< std::pair< int, float > > pairvector;
+  DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, pairvector.Capacity(), TEST_LOCATION );
+
+  pairvector.PushBack( std::make_pair( 5, 0.1f ) );
+  pairvector.PushBack( std::make_pair( 3, 0.2f ) );
+  pairvector.PushBack( std::make_pair( 4, 0.3f ) );
+  pairvector.PushBack( std::make_pair( 1, 0.4f ) );
+  pairvector.PushBack( std::make_pair( 2, 0.5f ) );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(5), pairvector.Count(), TEST_LOCATION );
+
+  Vector< std::pair< int, float > >::Iterator iter = pairvector.Begin();
+  int index = 0;
+  for( ; iter != pairvector.End(); ++iter, ++index )
+  {
+    std::cout << "pair " << (*iter).first << ":" << (*iter).second << std::endl;
+    DALI_TEST_EQUALS( (*iter).first, pairvector[ index ].first, TEST_LOCATION );
+    DALI_TEST_EQUALS( (*iter).second, pairvector[ index ].second, TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliVectorAsserts(void)
+{
+  tet_infoline("Testing Dali::Vector< int* > exception handling");
+
+  // empty vector
+  Vector< int* > pointervector;
+  try
+  {
+    int* value = NULL;
+    pointervector[ 1 ] = value;
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "VectorBase::mData", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    int* value = NULL;
+    value = pointervector[ 0 ];
+    (void)value; // to "use" the value
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "VectorBase::mData", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  Vector< int* >::Iterator iter = pointervector.Begin();
+  if( iter != pointervector.End() )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    pointervector.Erase( pointervector.Begin() );
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  iter = pointervector.Begin();
+  if( iter != pointervector.End() )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    pointervector.Remove( pointervector.Begin() );
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "(iterator < End()) && (iterator >= Begin())", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  iter = pointervector.Begin();
+  if( iter != pointervector.End() )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  // reserve 0 space
+  pointervector.Reserve( 0 );
+  iter = pointervector.Begin();
+  if( iter != pointervector.End() )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  // reserve 1 space
+  pointervector.Reserve( 1 );
+  iter = pointervector.Begin();
+  if( iter != pointervector.End() )
+  {
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    int* value = NULL;
+    pointervector[ 1 ] = value;
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "index < VectorBase::Count()", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    int* value = pointervector[ 1 ];
+    (void)value; // to "use" the value
+    tet_printf("Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch(Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "index < VectorBase::Count()", TEST_LOCATION );
+  }
+  catch(...)
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVectorAcidTest(void)
+{
+  tet_infoline("Testing multiple Dali::Vector's");
+
+  // create multiple vectors
+  Vector< std::pair< float, float > > pairvector;
+  DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, pairvector.Capacity(), TEST_LOCATION );
+  Vector< double > doublevector;
+  DALI_TEST_EQUALS( ZERO, doublevector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, doublevector.Capacity(), TEST_LOCATION );
+  Vector< int* > intptrvector;
+  DALI_TEST_EQUALS( ZERO, intptrvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intptrvector.Capacity(), TEST_LOCATION );
+  Vector< Dali::Actor* > actorptrvector;
+  DALI_TEST_EQUALS( ZERO, actorptrvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, actorptrvector.Capacity(), TEST_LOCATION );
+  Vector< long > longvector;
+  DALI_TEST_EQUALS( ZERO, longvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, longvector.Capacity(), TEST_LOCATION );
+  Vector< char > charvector;
+  DALI_TEST_EQUALS( ZERO, charvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, charvector.Capacity(), TEST_LOCATION );
+
+  // add items
+  static unsigned int acidCount = 10000;
+  int* ptr = NULL;
+  for( unsigned int i = 0; i < acidCount; ++i )
+  {
+    ++ptr;
+    pairvector.PushBack( std::make_pair( i, i ) );
+    doublevector.PushBack( (double)i );
+    intptrvector.PushBack( (int*)ptr );
+    actorptrvector.PushBack( (Dali::Actor*)ptr );
+    longvector.PushBack( (long)i );
+    charvector.PushBack( (char)i );
+  }
+  DALI_TEST_EQUALS( acidCount, pairvector.Count(), TEST_LOCATION );
+  std::size_t pairCapacity = pairvector.Capacity();
+  DALI_TEST_EQUALS( acidCount, doublevector.Count(), TEST_LOCATION );
+  std::size_t doubleCapacity = doublevector.Capacity();
+  DALI_TEST_EQUALS( acidCount, intptrvector.Count(), TEST_LOCATION );
+  std::size_t intptrCapacity = intptrvector.Capacity();
+  DALI_TEST_EQUALS( acidCount, actorptrvector.Count(), TEST_LOCATION );
+  std::size_t actorptrCapacity = actorptrvector.Capacity();
+  DALI_TEST_EQUALS( acidCount, longvector.Count(), TEST_LOCATION );
+  std::size_t longCapacity = longvector.Capacity();
+  DALI_TEST_EQUALS( acidCount, charvector.Count(), TEST_LOCATION );
+  std::size_t charCapacity = charvector.Capacity();
+
+  tet_printf("Dali::Vector< pair > capacity after %d pushbacks is %d", acidCount, pairCapacity );
+  tet_printf("Dali::Vector< double > capacity after %d pushbacks is %d", acidCount, doubleCapacity );
+  tet_printf("Dali::Vector< int* > capacity after %d pushbacks is %d", acidCount, intptrCapacity );
+  tet_printf("Dali::Vector< Actor* > capacity after %d pushbacks is %d", acidCount, actorptrCapacity );
+  tet_printf("Dali::Vector< long > capacity after %d pushbacks is %d", acidCount, longCapacity );
+  tet_printf("Dali::Vector< char > capacity after %d pushbacks is %d", acidCount, charCapacity );
+
+  // erase items
+  for( unsigned int i = 0; i < acidCount; ++i )
+  {
+    pairvector.Erase( pairvector.Begin() + ( i % pairvector.Count() ) );
+    doublevector.Erase( doublevector.Begin() + ( i % doublevector.Count() ) );
+    intptrvector.Erase( intptrvector.Begin() + ( i % intptrvector.Count() ) );
+    actorptrvector.Erase( actorptrvector.Begin() + ( i % actorptrvector.Count() ) );
+    longvector.Erase( longvector.Begin() + ( i % longvector.Count() ) );
+    charvector.Erase( charvector.Begin() + ( i % charvector.Count() ) );
+  }
+  DALI_TEST_EQUALS( ZERO, pairvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( pairCapacity, pairvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, doublevector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( doubleCapacity, doublevector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, intptrvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( intptrCapacity, intptrvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, actorptrvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( actorptrCapacity, actorptrvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, longvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( longCapacity, longvector.Capacity(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, charvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( charCapacity, charvector.Capacity(), TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVectorPushBack(void)
+{
+  tet_infoline( "Testing Dali::Vector< int* >PushBack(Element)" );
+
+  Vector<unsigned int> vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+
+  vector.Reserve( 2u );
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, vector.Capacity(), TEST_LOCATION );
+
+  vector.PushBack( 0u );
+  vector.PushBack( 1u );
+  vector.PushBack( 2u );
+
+  DALI_TEST_EQUALS( 3u, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 6u, vector.Capacity(), TEST_LOCATION );
+
+  vector.PushBack( 3u );
+
+  DALI_TEST_EQUALS( 4u, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 6u, vector.Capacity(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( 0u, vector[0u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, vector[1u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, vector[2u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, vector[3u], TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVectorInsert01(void)
+{
+  tet_infoline( "Testing Dali::Vector< int* >Insert(Iterator, Element)" );
+
+  // Test order of array inserted-into:
+  Vector< unsigned int > orderedVector;
+  orderedVector.PushBack( 9u );
+  for( unsigned int i = 8u; i <= 8u; --i )
+  {
+    orderedVector.Insert( orderedVector.Begin(), i );
+    DALI_TEST_EQUALS( 10u - i, orderedVector.Count(), TEST_LOCATION );
+    DALI_TEST_EQUALS( i, orderedVector[0u], TEST_LOCATION );
+  }
+
+  for( unsigned int i = 0u; i < 10u; ++i )
+  {
+    DALI_TEST_EQUALS( i, orderedVector[i], TEST_LOCATION );
+  }
+
+  // Test insertion out of range in non-empty array throws:
+  try
+  {
+    orderedVector.Insert( orderedVector.Begin() + 99u, 99u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf( "Assertion test failed - wrong Exception\n" );
+    tet_result( TET_FAIL );
+  }
+
+  try
+  {
+    orderedVector.Insert( orderedVector.Begin() - 1u, 99u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result( TET_FAIL );
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf( "Assertion test failed - wrong Exception\n" );
+    tet_result( TET_FAIL );
+  }
+
+  // Test insertion part-way through a largish array retains ordering:
+
+  // Build vector with hole in sequence:
+  Vector< unsigned int > longerVector;
+  const unsigned int insertionPoint = 131571u;
+  const unsigned int finalLength = 262143u;
+  for( unsigned int i = 0u; i < insertionPoint; ++i )
+  {
+    longerVector.PushBack( i );
+  }
+  for( unsigned int i = insertionPoint; i < finalLength; ++i )
+  {
+    longerVector.PushBack( i + 1 );
+  }
+
+  // Fill the hole in the sequence:
+  longerVector.Insert( longerVector.Begin() + insertionPoint, insertionPoint );
+
+  // Check the sequence is monotonically increasing by one every time:
+  for( unsigned int i = 0u; i <= finalLength; ++i )
+  {
+    DALI_TEST_EQUALS( i, longerVector[i], TEST_LOCATION );
+  }
+
+  // Insert into an empty vector
+  Vector< unsigned int > vector;
+
+  vector.Insert( vector.End(), orderedVector.Begin(), orderedVector.End() );
+  for( unsigned int i = 0u; i < 10u; ++i )
+  {
+    DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION );
+  }
+
+  vector.Clear();
+  vector.Insert( vector.Begin(), orderedVector.Begin(), orderedVector.End() );
+  for( unsigned int i = 0u; i < 10u; ++i )
+  {
+    DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION );
+  }
+
+  // Insert nothing.
+  vector.Insert( vector.Begin(), orderedVector.Begin(), orderedVector.Begin() );
+  for( unsigned int i = 0u; i < 10u; ++i )
+  {
+    DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION );
+  }
+
+  vector.Insert( vector.Begin() + 5, vector.Begin() + 5, vector.Begin() + 5 );
+  for( unsigned int i = 0u; i < 10u; ++i )
+  {
+    DALI_TEST_EQUALS( i, vector[i], TEST_LOCATION );
+  }
+
+  // AutoInsert
+  vector.Clear();
+  vector.PushBack( 0u );
+  vector.PushBack( 1u );
+  vector.PushBack( 2u );
+  vector.PushBack( 3u );
+
+  vector.Insert( vector.Begin() + 2, vector.Begin(), vector.End() );
+  DALI_TEST_EQUALS( 8u, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( 0u, vector[0u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, vector[1u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 0u, vector[2u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 1u, vector[3u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, vector[4u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, vector[5u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 2u, vector[6u], TEST_LOCATION );
+  DALI_TEST_EQUALS( 3u, vector[7u], TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVectorInsert02(void)
+{
+  tet_infoline("Testing Dali::Vector<char>::Insert(Iterator,Iterator,Iterator)");
+
+  Vector< char > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+  vector.PushBack( 1 );
+  vector.PushBack( 2 );
+  vector.PushBack( 3 );
+  vector.PushBack( 4 );
+  vector.PushBack( 5 );
+
+  Vector< char > vector2;
+  DALI_TEST_EQUALS( ZERO, vector2.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector2.Capacity(), TEST_LOCATION );
+  vector2.PushBack( 6 );
+  vector2.PushBack( 7 );
+  vector2.PushBack( 8 );
+  vector2.PushBack( 9 );
+  vector2.PushBack( 10 );
+
+  // Test insert at end
+  vector.Insert( vector.End(), vector2.Begin(), vector2.Begin() + 1u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(6), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 5 ], 6, TEST_LOCATION );
+
+  // Test insert at begin
+  vector.Insert( vector.Begin(), vector2.Begin()+1, vector2.Begin() + 2u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(7), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 7, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 5 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 6 ], 6, TEST_LOCATION );
+
+  // Test insert in the middle
+  vector.Insert( vector.Begin() + 3, vector2.Begin()+3, vector2.End() );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(9), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 7, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 9, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 10, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 5 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 6 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 7 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 8 ], 6, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVectorIntInsertAssert(void)
+{
+  tet_infoline("Testing Dali::Vector<char>::Insert(Iterator,Iterator,Iterator) asserts");
+
+  Vector< char > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+  vector.PushBack( 1 );
+  vector.PushBack( 2 );
+
+  Vector< char > vector2;
+  DALI_TEST_EQUALS( ZERO, vector2.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector2.Capacity(), TEST_LOCATION );
+  vector2.PushBack( 6 );
+  vector2.PushBack( 7 );
+  vector2.PushBack( 8 );
+  vector2.PushBack( 9 );
+  vector2.PushBack( 10 );
+
+  try
+  {
+    vector.Insert( vector.Begin() +  3u, vector2.Begin(), vector2.End() );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    vector.Insert( vector.Begin() -  1u, vector2.Begin(), vector2.End() );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( at <= End() ) && ( at >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    vector.Insert( vector.End(), vector2.End(), vector2.Begin() );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( from <= to )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+ }
+
+
+int UtcDaliVectorIntEraseRange(void)
+{
+  tet_infoline("Testing Dali::Vector<char>::Erase(Iterator,Iterator)");
+
+  Vector< char > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+
+  // Try to delete from empty vector.
+
+  vector.Erase( vector.Begin(), vector.End() );
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+
+  vector.PushBack( 1 );
+  vector.PushBack( 2 );
+  vector.PushBack( 3 );
+  vector.PushBack( 4 );
+  vector.PushBack( 5 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(5), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 2, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 4 ], 5, TEST_LOCATION );
+
+  Vector< char >::Iterator ret;
+
+  ret = vector.Erase( vector.Begin() + 1u, vector.Begin() + 2u );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 1, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 3, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( *ret, 3, TEST_LOCATION );
+
+  ret = vector.Erase( vector.Begin(), vector.Begin() + 2 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(2), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 5, TEST_LOCATION );
+  DALI_TEST_EQUALS( *ret, 4, TEST_LOCATION );
+
+  // try erasing last
+  vector.PushBack( 99 );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 99, TEST_LOCATION );
+  ret = vector.Erase( vector.Begin() + 1u, vector.End() );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(1), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION );
+
+  // try erasing all
+  vector.PushBack( 100 );
+  vector.PushBack( 101 );
+  vector.PushBack( 102 );
+
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(4), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 4, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 100, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 101, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 3 ], 102, TEST_LOCATION );
+
+  ret = vector.Erase( vector.Begin(), vector.End() );
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(0), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ret, vector.End(), TEST_LOCATION );
+
+  // try erase from Iterator to the same Iterator.
+  vector.PushBack( 100 );
+  vector.PushBack( 101 );
+  vector.PushBack( 102 );
+
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 100, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 101, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 102, TEST_LOCATION );
+
+  ret = vector.Erase( vector.Begin() + 1, vector.Begin() + 1 );
+
+  DALI_TEST_EQUALS( static_cast<Dali::VectorBase::SizeType>(3), vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 0 ], 100, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 1 ], 101, TEST_LOCATION );
+  DALI_TEST_EQUALS( vector[ 2 ], 102, TEST_LOCATION );
+
+  DALI_TEST_EQUALS( *ret, 101, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVectorIntEraseRangeAssert(void)
+{
+  tet_infoline("Testing Dali::Vector<char>::Erase(Iterator,Iterator) asserts");
+
+  Vector< char > vector;
+  DALI_TEST_EQUALS( ZERO, vector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, vector.Capacity(), TEST_LOCATION );
+
+
+  // Add some elements.
+  vector.PushBack( 1 );
+  vector.PushBack( 2 );
+
+  // first out of bounds
+  try
+  {
+    vector.Erase( vector.Begin() + 3u, vector.Begin() + 4u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( first <= End() ) && ( first >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    vector.Erase( vector.Begin() - 1u, vector.End() );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( first <= End() ) && ( first >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  // last out of bounds
+
+  try
+  {
+    vector.Erase( vector.Begin(), vector.Begin() + 3u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( last <= End() ) && ( last >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  try
+  {
+    vector.Erase( vector.Begin(), vector.Begin() - 1u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( last <= End() ) && ( last >= Begin() )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  vector.PushBack( 3 );
+
+  // first > last
+  try
+  {
+    vector.Erase( vector.Begin() + 2u, vector.Begin() + 1u );
+    tet_printf( "Assertion expected, but not occurred at %s\n", TEST_LOCATION );
+    tet_result(TET_FAIL);
+  }
+  catch( Dali::DaliException& e )
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "( first <= last )", TEST_LOCATION );
+  }
+  catch( ... )
+  {
+    tet_printf("Assertion test failed - wrong Exception\n" );
+    tet_result(TET_FAIL);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVectorVector2P(void)
+{
+  tet_infoline("Testing Dali::Vector< Vector2 >");
+
+  Vector< Vector2 > classvector;
+  DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION );
+
+  classvector.PushBack( Vector2() );
+
+  DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION );
+
+  classvector.PushBack( Vector2( 0.1f, 0.2f ) );
+
+  DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Vector2(), classvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector2( 0.1f, 0.2f ), classvector[ 1 ], TEST_LOCATION );
+
+  tet_result(TET_PASS); // for now
+  END_TEST;
+}
+
+int UtcDaliVectorVector3P(void)
+{
+  tet_infoline("Testing Dali::Vector< Vector3 >");
+
+  Vector< Vector3 > classvector;
+  DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION );
+
+  classvector.PushBack( Vector3() );
+
+  DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION );
+
+  classvector.PushBack( Vector3( 0.1f, 0.2f, 0.3f ) );
+
+  DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Vector3(), classvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( Vector3( 0.1f, 0.2f, 0.3f ), classvector[ 1 ], TEST_LOCATION );
+
+  tet_result(TET_PASS); // for now
+  END_TEST;
+}
+
+int UtcDaliVectorMatrixP(void)
+{
+  tet_infoline("Testing Dali::Vector< Matrix >");
+
+  Vector< Matrix > classvector;
+  DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION );
+
+  classvector.PushBack( Matrix() );
+
+  DALI_TEST_EQUALS( 1u, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_GREATER( classvector.Capacity(), ZERO, TEST_LOCATION );
+
+  classvector.PushBack( Matrix::IDENTITY );
+
+  DALI_TEST_EQUALS( 2u, classvector.Count(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( Matrix(), classvector[ 0 ], TEST_LOCATION );
+  DALI_TEST_EQUALS( Matrix::IDENTITY, classvector[ 1 ], TEST_LOCATION );
+
+  tet_result(TET_PASS); // for now
+  END_TEST;
+}
+
+/*
+ * this does not compile at the moment
+ * Vector< Actor > classvector; this does not compile yet either
+ *
+namespace
+{
+
+bool gConstructorCalled = false;
+bool gDestructorCalled = false;
+
+struct ComplexType
+{
+  ComplexType()
+  {
+    gConstructorCalled = true;
+  }
+  ~ComplexType()
+  {
+    gDestructorCalled = true;
+  }
+};
+
+} // anonymous namespace
+
+int UtcDaliVectorComplex( void)
+{
+  tet_infoline("Testing Dali::Vector< ComplexType > ");
+
+  Vector< ComplexType > classvector;
+  DALI_TEST_EQUALS( ZERO, classvector.Count(), TEST_LOCATION );
+  DALI_TEST_EQUALS( ZERO, classvector.Capacity(), TEST_LOCATION );
+
+  DALI_TEST_EQUALS( false, gConstructorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( false, gDestructorCalled, TEST_LOCATION );
+  classvector.PushBack( ComplexType() );
+  DALI_TEST_EQUALS( true, gConstructorCalled, TEST_LOCATION );
+  classvector.Clear();
+  DALI_TEST_EQUALS( true, gDestructorCalled, TEST_LOCATION );
+  tet_result(TET_PASS); // for now
+  END_TEST;
+}
+*/
diff --git a/automated-tests/src/dali/utc-Dali-Vector2.cpp b/automated-tests/src/dali/utc-Dali-Vector2.cpp
new file mode 100644 (file)
index 0000000..822a6ae
--- /dev/null
@@ -0,0 +1,609 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <cmath> // isfinite
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_vector2_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_vector2_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliVector2Constructor01P(void)
+{
+  TestApplication application;
+  Vector2 vec2;
+  DALI_TEST_EQUALS(vec2.x, 0.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 0.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Constructor02P(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Constructor03P(void)
+{
+  TestApplication application;
+  float array[] = {1.f,1.f};
+  Vector2 vec2(array);
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Constructor04P(void)
+{
+  TestApplication application;
+  Vector3 vec3(1.f,1.f,1.f);
+  Vector3 vec2(vec3);
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Constructor05P(void)
+{
+  TestApplication application;
+  Vector4 vec4(1.f,1.f,1.f,1.f);
+  Vector2 vec2(vec4);
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2CopyConstructor01P(void)
+{
+  TestApplication application;
+  float array[] = {1.f,1.f};
+  Vector2 vec2;
+  vec2 = array;
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2CopyConstructor02P(void)
+{
+  TestApplication application;
+  Vector3 vec3(1.f,1.f,1.f);
+  Vector3 vec2;
+  vec2 = vec3;
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2CopyConstructor03P(void)
+{
+  TestApplication application;
+  Vector4 vec4(1.f,1.f,1.f,1.f);
+  Vector3 vec2;
+  vec2 = vec4;
+  DALI_TEST_EQUALS(vec2.x, 1.0f, 0.001, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec2.y, 1.0f, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2AssignP(void)
+{
+  TestApplication application;
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(11.0f, 22.0f);
+
+  v1 = r0;
+  DALI_TEST_EQUALS(v1, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2AssignP02(void)
+{
+  TestApplication application;
+  Vector2 v1(10.0f, 20.0f);
+  Vector4 r0(11.0f, 22.0f, 33.f, 44.f);
+
+  v1 = r0;
+  DALI_TEST_EQUALS(v1, Vector2(r0.x, r0.y), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2AssignP03(void)
+{
+  TestApplication application;
+  Vector2 v1(10.0f, 20.0f);
+  Vector3 r0(11.0f, 22.0f, 33.f);
+
+  v1 = r0;
+  DALI_TEST_EQUALS(v1, Vector2(r0.x, r0.y), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2AddP(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 2.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(11.0f, 22.0f);
+
+  Vector2 v2 = v0+v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2AddAssignP(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 2.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(11.0f, 22.0f);
+
+  v0 += v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2SubtractP(void)
+{
+  TestApplication application;
+  Vector2 v0(11.0f, 22.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(1.0f, 2.0f);
+
+  Vector2 v2 = v0-v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2SubtractAssignP(void)
+{
+  TestApplication application;
+  Vector2 v0(11.0f, 22.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(1.0f, 2.0f);
+
+  v0 -= v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2NegateP(void)
+{
+  TestApplication application;
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(-10.0f, -20.0f);
+
+  Vector2 v2 = -v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Multiply01P(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 3.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(20.0f, 60.0f);
+
+  Vector2 v2 = v0 * v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2Multiply02P(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 3.0f);
+  Vector2 r0(20.0f, 30.0f);
+
+  Vector2 v2 = v0 * 10.f;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2MultiplyAssign01P(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 3.0f);
+  Vector2 v1(10.0f, 20.0f);
+  Vector2 r0(20.0f, 60.0f);
+
+  v0 *= v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2MultiplyAssign02P(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 3.0f);
+  Vector2 r0(20.0f, 30.0f);
+
+  v0 *= 10.f;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2Divide01P(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 1.0f);
+  Vector2 v1(2.0f, 3.0f);
+  Vector2 v2(4.0f, 9.0f);
+
+  DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2Divide02P(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 1.0f);
+  Vector2 v1(3.0f, 3.0f);
+  Vector2 v2(9.0f, 9.0f);
+
+  DALI_TEST_EQUALS( v0/1.f, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/1.f, v1, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/3.f, v0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2DivideAssign01P(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 1.0f);
+  Vector2 v1(2.0f, 3.0f);
+  Vector2 v2(4.0f, 9.0f);
+
+  Vector2 v4(v0);
+  v4 /= v0;
+  DALI_TEST_EQUALS(v4, v0, TEST_LOCATION);
+
+  Vector2 v5(v1);
+  v5 /= v0;
+  DALI_TEST_EQUALS(v5, v1, TEST_LOCATION);
+
+  Vector2 v6(v1);
+  v6 /= v6;
+  DALI_TEST_EQUALS(v6, v0, TEST_LOCATION);
+
+  v2 /= v1;
+  DALI_TEST_EQUALS(v2, v1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2DivideAssign02P(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 1.0f);
+  Vector2 v1(3.0f, 3.0f);
+
+  Vector2 v4(v0);
+  v4 /= 1.f;
+  DALI_TEST_EQUALS(v4, v0, TEST_LOCATION);
+
+  Vector2 v5(v1);
+  v5 /= 1.f;
+  DALI_TEST_EQUALS(v5, v1, TEST_LOCATION);
+
+  Vector2 v6(v1);
+  v6 /= 3.f;
+  DALI_TEST_EQUALS(v6, v0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector2EqualsP(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 2.0f);
+  Vector2 v1(1.0f, 2.0f);
+
+  DALI_TEST_CHECK(v0 == v1);
+
+  END_TEST;
+}
+
+int UtcDaliVector2NotEqualsP(void)
+{
+  TestApplication application;
+  Vector2 v0(1.0f, 2.0f);
+  Vector2 v1(1.0f, 2.0f);
+
+  Vector2 v2 = Vector2(0.0f, 2.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector2(1.0f, 0.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector2(1.0f, 77.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector2(33.0f, 44.0f);
+  DALI_TEST_CHECK(v0 != v2);
+  END_TEST;
+}
+
+int UtcDaliVector2OperatorSubscriptP(void)
+{
+  TestApplication application;
+  Vector2 testVector(1.0f, 2.0f);
+
+  // read array subscripts
+  DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION );
+
+  // write array subscripts/read struct memebers
+  testVector[0] = 3.0f;
+  testVector[1] = 4.0f;
+
+  DALI_TEST_EQUALS( testVector.x, 3.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.y, 4.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVector2OperatorSubscriptN(void)
+{
+  TestApplication application;
+  Vector2 testVector(1.0f, 2.0f);
+
+  try
+  {
+    float& w = testVector[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "Vector element index out of bounds", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVector2OperatorConstSubscriptP(void)
+{
+  TestApplication application;
+  const Vector2 testVector2(3.0f, 4.0f);
+  const float& x = testVector2[0];
+  const float& y = testVector2[1];
+  DALI_TEST_EQUALS( x, 3.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( y, 4.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector2OperatorConstSubscriptN(void)
+{
+  TestApplication application;
+  const Vector2 testVector2(3.0f, 4.0f);
+
+  try
+  {
+    const float& w = testVector2[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "Vector element index out of bounds" , TEST_LOCATION);
+  }
+
+
+  END_TEST;
+}
+
+
+int UtcDaliVector2LengthP(void)
+{
+  TestApplication application;
+  Vector2 v(1.0f, 2.0f);
+  DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y), 0.001f, TEST_LOCATION);
+
+  Vector2 v1(0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2LengthSquaredP(void)
+{
+  TestApplication application;
+  Vector2 v(1.0f, 2.0f);
+  DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y, 0.001f, TEST_LOCATION);
+
+  Vector2 v1(0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2NormalizeP(void)
+{
+  TestApplication application;
+  for (float f=0.0f; f<6.0f; f+=1.0f)
+  {
+    Vector2 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f);
+    v.Normalize();
+    DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliVector2NormalizeN(void)
+{
+  TestApplication application;
+  Vector2 v(0.0f, 0.0f);
+  v.Normalize();
+  DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2ClampVector2P(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Vector2::Clamp( const Vector2& v, const Vector2& min, const Vector2& max )");
+
+  Vector2 v0(2.0f, 0.8f);
+  Vector2 v1(-1.0f, 2.0f);
+  Vector2 v2(10.0f, 5.0f);
+  Vector2 v3(8.0f, 10.0f);
+  Vector2 v4(4.9f, 5.1f);
+  Vector2 min(1.0f, 4.0f);
+  Vector2 max(9.0f, 6.0f);
+
+  v0.Clamp( min, max );
+  v1.Clamp( min, max );
+  v2.Clamp( min, max );
+  v3.Clamp( min, max );
+  v4.Clamp( min, max );
+
+  DALI_TEST_EQUALS( v0, Vector2(2.0f, 4.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v1, Vector2(1.0f, 4.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v2, Vector2(9.0f, 5.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v3, Vector2(8.0f, 6.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v4, Vector2(4.9f, 5.1f), 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector2AsFloatP(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+  float* p = vec2.AsFloat();
+
+  DALI_TEST_EQUALS( p[0], 1.f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( p[1], 1.f, 0.01f, TEST_LOCATION );
+
+  p[0] = 2.f;
+  p[1] = 2.f;
+
+  DALI_TEST_EQUALS( p[0], 2.f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( p[1], 2.f, 0.01f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVector2ConstAsFloatP(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+  const float* p = vec2.AsFloat();
+
+  DALI_TEST_EQUALS( p[0], 1.f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( p[1], 1.f, 0.01f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVector2XWidthP(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+
+  DALI_TEST_EQUALS( vec2.x, 1.f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( vec2.width, 1.f, 0.01f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVector2YHeightP(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+
+  DALI_TEST_EQUALS( vec2.y, 1.f, 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( vec2.height, 1.f, 0.01f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+int UtcDaliVector2OStreamOperatorP(void)
+{
+  TestApplication application;
+  std::ostringstream oss;
+
+  Vector2 vector(1, 2);
+
+  oss << vector;
+
+  std::string expectedOutput = "[1, 2]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliVector2MaxP(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 1.0f);
+  Vector2 v1(1.0f, 2.0f);
+
+  DALI_TEST_EQUALS(Max(v0, v1), Vector2(2.0f, 2.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2MinP(void)
+{
+  TestApplication application;
+  Vector2 v0(2.0f, 1.0f);
+  Vector2 v1(1.0f, 2.0f);
+
+  DALI_TEST_EQUALS(Min(v0, v1), Vector2(1.0f, 1.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector2ClampP(void)
+{
+  TestApplication application;
+  tet_infoline("Testing Dali::Vector2::Clamp( const Vector2& v, const float& min, const float& max )");
+
+  Vector2 v0(2.0f, 0.8f);
+  Vector2 v1(-1.0f, 2.0f);
+
+  DALI_TEST_EQUALS( Clamp( v0, 0.9f, 1.1f ), Vector2(1.1f, 0.9f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( Clamp( v1, 1.0f, 1.0f ), Vector2(1.0f, 1.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( Clamp( v1, 0.0f, 3.0f ), Vector2(0.0f, 2.0f), 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-Vector3.cpp b/automated-tests/src/dali/utc-Dali-Vector3.cpp
new file mode 100644 (file)
index 0000000..f96a7b2
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+#include <cmath> // isfinite
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_vector3_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_vector3_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliVector3Constructor01P(void)
+{
+  TestApplication application;
+  Vector3 va;
+  DALI_TEST_EQUALS(va.x, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Constructor02P(void)
+{
+  TestApplication application;
+  Vector3 va(1.f, 1.f, 1.f);
+  DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Constructor03P(void)
+{
+  TestApplication application;
+  float array [] = {1.f, 1.f, 1.f};
+  Vector3 va(array);
+  DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Constructor04P(void)
+{
+  TestApplication application;
+  Vector2 vec2(1.f,1.f);
+  Vector3 va(vec2);
+  DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Constructor05P(void)
+{
+  TestApplication application;
+  Vector4 vec4(1.f, 1.f, 1.f, 1.f);
+  Vector3 va(vec4);
+  DALI_TEST_EQUALS(va.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 1.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Assign01P(void)
+{
+  TestApplication application;
+  Vector3 v0;
+  const float array[] = { 1.0f, 2.0f, 3.0f };
+  v0 = (const float*)array;
+
+  DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Assign02P(void)
+{
+  TestApplication application;
+  Vector2 vec2_q(1.0f, 2.0f);
+  Vector3 vec3a;
+  vec3a = vec2_q;
+
+  DALI_TEST_EQUALS(vec3a.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec3a.y, 2.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec3a.z, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Assign03P(void)
+{
+  TestApplication application;
+  Vector4 vec4_q(4.0f, 3.0f, 2.0f, 1.0f);
+  Vector3 vec3b;
+  vec3b = vec4_q;
+
+  DALI_TEST_EQUALS(vec3b.x, 4.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec3b.y, 3.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vec3b.z, 2.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Add01P(void)
+{
+  TestApplication application;
+  Vector3 v0(1.0f, 2.0f, 3.0f);
+  Vector3 v1(10.0f, 20.0f, 30.0f);
+  Vector3 r0(11.0f, 22.0f, 33.0f);
+
+  Vector3 v2 = v0+v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector3Add02P(void)
+{
+  TestApplication application;
+  Vector3 v0(1.0f, 2.0f, 3.0f);
+  Vector3 v1(10.0f, 20.0f, 30.0f);
+  Vector3 r0(11.0f, 22.0f, 33.0f);
+
+  v0 += v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector3Subtract01P(void)
+{
+  TestApplication application;
+  Vector3 v0(11.0f, 22.0f, 33.0f);
+  Vector3 v1(10.0f, 20.0f, 30.0f);
+  Vector3 r0(1.0f, 2.0f, 3.0f);
+
+  Vector3 v2 = v0-v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector3Subtract02P(void)
+{
+  TestApplication application;
+  Vector3 v0(11.0f, 22.0f, 33.0f);
+  Vector3 v1(10.0f, 20.0f, 30.0f);
+  Vector3 r0(1.0f, 2.0f, 3.0f);
+
+  v0 -= v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Multiply01P(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 3.0f, 4.0f);
+  Vector3 v1(10.0f, 20.0f,  30.0f);
+  Vector3 r0(20.0f, 60.0f, 120.0f);
+
+  Vector3 v2 = v0 * v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Multiply02P(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 3.0f, 4.0f);
+  Vector3 r0(20.0f, 30.0f, 40.0f);
+  Vector3 v2 = v0 * 10.f;
+  DALI_TEST_EQUALS(v2, r0, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Multiply03P(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 3.0f, 4.0f);
+  Vector3 v1(10.0f, 20.0f,  30.0f);
+  Vector3 r0(20.0f, 60.0f, 120.0f);
+  v0 *= v1;
+  DALI_TEST_EQUALS(v0, r0, 0.001, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Multiply04P(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 3.0f, 4.0f);
+  Vector3 r0(20.0f, 30.0f, 40.0f);
+  v0 *= 10.f;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Multiply05P(void)
+{
+  TestApplication application;
+  Vector3 vec3(Vector3::YAXIS);
+  Quaternion rotation(Radian(Math::PI_2), Vector3::ZAXIS);
+  Vector3 result(-Vector3::XAXIS);
+  vec3 *= rotation;
+  DALI_TEST_EQUALS( vec3, result, 0.001, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector3Divide01P(void)
+{
+  TestApplication application;
+  Vector3 v0(1.0f, 1.0f, 1.0f);
+  Vector3 v1(2.0f, 3.0f, 5.0f);
+  Vector3 v2(4.0f, 9.0f, 25.0f);
+
+  DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector3Divide02P(void)
+{
+  TestApplication application;
+  Vector3 v0(3.0f, 6.0f, 9.0f);
+  Vector3 v1(1.0f, 2.0f, 3.0f);
+  Vector3 r(3.0f, 3.0f, 3.0f);
+  Vector3 v2 = v0 / v1;
+  DALI_TEST_EQUALS(v2, r, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Divide03P(void)
+{
+  TestApplication application;
+  Vector3 v0(3.0f, 6.0f, 9.0f);
+  Vector3 v1(1.0f, 2.0f, 3.0f);
+  Vector3 v2 = v0 / 3.f;
+  DALI_TEST_EQUALS(v2, v1, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Divide04P(void)
+{
+  TestApplication application;
+  Vector3 v0(3.0f, 6.0f, 9.0f);
+  Vector3 v1(1.0f, 1.0f, 1.0f);
+  Vector3 v4(v0);
+  v4 /= v0;
+  DALI_TEST_EQUALS(v4, v1, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3Divide05P(void)
+{
+  TestApplication application;
+  Vector3 v0(3.0f, 6.0f, 9.0f);
+  Vector3 v1(1.0f, 2.0f, 3.0f);
+  Vector3 v4(v0);
+  v4 /= 3.f;
+  DALI_TEST_EQUALS(v4, v1, TEST_LOCATION);
+  END_TEST;
+}
+
+
+int UtcDaliVector3NegateP(void)
+{
+  TestApplication application;
+  Vector3 v1(10.0f, 20.0f, 30.f);
+  Vector3 r0(-10.0f, -20.0f, -30.f);
+
+  Vector3 v2 = -v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3EqualsP(void)
+{
+  TestApplication application;
+  Vector3 v0(1.0f, 2.0f,  3.0f);
+  Vector3 v1(1.0f, 2.0f,  3.0f);
+
+  DALI_TEST_CHECK(v0 == v1);
+  END_TEST;
+}
+
+int UtcDaliVector3NotEqualsP(void)
+{
+  TestApplication application;
+  Vector3 v0(1.0f, 2.0f,  3.0f);
+  Vector3 v1(1.0f, 2.0f,  3.0f);
+  Vector3 v2 = Vector3(0.0f, 2.0f, 3.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector3(1.0f, 0.0f, 3.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector3(1.0f, 2.0f, 0.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector3(11.0f, 22.0f, 33.0f);
+  DALI_TEST_CHECK(v0 != v2);
+  END_TEST;
+}
+
+int UtcDaliVector3OperatorSubscriptP(void)
+{
+  TestApplication application;
+  Vector3 testVector(1.0f, 2.0f, 3.0f);
+
+  // read array subscripts
+  DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[2], 3.0f, TEST_LOCATION );
+
+  // write array subscripts/read struct memebers
+  testVector[0] = 4.0f;
+  testVector[1] = 5.0f;
+  testVector[2] = 6.0f;
+
+  DALI_TEST_EQUALS( testVector.x, 4.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.y, 5.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.z, 6.0f, TEST_LOCATION );
+
+  // write struct members/read array subscripts
+  testVector.x = 7.0f;
+  testVector.y = 8.0f;
+  testVector.z = 9.0f;
+
+  DALI_TEST_EQUALS( testVector[0], 7.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[1], 8.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[2], 9.0f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector3ConstOperatorSubscriptP(void)
+{
+  TestApplication application;
+  Vector3 testVector(1.0f, 2.0f, 3.0f);
+
+  // write struct members/read array subscripts
+  const Vector3 testVector2(1.0f, 2.0f, 3.0f);
+  const float& x = testVector2[0];
+  const float& y = testVector2[1];
+  const float& z ( testVector2[2] );
+
+  DALI_TEST_EQUALS( x, 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( y, 2.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( z, 3.0f, TEST_LOCATION );
+
+  try
+  {
+    float& w = testVector[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "index < 3", TEST_LOCATION );
+  }
+
+  try
+  {
+    const float& w = testVector2[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT(e, "index < 3", TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVector3DotP(void)
+{
+  TestApplication application;
+  DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::YAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::ZAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::XAXIS.Dot(Vector3::XAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::YAXIS.Dot(Vector3::YAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::ZAXIS.Dot(Vector3::ZAXIS), 1.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector3(1.0f, 0.0f, 0.0f).Dot(Vector3(1.0f, 0.0f, 0.0f)), 1.0f, TEST_LOCATION);
+
+  for (float x = 0; x<6.0f; x+=1.0f)
+  {
+    Vector3 v0(cosf(x), sinf(x), 0.0f);
+    Vector3 v1(sinf(x), -cosf(x), 0.0f);
+    DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION);
+
+    v0 = Vector3(cosf(x), 0.0f, sinf(x));
+    v1 = Vector3(sinf(x), 0.0f, -cosf(x));
+    DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION);
+  }
+
+  Vector3 v0 = Vector3(12.0f, 7.0f, 9.0f);
+  v0.Normalize();
+
+  Vector3 v1 = v0 * 2.0f;
+  DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3CrossP(void)
+{
+  TestApplication application;
+  DALI_TEST_EQUALS(Vector3::XAXIS.Cross(Vector3::YAXIS), Vector3::ZAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::YAXIS.Cross(Vector3::ZAXIS), Vector3::XAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::ZAXIS.Cross(Vector3::XAXIS), Vector3::YAXIS, 0.0001f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector3::XAXIS.Cross(Vector3::ZAXIS), -Vector3::YAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::YAXIS.Cross(Vector3::XAXIS), -Vector3::ZAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector3::ZAXIS.Cross(Vector3::YAXIS), -Vector3::XAXIS, 0.0001f, TEST_LOCATION);
+
+  Vector3 v0(2.0f, 3.0f, 4.0f);
+  Vector3 v1(10.0f, 20.0f, 30.0f);
+  Vector3 result(   (v0.y * v1.z) - (v0.z * v1.y),
+                    (v0.z * v1.x) - (v0.x * v1.z),
+                    (v0.x * v1.y) - (v0.y * v1.x) );
+
+
+  DALI_TEST_EQUALS(v0.Cross(v1), result, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3LengthP(void)
+{
+  TestApplication application;
+  Vector3 v(1.0f, 2.0f, 3.0f);
+  DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y + v.z*v.z), 0.001f, TEST_LOCATION);
+
+  Vector3 v1(0.0f, 0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3LengthSquaredP(void)
+{
+  TestApplication application;
+  Vector3 v(1.0f, 2.0f, 3.0f);
+  DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y + v.z*v.z, 0.001f, TEST_LOCATION);
+
+  Vector3 v1(0.0f, 0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3NormalizeP(void)
+{
+  TestApplication application;
+  for (float f=0.0f; f<6.0f; f+=1.0f)
+  {
+    Vector3 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f, cosf(f+2.0f)*10.0f);
+    v.Normalize();
+    DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION);
+  }
+
+  Vector3 v(0.0f, 0.0f, 0.0f);
+  v.Normalize();
+  DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3ClampVector3P(void)
+{
+  TestApplication application;
+
+  Vector3 v0(2.0f, 0.8f, 0.0f);
+  Vector3 v1(-1.0f, 2.0f, 10.0f);
+  Vector3 v2(10.0f, 5.0f, 0.0f);
+  Vector3 v3(8.0f, 10.0f, 5.0f);
+  Vector3 v4(4.9f, 5.1f, 10.0f);
+  Vector3 min(1.0f, 4.0f, 1.5f);
+  Vector3 max(9.0f, 6.0f, 8.0f);
+
+  v0.Clamp( min, max );
+  v1.Clamp( min, max );
+  v2.Clamp( min, max );
+  v3.Clamp( min, max );
+  v4.Clamp( min, max );
+
+  DALI_TEST_EQUALS( v0, Vector3(2.0f, 4.0f, 1.5f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v1, Vector3(1.0f, 4.0f, 8.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v2, Vector3(9.0f, 5.0f, 1.5f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v3, Vector3(8.0f, 6.0f, 5.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v4, Vector3(4.9f, 5.1f, 8.0f), 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector3AsFloatP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  Vector3 v0(values);
+
+  for (int i=0;i<3;++i)
+  {
+    DALI_TEST_EQUALS(v0.AsFloat()[i], values[i], TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVector3ConstAsFloatP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  Vector3 v0(values);
+
+  const Vector3 v1(values);
+  for (int i=0;i<3;++i)
+  {
+    DALI_TEST_EQUALS(v1.AsFloat()[i], values[i], TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliVector3ConstAsVectorXYP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  const Vector3 v0(values);
+  DALI_TEST_EQUALS(v0.GetVectorXY().x, values[0], TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.GetVectorXY().y, values[1], TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3AsVectorXYP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  Vector3 v0(values);
+
+  DALI_TEST_EQUALS(v0.GetVectorXY().x, values[0], TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.GetVectorXY().y, values[1], TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3ConstAsVectorXZP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  const Vector3 v0(values);
+
+  DALI_TEST_EQUALS(v0.GetVectorYZ().x, values[1], TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.GetVectorYZ().y, values[2], TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3AsVectorXZP(void)
+{
+  TestApplication application;
+  float values[] = {0.0f,  1.0f,  2.0f};
+  Vector3 v0(values);
+
+  DALI_TEST_EQUALS(v0.GetVectorYZ().x, values[1], TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.GetVectorYZ().y, values[2], TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3OStreamOperatorP(void)
+{
+  TestApplication application;
+  std::ostringstream oss;
+
+  Vector3 vector(1, 2, 3);
+
+  oss << vector;
+
+  std::string expectedOutput = "[1, 2, 3]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3MinP(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 2.0f, 1.0f);
+  Vector3 v1(1.0f, 1.0f, 2.0f);
+
+  DALI_TEST_EQUALS(Min(v0, v1), Vector3(1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3MaxP(void)
+{
+  TestApplication application;
+  Vector3 v0(2.0f, 1.0f, 3.0f);
+  Vector3 v1(1.0f, 2.0f, 3.0f);
+
+  DALI_TEST_EQUALS(Max(v0, v1), Vector3(2.0f, 2.0f, 3.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector3ClampP(void)
+{
+  TestApplication application;
+  Vector3 v0( 2.0f, 1.0f, 0.0f );
+  Vector3 v1( -1.0f, 2.0f, 1.0f );
+
+  DALI_TEST_EQUALS( Clamp( v0, 0.9f, 1.1f ), Vector3(1.1f, 1.0f, 0.9f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( Clamp( v1, 1.0f, 1.0f ), Vector3(1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector3ConstantsP(void)
+{
+  TestApplication application;
+  Vector3 va = Vector3::ZERO;
+  Vector3 vb = Vector3::ONE;
+  Vector3 vc = Vector3::XAXIS;
+
+  DALI_TEST_EQUALS(va.x, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.y, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(va.z, 0.0f, 0.001f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(vb.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vb.y, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vb.z, 1.0f, 0.001f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(vc.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vc.y, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(vc.z, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
diff --git a/automated-tests/src/dali/utc-Dali-Vector4.cpp b/automated-tests/src/dali/utc-Dali-Vector4.cpp
new file mode 100644 (file)
index 0000000..e83f0d9
--- /dev/null
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <sstream>
+
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+void utc_dali_vector4_startup(void)
+{
+  test_return_value = TET_UNDEF;
+}
+
+void utc_dali_vector4_cleanup(void)
+{
+  test_return_value = TET_PASS;
+}
+
+int UtcDaliVector4Constructor01P(void)
+{
+  Vector4 v;
+  DALI_TEST_EQUALS(v.x, 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.y, 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.z, 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Constructor02P(void)
+{
+  Vector4 v(1.0f, 2.0f, 3.0f, 4.f);
+  DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.w, 4.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Constructor03P(void)
+{
+  float f [] = {1.0f, 2.0f, 3.0f, 4.f};
+  Vector4 v(f);
+  DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.w, 4.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Constructor04P(void)
+{
+  Vector2 vec2(1.f, 2.f);
+  Vector4 v(vec2);
+  DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.z, 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Constructor05P(void)
+{
+  Vector3 vec3(1.f, 2.f, 3.f);
+  Vector4 v(vec3);
+  DALI_TEST_EQUALS(v.x, 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.y, 2.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.z, 3.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v.w, 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Assign01P(void)
+{
+  Vector4 v0;
+  const float array[] = { 1.0f, 2.0f, 3.0f, 4.f };
+  v0 = (const float*)array;
+
+  DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.w, 4.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Assign02P(void)
+{
+  Vector2 vec2(1.f, 2.f);
+  Vector4 v0;
+  v0 = vec2;
+  DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.z, 0.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.z, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Assign03P(void)
+{
+  Vector3 vec3(1.f, 2.f, 3.f);
+  Vector4 v0;
+  v0 = vec3;
+  DALI_TEST_EQUALS(v0.x, 1.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.y, 2.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.z, 3.0f, 0.001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0.w, 0.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Add01P(void)
+{
+  Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f);
+  Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f);
+  Vector4 r0(11.0f, 22.0f, 33.0f, 44.0f);
+
+  Vector4 v2 = v0+v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4Add02P(void)
+{
+  Vector4 v0(1.0f, 2.0f, 3.0f, 4.0f);
+  Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f);
+  Vector4 r0(11.0f, 22.0f, 33.0f, 44.0f);
+
+  v0 += v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Subtract01P(void)
+{
+  Vector4 v0(11.0f, 22.0f, 33.0f, 44.0f);
+  Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f);
+  Vector4 r0(1.0f, 2.0f, 3.0f, 4.0f);
+
+  Vector4 v2 = v0-v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Subtract02P(void)
+{
+  Vector4 v0(11.0f, 22.0f, 33.0f, 44.0f);
+  Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f);
+  Vector4 r0(1.0f, 2.0f, 3.0f, 4.0f);
+
+  v0 -= v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Multiply01P(void)
+{
+  Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f);
+  Vector4 v1(10.0f, 20.0f,  30.0f,  40.0f);
+  Vector4 r0(20.0f, 60.0f, 120.0f, 200.0f);
+
+  Vector4 v2 = v0 * v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4Multiply02P(void)
+{
+  Vector4 v0(2.0f,   4.0f,  8.0f,  16.0f);
+  const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f);
+  Vector4 v2 = v0 * 10.0f;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Multiply03P(void)
+{
+  Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f);
+  Vector4 v1(10.0f, 20.0f,  30.0f,  40.0f);
+  Vector4 r0(20.0f, 60.0f, 120.0f, 200.0f);
+
+  v0 *= v1;
+  DALI_TEST_EQUALS(v0, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Multiply04P(void)
+{
+  Vector4 v0(2.0f,   4.0f,  8.0f,  16.0f);
+  const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f);
+  Vector4 v2(r0);
+  v0 *= 10.0f;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Divide01P(void)
+{
+  Vector4 v0(1.0f, 1.0f, 1.0f, 1.0f);
+  Vector4 v1(2.0f, 3.0f, 5.0f, 7.0f);
+  Vector4 v2(4.0f, 9.0f, 25.0f, 49.0f);
+
+  DALI_TEST_EQUALS( v0/v0, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v0, v1, TEST_LOCATION);
+  DALI_TEST_EQUALS( v1/v1, v0, TEST_LOCATION);
+  DALI_TEST_EQUALS( v2/v1, v1, TEST_LOCATION);
+
+
+  END_TEST;
+}
+
+int UtcDaliVector4Divide02P(void)
+{
+  Vector4 v0(2.0f,   4.0f,  8.0f,  16.0f);
+  const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f);
+  const Vector4 r1(10.0f, 20.0f, 40.0f,  80.0f);
+  const Vector4 r2( 1.0f,  2.0f,  4.0f,   8.0f);
+  const Vector4 r3(2.0f,   4.0f,  8.0f,  16.0f);
+
+  Vector4 v2 = r0 / 10.0f;
+  DALI_TEST_EQUALS(v2, r3, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4Divide03P(void)
+{
+  Vector4 v0(1.0f, 1.0f, 1.0f, 1.0f);
+  Vector4 v1(2.0f, 3.0f, 5.0f, 7.0f);
+  Vector4 v2(4.0f, 9.0f, 25.0f, 49.0f);
+
+  Vector4 v4(v0);
+  v4 /= v0;
+  DALI_TEST_EQUALS(v4, v0, TEST_LOCATION);
+
+  Vector4 v5(v1);
+  v5 /= v0;
+  DALI_TEST_EQUALS(v5, v1, TEST_LOCATION);
+
+  Vector4 v6(v1);
+  v6 /= v6;
+  DALI_TEST_EQUALS(v6, v0, TEST_LOCATION);
+
+  v2 /= v1;
+  DALI_TEST_EQUALS(v2, v1, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4Divide04P(void)
+{
+  Vector4 v0(2.0f,   4.0f,  8.0f,  16.0f);
+  const Vector4 r0(20.0f, 40.0f, 80.0f, 160.0f);
+  const Vector4 r1(10.0f, 20.0f, 40.0f,  80.0f);
+  const Vector4 r2( 1.0f,  2.0f,  4.0f,   8.0f);
+  const Vector4 r3(2.0f,   4.0f,  8.0f,  16.0f);
+
+  Vector4 v2(r0);
+  v2 /= 10.0f;
+  DALI_TEST_EQUALS(v2, r3, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4NegateP(void)
+{
+  TestApplication application;
+  Vector4 v1(10.0f, 20.0f, 30.f, 40.f);
+  Vector4 r0(-10.0f, -20.0f, -30.f, -40.f);
+
+  Vector4 v2 = -v1;
+  DALI_TEST_EQUALS(v2, r0, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4EqualsP(void)
+{
+  Vector4 v0(1.0f, 2.0f,  3.0f, 4.0f);
+  Vector4 v1(1.0f, 2.0f,  3.0f, 4.0f);
+
+  DALI_TEST_CHECK(v0 == v1);
+  END_TEST;
+}
+
+int UtcDaliVector4NotEqualsP(void)
+{
+  Vector4 v0(1.0f, 2.0f,  3.0f, 4.0f);
+  Vector4 v1(1.0f, 2.0f,  3.0f, 4.0f);
+
+  Vector4 v2 = Vector4(0.0f, 2.0f, 3.0f, 4.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector4(1.0f, 0.0f, 3.0f, 4.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector4(1.0f, 2.0f, 0.0f, 4.0f);
+  DALI_TEST_CHECK(v0 != v2);
+
+  v2 = Vector4(1.0f, 2.0f, 3.0f, 0.0f);
+  DALI_TEST_CHECK(v0 != v2);
+  END_TEST;
+}
+
+int UtcDaliVector4OperatorSubscriptP(void)
+{
+  Vector4 testVector(1.0f, 2.0f, 3.0f, 4.0f);
+
+  // read array subscripts
+  DALI_TEST_EQUALS( testVector[0], 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[1], 2.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[2], 3.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[3], 4.0f, TEST_LOCATION );
+
+  // write array subscripts/read struct memebers
+  testVector[0] = 5.0f;
+  testVector[1] = 6.0f;
+  testVector[2] = 7.0f;
+  testVector[3] = 8.0f;
+
+  DALI_TEST_EQUALS( testVector.x, 5.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.y, 6.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.z, 7.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector.w, 8.0f, TEST_LOCATION );
+
+  // write struct members/read array subscripts
+  testVector.x = 9.0f;
+  testVector.y = 10.0f;
+  testVector.z = 11.0f;
+  testVector.w = 12.0f;
+
+  DALI_TEST_EQUALS( testVector[0],  9.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[1], 10.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[2], 11.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( testVector[3], 12.0f, TEST_LOCATION );
+
+  END_TEST;
+}
+
+
+int UtcDaliVector4ConstOperatorSubscriptP(void)
+{
+  Vector4 testVector(1.0f, 2.0f, 3.0f, 4.0f);
+
+  // write struct members/read array subscripts
+  const Vector4 testVector2(1.0f, 2.0f, 3.0f, 4.0f);
+  const float& x = testVector2[0];
+  const float& y = testVector2[1];
+  const float& z ( testVector2[2] );
+  const float& w ( testVector2[3] );
+
+  DALI_TEST_EQUALS( x, 1.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( y, 2.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( z, 3.0f, TEST_LOCATION );
+  DALI_TEST_EQUALS( w, 4.0f, TEST_LOCATION );
+
+  try
+  {
+    float& w = testVector[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "index < 4", TEST_LOCATION );
+  }
+
+  try
+  {
+    const float& w = testVector2[4];
+    if(w==0.0f);
+    tet_result(TET_FAIL);
+  }
+  catch (Dali::DaliException& e)
+  {
+    DALI_TEST_PRINT_ASSERT( e );
+    DALI_TEST_ASSERT( e, "index < 4", TEST_LOCATION );
+  }
+  END_TEST;
+}
+
+int UtcDaliVector4Dot01P(void)
+{
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::YAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::ZAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector4::XAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Dot(Vector4::YAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::ZAXIS.Dot(Vector4::ZAXIS), 1.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot(Vector4(1.0f, 0.0f, 0.0f, 1.0f)), 1.0f, TEST_LOCATION);
+
+  // Test v0 . v0 and v0 . v1 (v1 is always 90 degrees out of phase with v0)
+  for (float x = 0; x<6.0f; x+=1.0f)
+  {
+    // vectors rotating in the XY plane.
+    Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f);
+    Vector4 v1(sinf(x), -cosf(x), 0.0f, 1.0f);
+    DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION);
+
+    // vectors rotating in the XZ plane.
+    v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f);
+    v1 = Vector4(sinf(x), 0.0f, -cosf(x), 0.0f);
+    DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot(v0), 1.0f, 0.0001f, TEST_LOCATION);
+  }
+
+  Vector4 v0 = Vector4(12.0f, 7.0f, 9.0f, 14.0f);
+  v0.Normalize();
+
+  Vector4 v1 = v0 * 2.0f;
+  DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4DotVector302P(void)
+{
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::YAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::ZAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot(Vector3::XAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Dot(Vector3::YAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::ZAXIS.Dot(Vector3::ZAXIS), 1.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot(Vector3(1.0f, 0.0f, 0.0f)), 1.0f, TEST_LOCATION);
+
+  // Test v0 . v0b and v0 . v1 (v1 is always 90 degrees out of phase with v0)
+  for (float x = 0; x<6.0f; x+=1.0f)
+  {
+    // vectors rotating in the XY plane.
+    Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f);
+    Vector3 v0b(cosf(x), sinf(x), 0.0f);
+    Vector3 v1(sinf(x), -cosf(x), 0.0f);
+    DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot(v0b), 1.0f, 0.0001f, TEST_LOCATION);
+
+    // vectors rotating in the XZ plane.
+    v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f);
+    v0b = Vector3(cosf(x), 0.0f, sinf(x));
+    v1 = Vector3(sinf(x), 0.0f, -cosf(x));
+    DALI_TEST_EQUALS(v0.Dot(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot(v0b), 1.0f, 0.0001f, TEST_LOCATION);
+  }
+
+  Vector4 v0 = Vector4(12.0f, 7.0f, 9.0f, 14.0f);
+  v0.Normalize();
+
+  Vector3 v1(v0 * 2.0f);
+  DALI_TEST_EQUALS(v0.Dot(v1), 2.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4Dot4P(void)
+{
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::YAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::ZAXIS), 0.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Dot4(Vector4::ZAXIS), 0.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector4::XAXIS.Dot4(Vector4::XAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Dot4(Vector4::YAXIS), 1.0f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::ZAXIS.Dot4(Vector4::ZAXIS), 1.0f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector4(1.0f, 0.0f, 0.0f, 1.0f).Dot4(Vector4(1.0f, 0.0f, 0.0f, 1.0f)), 2.0f, TEST_LOCATION);
+
+  for (float x = 0; x<6.0f; x+=1.0f)
+  {
+    Vector4 v0(cosf(x), sinf(x), 0.0f, 1.0f);
+    Vector4 v1(sinf(x), -cosf(x), 0.0f, 1.0f);
+    DALI_TEST_EQUALS(v0.Dot4(v1), 1.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot4(v0), 2.0f, 0.0001f, TEST_LOCATION);
+
+    v0 = Vector4(cosf(x), 0.0f, sinf(x), 0.0f);
+    v1 = Vector4(sinf(x), 0.0f, -cosf(x), 0.0f);
+    DALI_TEST_EQUALS(v0.Dot4(v1), 0.0f, 0.0001f, TEST_LOCATION);
+    DALI_TEST_EQUALS(v0.Dot4(v0), 1.0f, 0.0001f, TEST_LOCATION);
+  }
+
+  Vector4 v0(12.0f, 7.0f, 9.0f, 3.0f);
+  v0.Normalize();
+
+  Vector4 v1 = v0 * 2.0f;
+  DALI_TEST_EQUALS(v0.Dot4(v1), 2.0f + 3.0f*6.0f, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4CrossP(void)
+{
+  DALI_TEST_EQUALS(Vector4::XAXIS.Cross(Vector4::YAXIS), Vector4::ZAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Cross(Vector4::ZAXIS), Vector4::XAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::ZAXIS.Cross(Vector4::XAXIS), Vector4::YAXIS, 0.0001f, TEST_LOCATION);
+
+  DALI_TEST_EQUALS(Vector4::XAXIS.Cross(Vector4::ZAXIS), -Vector4::YAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::YAXIS.Cross(Vector4::XAXIS), -Vector4::ZAXIS, 0.0001f, TEST_LOCATION);
+  DALI_TEST_EQUALS(Vector4::ZAXIS.Cross(Vector4::YAXIS), -Vector4::XAXIS, 0.0001f, TEST_LOCATION);
+
+  Vector4 v0(2.0f, 3.0f, 4.0f, 5.0f);
+  Vector4 v1(10.0f, 20.0f, 30.0f, 40.0f);
+  Vector4 result(   (v0.y * v1.z) - (v0.z * v1.y),
+                    (v0.z * v1.x) - (v0.x * v1.z),
+                    (v0.x * v1.y) - (v0.y * v1.x),
+                    0.0f);
+
+  DALI_TEST_EQUALS(v0.Cross(v1), result, 0.001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4LengthP(void)
+{
+  Vector4 v(1.0f, 2.0f, 3.0f, 4.0f);
+  DALI_TEST_EQUALS(v.Length(), sqrtf(v.x*v.x + v.y*v.y + v.z*v.z), 0.001f, TEST_LOCATION);
+
+  Vector4 v1(0.0f, 0.0f, 0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.Length(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4LengthSquaredP(void)
+{
+  Vector4 v(1.0f, 2.0f, 3.0f, 4.0f);
+  DALI_TEST_EQUALS(v.LengthSquared(), v.x*v.x + v.y*v.y + v.z*v.z, 0.001f, TEST_LOCATION);
+
+  Vector4 v1(0.0f, 0.0f, 0.0f, 0.0f);
+  DALI_TEST_EQUALS(v1.LengthSquared(), 0.0f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4NormalizeP(void)
+{
+  for (float f=0.0f; f<6.0f; f+=1.0f)
+  {
+    Vector4 v(cosf(f)*10.0f, cosf(f+1.0f)*10.0f, cosf(f+2.0f)*10.0f, 1.0f);
+    v.Normalize();
+    DALI_TEST_EQUALS(v.LengthSquared(), 1.0f, 0.001f, TEST_LOCATION);
+  }
+
+  Vector4 v(0.0f, 0.0f, 0.0f, 1.0f);
+  v.Normalize();
+  DALI_TEST_EQUALS(v.LengthSquared(), 0.0f, 0.00001f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4ClampVector4P(void)
+{
+  tet_infoline("Testing Dali::Vector4::Clamp( const Vector4& v, const Vector4& min, const Vector4& max )");
+
+  Vector4 v0(2.0f, 0.8f, 0.0f, 5.0f);
+  Vector4 v1(-1.0f, 2.0f, 10.0f, -10.0f);
+  Vector4 v2(10.0f, 5.0f, 0.0f, 10.0f);
+  Vector4 v3(8.0f, 10.0f, 5.0f, -20.0f);
+  Vector4 v4(4.9f, 5.1f, 10.0f, 0.0f);
+
+  Vector4 min(1.0f, -2.0f, -8.0f, -16.0f);
+  Vector4 max(2.0f, 4.0f, 4.0f, -8.0f);
+
+  v0.Clamp( min, max );
+  v1.Clamp( min, max );
+  v2.Clamp( min, max );
+  v3.Clamp( min, max );
+  v4.Clamp( min, max );
+
+  DALI_TEST_EQUALS( v0, Vector4( 2.0f, 0.8f, 0.0f, -8.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v1, Vector4( 1.0f, 2.0f, 4.0f, -10.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v2, Vector4( 2.0f, 4.0f, 0.0f, -8.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v3, Vector4( 2.0f, 4.0f, 4.0f, -16.0f), 0.01f, TEST_LOCATION );
+  DALI_TEST_EQUALS( v4, Vector4( 2.0f, 4.0f, 4.0f, -8.0f), 0.01f, TEST_LOCATION );
+  END_TEST;
+}
+
+int UtcDaliVector4AsFloatP(void)
+{
+  float values[] = {0.0f,  1.0f,  2.0f, 3.0f};
+  Vector4 v0(values);
+
+  for (int i=0;i<4;++i)
+  {
+    DALI_TEST_EQUALS(v0.AsFloat()[i], values[i], TEST_LOCATION);
+  }
+
+  END_TEST;
+}
+
+int UtcDaliVector4ConstAsFloatP(void)
+{
+  float values[] = {0.0f,  1.0f,  2.0f, 3.0f};
+  Vector4 v0(values);
+
+  const Vector4 v1(values);
+  for (int i=0;i<4;++i)
+  {
+    DALI_TEST_EQUALS(v1.AsFloat()[i], values[i], TEST_LOCATION);
+  }
+  END_TEST;
+}
+
+int UtcDaliVector4OStreamOperatorP(void)
+{
+  std::ostringstream oss;
+
+  Vector4 vector(1.0f, 2.0f, 3.0f, 4.0f);
+
+  oss << vector;
+
+  std::string expectedOutput = "[1, 2, 3, 4]";
+
+  DALI_TEST_EQUALS( oss.str(), expectedOutput, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4MaxP(void)
+{
+  Vector4 v0(2.0f, 2.0f, 1.0f, 1.0f);
+  Vector4 v1(1.0f, 1.0f, 2.0f, 2.0f);
+
+  DALI_TEST_EQUALS(Max(v0, v1), Vector4(2.0f, 2.0f, 2.0f, 2.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4MinP(void)
+{
+  Vector4 v0(2.0f, 2.0f, 1.0f, 1.0f);
+  Vector4 v1(1.0f, 1.0f, 2.0f, 2.0f);
+
+  DALI_TEST_EQUALS(Min(v0, v1), Vector4(1.0f, 1.0f, 1.0f, 1.0f), 0.01f, TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliVector4ClampP(void)
+{
+  tet_infoline("Testing Dali::Vector4::Clamp()");
+
+  Vector4 v0(2.0f, 2.0f, -2.0f, -2.0f);
+  DALI_TEST_EQUALS(Clamp(v0, -1.0f, 1.0f), Vector4(1.0f, 1.0f, -1.0f, -1.0f), 0.01f, TEST_LOCATION);
+
+  Vector4 v1(1.0f, 0.0f, 0.0f, -1.0f);
+  DALI_TEST_EQUALS(Clamp(v1, -1.0f, 1.0f), v1, 0.01f, TEST_LOCATION);
+
+  END_TEST;
+}
+
+int UtcDaliVector4ConstantsP(void)
+{
+  float f[] = {2.0f, 3.0f, 4.0f, 5.0f};
+  Vector4 v0(f);
+  Vector4 v1(f[0], f[1], f[2], f[3]);
+  Vector4 v2(v0);
+
+  DALI_TEST_EQUALS(v0, v1, TEST_LOCATION);
+  DALI_TEST_EQUALS(v0, v2, TEST_LOCATION);
+  DALI_TEST_CHECK(v0 == v1);
+  END_TEST;
+}
diff --git a/automated-tests/src/dali/utc-Dali-WheelEvent.cpp b/automated-tests/src/dali/utc-Dali-WheelEvent.cpp
new file mode 100644 (file)
index 0000000..9722454
--- /dev/null
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <iostream>
+#include <stdlib.h>
+#include <dali/public-api/dali-core.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+#include <dali-test-suite-utils.h>
+
+using namespace Dali;
+
+namespace
+{
+
+// Key Event Test references
+const static unsigned int SHIFT_MODIFIER  = 0x1;
+const static unsigned int CTRL_MODIFIER  = 0x2;
+const static unsigned int ALT_MODIFIER  = 0x4;
+const static unsigned int SHIFT_AND_CTRL_MODIFIER  = SHIFT_MODIFIER | CTRL_MODIFIER;
+
+
+// Stores data that is populated in the callback and will be read by the TET cases
+struct SignalData
+{
+  SignalData()
+  : functorCalled(false)
+  {}
+
+  void Reset()
+  {
+    functorCalled = false;
+
+    receivedWheelEvent.type = WheelEvent::MOUSE_WHEEL;
+    receivedWheelEvent.direction = 0;
+    receivedWheelEvent.modifiers = 0;
+    receivedWheelEvent.point = Vector2::ZERO;
+    receivedWheelEvent.z = 0;
+    receivedWheelEvent.timeStamp = 0;
+
+    wheeledActor.Reset();
+  }
+
+  bool functorCalled;
+  WheelEvent receivedWheelEvent;
+  Actor wheeledActor;
+};
+
+// Functor that sets the data when called
+struct WheelEventReceivedFunctor
+{
+  WheelEventReceivedFunctor( SignalData& data ) : signalData( data ) { }
+
+  bool operator()( Actor actor, const WheelEvent& wheelEvent )
+  {
+    signalData.functorCalled = true;
+    signalData.receivedWheelEvent = wheelEvent;
+    signalData.wheeledActor = actor;
+
+    return true;
+  }
+
+  SignalData& signalData;
+};
+
+} // anonymous namespace
+
+int UtcDaliWheelEventConstructor(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);  // coustruct a wheel event
+
+  DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, event.type, TEST_LOCATION); // check type
+  DALI_TEST_EQUALS(1, event.direction, TEST_LOCATION); // check direction
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(Vector2(1.0f, 1.0f), event.point, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1, event.z, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1000u, event.timeStamp, TEST_LOCATION); // check modifier
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliWheelEventIsShiftModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event;
+  DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION);
+
+  event.modifiers = SHIFT_MODIFIER; // Set to Shift Modifier
+
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsShiftModifier(), TEST_LOCATION); // check IsShiftModifier
+
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliWheelEventIsCtrlModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event;
+  DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION);
+
+  event.modifiers = CTRL_MODIFIER; // Set to Ctrl Modifier
+
+  DALI_TEST_EQUALS(CTRL_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier(), TEST_LOCATION); // check IsCtrlModifier
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliWheelEventIsAltModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event;
+  DALI_TEST_EQUALS(0u, event.modifiers, TEST_LOCATION);
+
+  event.modifiers = ALT_MODIFIER; // Set to Alt Modifier
+
+  DALI_TEST_EQUALS(ALT_MODIFIER, event.modifiers, TEST_LOCATION); // check able to set
+
+  DALI_TEST_EQUALS(true, event.IsAltModifier(), TEST_LOCATION);  // IsAltModifier
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliWheelEventIsNotShiftModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);
+
+  DALI_TEST_EQUALS(CTRL_MODIFIER, event.modifiers, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsShiftModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliWheelEventIsNotCtrlModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, ALT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);
+
+  DALI_TEST_EQUALS(ALT_MODIFIER, event.modifiers, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive fail test case for a method
+int UtcDaliWheelEventIsNotAltModifier(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);
+
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, event.modifiers, TEST_LOCATION);  // check different modifier used
+
+  DALI_TEST_EQUALS(false, event.IsAltModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliWheelEventANDModifer(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_AND_CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier() && event.IsShiftModifier(), TEST_LOCATION);
+
+  event.modifiers = SHIFT_MODIFIER;
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier() && event.IsShiftModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+// Positive test case for a method
+int UtcDaliWheelEventORModifer(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  WheelEvent event(WheelEvent::MOUSE_WHEEL, 1, SHIFT_AND_CTRL_MODIFIER, Vector2(1.0f, 1.0f), 1, 1000u);
+  DALI_TEST_EQUALS(true, event.IsCtrlModifier() || event.IsAltModifier(), TEST_LOCATION);
+
+  event.modifiers = SHIFT_MODIFIER;
+
+  DALI_TEST_EQUALS(false, event.IsCtrlModifier() && event.IsAltModifier(), TEST_LOCATION);
+  END_TEST;
+}
+
+int UtcDaliWheelEventSignalling(void)
+{
+  TestApplication application; // Reset all test adapter return codes
+
+  Actor actor = Actor::New();
+  actor.SetSize(100.0f, 100.0f);
+  actor.SetAnchorPoint(AnchorPoint::TOP_LEFT);
+  Stage::GetCurrent().Add(actor);
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Connect to actor's wheel event signal
+  SignalData data;
+  WheelEventReceivedFunctor functor( data );
+  actor.WheelEventSignal().Connect( &application, functor );
+
+  Vector2 screenCoordinates( 10.0f, 10.0f );
+  Integration::WheelEvent event(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u);
+
+  // Emit a wheel signal
+  application.ProcessEvent( event );
+  DALI_TEST_EQUALS( true, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( actor == data.wheeledActor );
+  DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, data.receivedWheelEvent.type, TEST_LOCATION); // check type
+  DALI_TEST_EQUALS(0, data.receivedWheelEvent.direction, TEST_LOCATION); // check direction
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, data.receivedWheelEvent.modifiers, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(screenCoordinates, data.receivedWheelEvent.point, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1, data.receivedWheelEvent.z, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1000u, data.receivedWheelEvent.timeStamp, TEST_LOCATION); // check modifier
+  data.Reset();
+
+  // Emit a wheel signal where the actor is not present, will hit the root actor though
+  Actor rootActor( Stage::GetCurrent().GetRootLayer() );
+
+  // Connect to root actor's wheel event signal
+  SignalData rootData;
+  WheelEventReceivedFunctor rootFunctor( rootData ); // Consumes signal
+  rootActor.WheelEventSignal().Connect( &application, rootFunctor );
+
+  screenCoordinates.x = screenCoordinates.y = 300.0f;
+  Integration::WheelEvent newEvent(Integration::WheelEvent::MOUSE_WHEEL, 0, SHIFT_MODIFIER, screenCoordinates, 1, 1000u);
+  application.ProcessEvent( newEvent );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  DALI_TEST_EQUALS( true, rootData.functorCalled, TEST_LOCATION );
+  DALI_TEST_CHECK( rootActor == rootData.wheeledActor );
+  DALI_TEST_EQUALS(WheelEvent::MOUSE_WHEEL, rootData.receivedWheelEvent.type, TEST_LOCATION); // check type
+  DALI_TEST_EQUALS(0, rootData.receivedWheelEvent.direction, TEST_LOCATION); // check direction
+  DALI_TEST_EQUALS(SHIFT_MODIFIER, rootData.receivedWheelEvent.modifiers, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(screenCoordinates, rootData.receivedWheelEvent.point, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1, rootData.receivedWheelEvent.z, TEST_LOCATION); // check modifier
+  DALI_TEST_EQUALS(1000u, rootData.receivedWheelEvent.timeStamp, TEST_LOCATION); // check modifier
+
+  // Remove actor from stage
+  Stage::GetCurrent().Remove( actor );
+
+  // Render and notify
+  application.SendNotification();
+  application.Render();
+
+  // Emit a move at the same point, we should not be signalled.
+  application.ProcessEvent( event );
+  DALI_TEST_EQUALS( false, data.functorCalled, TEST_LOCATION );
+  data.Reset();
+  END_TEST;
+}
diff --git a/automated-tests/style/back_top.png b/automated-tests/style/back_top.png
new file mode 100644 (file)
index 0000000..19cbd76
Binary files /dev/null and b/automated-tests/style/back_top.png differ
diff --git a/automated-tests/style/blue.jpg b/automated-tests/style/blue.jpg
new file mode 100644 (file)
index 0000000..d1db8f7
Binary files /dev/null and b/automated-tests/style/blue.jpg differ
diff --git a/automated-tests/style/gray.jpg b/automated-tests/style/gray.jpg
new file mode 100644 (file)
index 0000000..f1acfdb
Binary files /dev/null and b/automated-tests/style/gray.jpg differ
diff --git a/automated-tests/style/jquery.min.js b/automated-tests/style/jquery.min.js
new file mode 100644 (file)
index 0000000..198b3ff
--- /dev/null
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.1 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function cb(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function ca(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bE.test(a)?d(a,e):ca(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)ca(a+"["+e+"]",b[e],c,d);else d(a,b)}function b_(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function b$(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bT,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=b$(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=b$(a,c,d,e,"*",g));return l}function bZ(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bP),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bC(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bx:by,g=0,h=e.length;if(d>0){if(c!=="border")for(;g<h;g++)c||(d-=parseFloat(f.css(a,"padding"+e[g]))||0),c==="margin"?d+=parseFloat(f.css(a,c+e[g]))||0:d-=parseFloat(f.css(a,"border"+e[g]+"Width"))||0;return d+"px"}d=bz(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0;if(c)for(;g<h;g++)d+=parseFloat(f.css(a,"padding"+e[g]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+e[g]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+e[g]))||0);return d+"px"}function bp(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c+(i[c][d].namespace?".":"")+i[c][d].namespace,i[c][d],i[c][d].data)}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?m(g):h==="function"&&(!a.unique||!o.has(g))&&c.push(g)},n=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,l=j||0,j=0,k=c.length;for(;c&&l<k;l++)if(c[l].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}i=!1,c&&(a.once?e===!0?o.disable():c=[]:d&&d.length&&(e=d.shift(),o.fireWith(e[0],e[1])))},o={add:function(){if(c){var a=c.length;m(arguments),i?k=c.length:e&&e!==!0&&(j=a,n(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){i&&f<=k&&(k--,f<=l&&l--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&o.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(i?a.once||d.push([b,c]):(!a.once||!e)&&n(b,c));return this},fire:function(){o.fireWith(this,arguments);return this},fired:function(){return!!e}};return o};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p,q=c.createElement("div"),r=c.documentElement;q.setAttribute("className","t"),q.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="<div "+n+"><div></div></div>"+"<table "+n+" cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="<div style='width:4px;'></div>",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h=null;if(typeof a=="undefined"){if(this.length){h=f.data(this[0]);if(this[0].nodeType===1&&!f._data(this[0],"parsedAttrs")){e=this[0].attributes;for(var i=0,j=e.length;i<j;i++)g=e[i].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),l(this[0],g,h[g]));f._data(this[0],"parsedAttrs",!0)}}return h}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split("."),d[1]=d[1]?"."+d[1]:"";if(c===b){h=this.triggerHandler("getData"+d[1]+"!",[d[0]]),h===b&&this.length&&(h=f.data(this[0],a),h=l(this[0],a,h));return h===b&&d[1]?this.data(d[0]):h}return this.each(function(){var b=f(this),e=[d[0],c];b.triggerHandler("setData"+d[1]+"!",e),f.data(this,a,c),b.triggerHandler("changeData"+d[1]+"!",e)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise()}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h<g;h++)e=d[h],e&&(c=f.propFix[e]||e,f.attr(a,e,""),a.removeAttribute(v?e:c),u.test(e)&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};
+f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=[],j,k,l,m,n,o,p,q,r,s,t;g[0]=c,c.delegateTarget=this;if(e&&!c.target.disabled&&(!c.button||c.type!=="click")){m=f(this),m.context=this.ownerDocument||this;for(l=c.target;l!=this;l=l.parentNode||this){o={},q=[],m[0]=l;for(j=0;j<e;j++)r=d[j],s=r.selector,o[s]===b&&(o[s]=r.quick?H(l,r.quick):m.is(s)),o[s]&&q.push(r);q.length&&i.push({elem:l,matches:q})}}d.length>e&&i.push({elem:this,matches:d.slice(e)});for(j=0;j<i.length&&!c.isPropagationStopped();j++){p=i[j],c.currentTarget=p.elem;for(k=0;k<p.matches.length&&!c.isImmediatePropagationStopped();k++){r=p.matches[k];if(h||!c.namespace&&!r.namespace||c.namespace_re&&c.namespace_re.test(r.namespace))c.data=r.data,c.handleObj=r,n=((f.event.special[r.origType]||{}).handle||r.handler).apply(p.elem,g),n!==b&&(c.result=n,n===!1&&(c.preventDefault(),c.stopPropagation()))}}return c.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0)}),d._submit_attached=!0)})},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on.call(this,a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.type+"."+e.namespace:e.type,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.POS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function()
+{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bp)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1></$2>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bn(k[i]);else bn(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||be.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bq=/alpha\([^)]*\)/i,br=/opacity=([^)]*)/,bs=/([A-Z]|^ms)/g,bt=/^-?\d+(?:px)?$/i,bu=/^-?\d/,bv=/^([\-+])=([\-+.\de]+)/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Left","Right"],by=["Top","Bottom"],bz,bA,bB;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bz(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bv.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bz)return bz(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bC(a,b,d);f.swap(a,bw,function(){e=bC(a,b,d)});return e}},set:function(a,b){if(!bt.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cv(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cu("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cu("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cv(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cn.test(h)?(o=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),o?(f._data(this,"toggle"+i,o==="show"?"hide":"show"),j[o]()):j[h]()):(k=co.exec(h),l=j.cur(),k?(m=parseFloat(k[2]),n=k[3]||(f.cssNumber[i]?"":"px"),n!=="px"&&(f.style(this,i,(m||1)+n),l=(m||1)/j.cur()*l,f.style(this,i,l+n)),k[1]&&(m=(k[1]==="-="?-1:1)*m+l),j.custom(l,m,n)):j.custom(l,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:cu("show",1),slideUp:cu("hide",1),slideToggle:cu("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cr||cs(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){e.options.hide&&f._data(e.elem,"fxshow"+e.prop)===b&&f._data(e.elem,"fxshow"+e.prop,e.start)},h()&&f.timers.push(h)&&!cp&&(cp=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cr||cs(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cp),cp=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(["width","height"],function(a,b){f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cy(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.support.fixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.support.fixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
diff --git a/automated-tests/style/orange.jpg b/automated-tests/style/orange.jpg
new file mode 100644 (file)
index 0000000..ac4c749
Binary files /dev/null and b/automated-tests/style/orange.jpg differ
diff --git a/automated-tests/style/popup.js b/automated-tests/style/popup.js
new file mode 100644 (file)
index 0000000..5f994f4
--- /dev/null
@@ -0,0 +1,1215 @@
+/**
+ * Copyright (c)2005-2009 Matt Kruse (javascripttoolbox.com)
+ * 
+ * Dual licensed under the MIT and GPL licenses. 
+ * This basically means you can use this code however you want for
+ * free, but don't claim to have written it yourself!
+ * Donations always accepted: http://www.JavascriptToolbox.com/donate/
+ * 
+ * Please do not link to the .js files on javascripttoolbox.com from
+ * your site. Copy the files locally to your server instead.
+ * 
+ */
+/* ******************************************************************* */
+/*   UTIL FUNCTIONS                                                    */
+/* ******************************************************************* */
+var Util = {'$VERSION':1.06};
+
+// Util functions - these are GLOBAL so they
+// look like built-in functions.
+
+// Determine if an object is an array
+function isArray(o) {
+       return (o!=null && typeof(o)=="object" && typeof(o.length)=="number" && (o.length==0 || defined(o[0])));
+};
+
+// Determine if an object is an Object
+function isObject(o) {
+       return (o!=null && typeof(o)=="object" && defined(o.constructor) && o.constructor==Object && !defined(o.nodeName));
+};
+
+// Determine if a reference is defined
+function defined(o) {
+       return (typeof(o)!="undefined");
+};
+
+// Iterate over an array, object, or list of items and run code against each item
+// Similar functionality to Perl's map() function
+function map(func) {
+       var i,j,o;
+       var results = [];
+       if (typeof(func)=="string") {
+               func = new Function('$_',func);
+       }
+       for (i=1; i<arguments.length; i++) {
+               o = arguments[i];
+               if (isArray(o)) {
+                       for (j=0; j<o.length; j++) {
+                               results[results.length] = func(o[j]);
+                       }
+               }
+               else if (isObject(o)) {
+                       for (j in o) {
+                               results[results.length] = func(o[j]);
+                       }
+               }
+               else {
+                       results[results.length] = func(o);
+               }
+       }
+       return results;
+};
+
+// Set default values in an object if they are undefined
+function setDefaultValues(o,values) {
+       if (!defined(o) || o==null) {
+               o = {};
+       }
+       if (!defined(values) || values==null) {
+               return o;
+       }
+       for (var val in values) {
+               if (!defined(o[val])) {
+                       o[val] = values[val];
+               }
+       }
+       return o;
+};
+
+/* ******************************************************************* */
+/*   DEFAULT OBJECT PROTOTYPE ENHANCEMENTS                             */
+/* ******************************************************************* */
+// These functions add useful functionality to built-in objects
+Array.prototype.contains = function(o) {
+       var i,l;
+       if (!(l = this.length)) { return false; }
+       for (i=0; i<l; i++) {
+               if (o==this[i]) {
+                       return true;
+               }
+       }
+};
+
+/* ******************************************************************* */
+/*   DOM FUNCTIONS                                                     */
+/* ******************************************************************* */
+var DOM = (function() { 
+       var dom = {};
+       
+       // Get a parent tag with a given nodename
+       dom.getParentByTagName = function(o,tagNames) {
+               if(o==null) { return null; }
+               if (isArray(tagNames)) {
+                       tagNames = map("return $_.toUpperCase()",tagNames);
+                       while (o=o.parentNode) {
+                               if (o.nodeName && tagNames.contains(o.nodeName)) {
+                                       return o;
+                               }
+                       }
+               }
+               else {
+                       tagNames = tagNames.toUpperCase();
+                       while (o=o.parentNode) {
+                               if (o.nodeName && tagNames==o.nodeName) {
+                                       return o;
+                               }
+                       }
+               }
+               return null;
+       };
+       
+       // Remove a node from its parent
+       dom.removeNode = function(o) {
+               if (o!=null && o.parentNode && o.parentNode.removeChild) {
+                       // First remove all attributes which are func references, to avoid memory leaks
+                       for (var i in o) {
+                               if (typeof(o[i])=="function") {
+                                       o[i] = null;
+                               }
+                       }
+                       o.parentNode.removeChild(o);
+                       return true;
+               }
+               return false;
+       };
+
+       // Get the outer width in pixels of an object, including borders, padding, and margin
+       dom.getOuterWidth = function(o) {
+               if (defined(o.offsetWidth)) {
+                       return o.offsetWidth;
+               }
+               return null;
+       };
+
+       // Get the outer height in pixels of an object, including borders, padding, and margin
+       dom.getOuterHeight = function(o) {
+               if (defined(o.offsetHeight)) {
+                       return o.offsetHeight;
+               }
+               return null;
+       };
+
+       // Resolve an item, an array of items, or an object of items
+       dom.resolve = function() {
+               var results = new Array();
+               var i,j,o;
+               for (var i=0; i<arguments.length; i++) {
+                       var o = arguments[i];
+                       if (o==null) {
+                               if (arguments.length==1) {
+                                       return null;
+                               }
+                               results[results.length] = null;
+                       }
+                       else if (typeof(o)=='string') {
+                               if (document.getElementById) {
+                                       o = document.getElementById(o);
+                               }
+                               else if (document.all) {
+                                       o = document.all[o];
+                               }
+                               if (arguments.length==1) {
+                                       return o;
+                               }
+                               results[results.length] = o;
+                       }
+                       else if (isArray(o)) {
+                               for (j=0; j<o.length; j++) {
+                                       results[results.length] = o[j];
+                               }
+                       }
+                       else if (isObject(o)) {
+                               for (j in o) {
+                                       results[results.length] = o[j];
+                               }
+                       }
+                       else if (arguments.length==1) {
+                               return o;
+                       }
+                       else {
+                               results[results.length] = o;
+                       }
+         }
+         return results;
+       };
+       dom.$ = dom.resolve;
+       
+       return dom;
+})();
+
+/* ******************************************************************* */
+/*   CSS FUNCTIONS                                                     */
+/* ******************************************************************* */
+var CSS = (function(){
+       var css = {};
+
+       // Convert an RGB string in the form "rgb (255, 255, 255)" to "#ffffff"
+       css.rgb2hex = function(rgbString) {
+               if (typeof(rgbString)!="string" || !defined(rgbString.match)) { return null; }
+               var result = rgbString.match(/^\s*rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*/);
+               if (result==null) { return rgbString; }
+               var rgb = +result[1] << 16 | +result[2] << 8 | +result[3];
+               var hex = "";
+               var digits = "0123456789abcdef";
+               while(rgb!=0) { 
+                       hex = digits.charAt(rgb&0xf)+hex; 
+                       rgb>>>=4; 
+               } 
+               while(hex.length<6) { hex='0'+hex; }
+               return "#" + hex;
+       };
+
+       // Convert hyphen style names like border-width to camel case like borderWidth
+       css.hyphen2camel = function(property) {
+               if (!defined(property) || property==null) { return null; }
+               if (property.indexOf("-")<0) { return property; }
+               var str = "";
+               var c = null;
+               var l = property.length;
+               for (var i=0; i<l; i++) {
+                       c = property.charAt(i);
+                       str += (c!="-")?c:property.charAt(++i).toUpperCase();
+               }
+               return str;
+       };
+       
+       // Determine if an object or class string contains a given class.
+       css.hasClass = function(obj,className) {
+               if (!defined(obj) || obj==null || !RegExp) { return false; }
+               var re = new RegExp("(^|\\s)" + className + "(\\s|$)");
+               if (typeof(obj)=="string") {
+                       return re.test(obj);
+               }
+               else if (typeof(obj)=="object" && obj.className) {
+                       return re.test(obj.className);
+               }
+               return false;
+       };
+       
+       // Add a class to an object
+       css.addClass = function(obj,className) {
+               if (typeof(obj)!="object" || obj==null || !defined(obj.className)) { return false; }
+               if (obj.className==null || obj.className=='') { 
+                       obj.className = className; 
+                       return true; 
+               }
+               if (css.hasClass(obj,className)) { return true; }
+               obj.className = obj.className + " " + className;
+               return true;
+       };
+       
+       // Remove a class from an object
+       css.removeClass = function(obj,className) {
+               if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
+               if (!css.hasClass(obj,className)) { return false; }
+               var re = new RegExp("(^|\\s+)" + className + "(\\s+|$)");
+               obj.className = obj.className.replace(re,' ');
+               return true;
+       };
+       
+       // Fully replace a class with a new one
+       css.replaceClass = function(obj,className,newClassName) {
+               if (typeof(obj)!="object" || obj==null || !defined(obj.className) || obj.className==null) { return false; }
+               css.removeClass(obj,className);
+               css.addClass(obj,newClassName);
+               return true;
+       };
+       
+       // Get the currently-applied style of an object
+       css.getStyle = function(o, property) {
+               if (o==null) { return null; }
+               var val = null;
+               var camelProperty = css.hyphen2camel(property);
+               // Handle "float" property as a special case
+               if (property=="float") {
+                       val = css.getStyle(o,"cssFloat");
+                       if (val==null) { 
+                               val = css.getStyle(o,"styleFloat"); 
+                       }
+               }
+               else if (o.currentStyle && defined(o.currentStyle[camelProperty])) {
+                       val = o.currentStyle[camelProperty];
+               }
+               else if (window.getComputedStyle) {
+                       val = window.getComputedStyle(o,null).getPropertyValue(property);
+               }
+               else if (o.style && defined(o.style[camelProperty])) {
+                       val = o.style[camelProperty];
+               }
+               // For color values, make the value consistent across browsers
+               // Convert rgb() colors back to hex for consistency
+               if (/^\s*rgb\s*\(/.test(val)) {
+                       val = css.rgb2hex(val);
+               }
+               // Lowercase all #hex values
+               if (/^#/.test(val)) {
+                       val = val.toLowerCase();
+               }
+               return val;
+       };
+       css.get = css.getStyle;
+
+       // Set a style on an object
+       css.setStyle = function(o, property, value) {
+               if (o==null || !defined(o.style) || !defined(property) || property==null || !defined(value)) { return false; }
+               if (property=="float") {
+                       o.style["cssFloat"] = value;
+                       o.style["styleFloat"] = value;
+               }
+               else if (property=="opacity") {
+                       o.style['-moz-opacity'] = value;
+                       o.style['-khtml-opacity'] = value;
+                       o.style.opacity = value;
+                       if (defined(o.style.filter)) {
+                               o.style.filter = "alpha(opacity=" + value*100 + ")";
+                       }
+               }
+               else {
+                       o.style[css.hyphen2camel(property)] = value;
+               }
+               return true;
+       };
+       css.set = css.setStyle;
+       
+       // Get a unique ID which doesn't already exist on the page
+       css.uniqueIdNumber=1000;
+       css.createId = function(o) {
+               if (defined(o) && o!=null && defined(o.id) && o.id!=null && o.id!="") { 
+                       return o.id;
+               }
+               var id = null;
+               while (id==null || document.getElementById(id)!=null) {
+                       id = "ID_"+(css.uniqueIdNumber++);
+               }
+               if (defined(o) && o!=null && (!defined(o.id)||o.id=="")) {
+                       o.id = id;
+               }
+               return id;
+       };
+       
+       return css;
+})();
+
+/* ******************************************************************* */
+/*   EVENT FUNCTIONS                                                   */
+/* ******************************************************************* */
+
+var Event = (function(){
+       var ev = {};
+       
+       // Resolve an event using IE's window.event if necessary
+       // --------------------------------------------------------------------
+       ev.resolve = function(e) {
+               if (!defined(e) && defined(window.event)) {
+                       e = window.event;
+               }
+               return e;
+       };
+       
+       // Add an event handler to a function
+       // Note: Don't use 'this' within functions added using this method, since
+       // the attachEvent and addEventListener models differ.
+       // --------------------------------------------------------------------
+       ev.add = function( obj, type, fn, capture ) {
+               if (obj.addEventListener) {
+                       obj.addEventListener( type, fn, capture );
+                       return true;
+               }
+               else if (obj.attachEvent) {
+                       obj.attachEvent( "on"+type, fn );
+                       return true;
+               }
+               return false;
+       };
+
+       // Get the mouse position of an event
+       // --------------------------------------------------------------------
+       // PageX/Y, where they exist, are more reliable than ClientX/Y because 
+       // of some browser bugs in Opera/Safari
+       ev.getMouseX = function(e) {
+               e = ev.resolve(e);
+               if (defined(e.pageX)) {
+                       return e.pageX;
+               }
+               if (defined(e.clientX)) {
+                       return e.clientX+Screen.getScrollLeft();
+               }
+               return null;
+       };
+       ev.getMouseY = function(e) {
+               e = ev.resolve(e);
+               if (defined(e.pageY)) {
+                       return e.pageY;
+               }
+               if (defined(e.clientY)) {
+                       return e.clientY+Screen.getScrollTop();
+               }
+               return null;
+       };
+
+       // Stop the event from bubbling up to parent elements.
+       // Two method names map to the same function
+       // --------------------------------------------------------------------
+       ev.cancelBubble = function(e) {
+               e = ev.resolve(e);
+               if (typeof(e.stopPropagation)=="function") { e.stopPropagation(); } 
+               if (defined(e.cancelBubble)) { e.cancelBubble = true; }
+       };
+       ev.stopPropagation = ev.cancelBubble;
+
+       // Prevent the default handling of the event to occur
+       // --------------------------------------------------------------------
+       ev.preventDefault = function(e) {
+               e = ev.resolve(e);
+               if (typeof(e.preventDefault)=="function") { e.preventDefault(); } 
+               if (defined(e.returnValue)) { e.returnValue = false; }
+       };
+       
+       return ev;
+})();
+
+/* ******************************************************************* */
+/*   SCREEN FUNCTIONS                                                  */
+/* ******************************************************************* */
+var Screen = (function() {
+       var screen = {};
+
+       // Get a reference to the body
+       // --------------------------------------------------------------------
+       screen.getBody = function() {
+               if (document.body) {
+                       return document.body;
+               }
+               if (document.getElementsByTagName) {
+                       var bodies = document.getElementsByTagName("BODY");
+                       if (bodies!=null && bodies.length>0) {
+                               return bodies[0];
+                       }
+               }
+               return null;
+       };
+
+       // Get the amount that the main document has scrolled from top
+       // --------------------------------------------------------------------
+       screen.getScrollTop = function() {
+               if (document.documentElement && defined(document.documentElement.scrollTop) && document.documentElement.scrollTop>0) {
+                       return document.documentElement.scrollTop;
+               }
+               if (document.body && defined(document.body.scrollTop)) {
+                       return document.body.scrollTop;
+               }
+               return null;
+       };
+       
+       // Get the amount that the main document has scrolled from left
+       // --------------------------------------------------------------------
+       screen.getScrollLeft = function() {
+               if (document.documentElement && defined(document.documentElement.scrollLeft) && document.documentElement.scrollLeft>0) {
+                       return document.documentElement.scrollLeft;
+               }
+               if (document.body && defined(document.body.scrollLeft)) {
+                       return document.body.scrollLeft;
+               }
+               return null;
+       };
+       
+       // Util function to default a bad number to 0
+       // --------------------------------------------------------------------
+       screen.zero = function(n) {
+               return (!defined(n) || isNaN(n))?0:n;
+       };
+
+       // Get the width of the entire document
+       // --------------------------------------------------------------------
+       screen.getDocumentWidth = function() {
+               var width = 0;
+               var body = screen.getBody();
+               if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
+                   var rightMargin = parseInt(CSS.get(body,'marginRight'),10) || 0;
+                   var leftMargin = parseInt(CSS.get(body,'marginLeft'), 10) || 0;
+                       width = Math.max(body.offsetWidth + leftMargin + rightMargin, document.documentElement.clientWidth);
+               }
+               else {
+                       width =  Math.max(body.clientWidth, body.scrollWidth);
+               }
+               if (isNaN(width) || width==0) {
+                       width = screen.zero(self.innerWidth);
+               }
+               return width;
+       };
+       
+       // Get the height of the entire document
+       // --------------------------------------------------------------------
+       screen.getDocumentHeight = function() {
+               var body = screen.getBody();
+               var innerHeight = (defined(self.innerHeight)&&!isNaN(self.innerHeight))?self.innerHeight:0;
+               if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
+                   var topMargin = parseInt(CSS.get(body,'marginTop'),10) || 0;
+                   var bottomMargin = parseInt(CSS.get(body,'marginBottom'), 10) || 0;
+                       return Math.max(body.offsetHeight + topMargin + bottomMargin, document.documentElement.clientHeight, document.documentElement.scrollHeight, screen.zero(self.innerHeight));
+               }
+               return Math.max(body.scrollHeight, body.clientHeight, screen.zero(self.innerHeight));
+       };
+       
+       // Get the width of the viewport (viewable area) in the browser window
+       // --------------------------------------------------------------------
+       screen.getViewportWidth = function() {
+               if (document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
+                       return document.documentElement.clientWidth;
+               }
+               else if (document.compatMode && document.body) {
+                       return document.body.clientWidth;
+               }
+               return screen.zero(self.innerWidth);
+       };
+       
+       // Get the height of the viewport (viewable area) in the browser window
+       // --------------------------------------------------------------------
+       screen.getViewportHeight = function() {
+               if (!window.opera && document.documentElement && (!document.compatMode || document.compatMode=="CSS1Compat")) {
+                       return document.documentElement.clientHeight;
+               }
+               else if (document.compatMode && !window.opera && document.body) {
+                       return document.body.clientHeight;
+               }
+               return screen.zero(self.innerHeight);
+       };
+
+       return screen;
+})();var Sort = (function(){
+       var sort = {};
+       sort.AlphaNumeric = function(a,b) {
+               if (a==b) { return 0; }
+               if (a<b) { return -1; }
+               return 1;
+       };
+
+       sort.Default = sort.AlphaNumeric;
+       
+       sort.NumericConversion = function(val) {
+               if (typeof(val)!="number") {
+                       if (typeof(val)=="string") {
+                               val = parseFloat(val.replace(/,/g,''));
+                               if (isNaN(val) || val==null) { val=0; }
+                       }
+                       else {
+                               val = 0;
+                       }
+               }
+               return val;
+       };
+       
+       sort.Numeric = function(a,b) {
+               return sort.NumericConversion(a)-sort.NumericConversion(b);
+       };
+
+       sort.IgnoreCaseConversion = function(val) {
+               if (val==null) { val=""; }
+               return (""+val).toLowerCase();
+       };
+
+       sort.IgnoreCase = function(a,b) {
+               return sort.AlphaNumeric(sort.IgnoreCaseConversion(a),sort.IgnoreCaseConversion(b));
+       };
+
+       sort.CurrencyConversion = function(val) {
+               if (typeof(val)=="string") {
+                       val = val.replace(/^[^\d\.]/,'');
+               }
+               return sort.NumericConversion(val);
+       };
+       
+       sort.Currency = function(a,b) {
+               return sort.Numeric(sort.CurrencyConversion(a),sort.CurrencyConversion(b));
+       };
+       
+       sort.DateConversion = function(val) {
+               // inner util function to parse date formats
+               function getdate(str) {
+                       // inner util function to convert 2-digit years to 4
+                       function fixYear(yr) {
+                               yr = +yr;
+                               if (yr<50) { yr += 2000; }
+                               else if (yr<100) { yr += 1900; }
+                               return yr;
+                       };
+                       var ret;
+                       // YYYY-MM-DD
+                       if (ret=str.match(/(\d{2,4})-(\d{1,2})-(\d{1,2})/)) {
+                               return (fixYear(ret[1])*10000) + (ret[2]*100) + (+ret[3]);
+                       }
+                       // MM/DD/YY[YY] or MM-DD-YY[YY]
+                       if (ret=str.match(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2,4})/)) {
+                               return (fixYear(ret[3])*10000) + (ret[1]*100) + (+ret[2]);
+                       }
+                       return 99999999; // So non-parsed dates will be last, not first
+               };
+               return getdate(val);
+       };
+
+       sort.Date = function(a,b) {
+               return sort.Numeric(sort.DateConversion(a),sort.DateConversion(b));
+       };
+
+       return sort;
+})();
+
+var Position = (function() {
+       // Resolve a string identifier to an object
+       // ========================================
+       function resolveObject(s) {
+               if (document.getElementById && document.getElementById(s)!=null) {
+                       return document.getElementById(s);
+               }
+               else if (document.all && document.all[s]!=null) {
+                       return document.all[s];
+               }
+               else if (document.anchors && document.anchors.length && document.anchors.length>0 && document.anchors[0].x) {
+                       for (var i=0; i<document.anchors.length; i++) {
+                               if (document.anchors[i].name==s) { 
+                                       return document.anchors[i]
+                               }
+                       }
+               }
+       }
+       
+       var pos = {};
+       pos.$VERSION = 1.0;
+       
+       // Set the position of an object
+       // =============================
+       pos.set = function(o,left,top) {
+               if (typeof(o)=="string") {
+                       o = resolveObject(o);
+               }
+               if (o==null || !o.style) {
+                       return false;
+               }
+               
+               // If the second parameter is an object, it is assumed to be the result of getPosition()
+               if (typeof(left)=="object") {
+                       var pos = left;
+                       left = pos.left;
+                       top = pos.top;
+               }
+               
+               o.style.left = left + "px";
+               o.style.top = top + "px";
+               return true;
+       };
+       
+       // Retrieve the position and size of an object
+       // ===========================================
+       pos.get = function(o) {
+               var fixBrowserQuirks = true;
+                       // If a string is passed in instead of an object ref, resolve it
+               if (typeof(o)=="string") {
+                       o = resolveObject(o);
+               }
+               
+               if (o==null) {
+                       return null;
+               }
+               
+               var left = 0;
+               var top = 0;
+               var width = 0;
+               var height = 0;
+               var parentNode = null;
+               var offsetParent = null;
+       
+               
+               offsetParent = o.offsetParent;
+               var originalObject = o;
+               var el = o; // "el" will be nodes as we walk up, "o" will be saved for offsetParent references
+               while (el.parentNode!=null) {
+                       el = el.parentNode;
+                       if (el.offsetParent==null) {
+                       }
+                       else {
+                               var considerScroll = true;
+                               /*
+                               In Opera, if parentNode of the first object is scrollable, then offsetLeft/offsetTop already 
+                               take its scroll position into account. If elements further up the chain are scrollable, their 
+                               scroll offsets still need to be added in. And for some reason, TR nodes have a scrolltop value
+                               which must be ignored.
+                               */
+                               if (fixBrowserQuirks && window.opera) {
+                                       if (el==originalObject.parentNode || el.nodeName=="TR") {
+                                               considerScroll = false;
+                                       }
+                               }
+                               if (considerScroll) {
+                                       if (el.scrollTop && el.scrollTop>0) {
+                                               top -= el.scrollTop;
+                                       }
+                                       if (el.scrollLeft && el.scrollLeft>0) {
+                                               left -= el.scrollLeft;
+                                       }
+                               }
+                       }
+                       // If this node is also the offsetParent, add on the offsets and reset to the new offsetParent
+                       if (el == offsetParent) {
+                               left += o.offsetLeft;
+                               if (el.clientLeft && el.nodeName!="TABLE") { 
+                                       left += el.clientLeft;
+                               }
+                               top += o.offsetTop;
+                               if (el.clientTop && el.nodeName!="TABLE") {
+                                       top += el.clientTop;
+                               }
+                               o = el;
+                               if (o.offsetParent==null) {
+                                       if (o.offsetLeft) {
+                                               left += o.offsetLeft;
+                                       }
+                                       if (o.offsetTop) {
+                                               top += o.offsetTop;
+                                       }
+                               }
+                               offsetParent = o.offsetParent;
+                       }
+               }
+               
+       
+               if (originalObject.offsetWidth) {
+                       width = originalObject.offsetWidth;
+               }
+               if (originalObject.offsetHeight) {
+                       height = originalObject.offsetHeight;
+               }
+               
+               return {'left':left, 'top':top, 'width':width, 'height':height
+                               };
+       };
+       
+       // Retrieve the position of an object's center point
+       // =================================================
+       pos.getCenter = function(o) {
+               var c = this.get(o);
+               if (c==null) { return null; }
+               c.left = c.left + (c.width/2);
+               c.top = c.top + (c.height/2);
+               return c;
+       };
+       
+       return pos;
+})();// CLASS CONSTRUCTOR
+// --------------------------------------------------------------------
+var Popup = function(div, options) {
+       this.div = defined(div)?div:null;
+       this.index = Popup.maxIndex++;
+       this.ref = "Popup.objects["+this.index+"]";
+       Popup.objects[this.index] = this;
+       // Store a reference to the DIV by id, also
+       if (typeof(this.div)=="string") {
+               Popup.objectsById[this.div] = this;
+       }
+       if (defined(this.div) && this.div!=null && defined(this.div.id)) {
+               Popup.objectsById[this.div.id] = this.div.id;
+       }
+       // Apply passed-in options
+       if (defined(options) && options!=null && typeof(options)=="object") {
+               for (var i in options) {
+                       this[i] = options[i];
+               }
+       }
+       return this;
+};
+
+// CLASS PROPERTIES
+// --------------------------------------------------------------------
+// Index of popup objects, to maintain a global reference if necessary
+Popup.maxIndex = 0;
+Popup.objects = {};
+Popup.objectsById = {};
+
+// The z-index value that popups will start at
+Popup.minZIndex = 101;
+
+// Class names to assign to other objects
+Popup.screenClass = "PopupScreen";
+Popup.iframeClass = "PopupIframe";
+Popup.screenIframeClass = "PopupScreenIframe";
+
+// CLASS METHODS
+// --------------------------------------------------------------------
+
+// Hide all currently-visible non-modal dialogs
+Popup.hideAll = function() {
+       for (var i in Popup.objects) {
+               var p = Popup.objects[i];
+               if (!p.modal && p.autoHide) {
+                       p.hide();
+               }
+       }
+};
+// Catch global events as a trigger to hide auto-hide popups
+Event.add(document, "mouseup", Popup.hideAll, false);
+
+// A simple class method to show a popup without creating an instance
+Popup.show = function(divObject, referenceObject, position, options, modal) {
+       var popup;
+       if (defined(divObject)) { 
+               popup = new Popup(divObject);
+       }
+       else {
+               popup = new Popup();
+               popup.destroyDivOnHide = true;
+       }
+       if (defined(referenceObject)) { popup.reference = DOM.resolve(referenceObject); }
+       if (defined(position)) { popup.position = position; }
+       if (defined(options) && options!=null && typeof(options)=="object") {
+               for (var i in options) {
+                       popup[i] = options[i];
+               }
+       }
+       if (typeof(modal)=="boolean") {
+               popup.modal = modal;
+       }
+       popup.destroyObjectsOnHide = true;
+       popup.show();
+       return popup;
+};
+
+// A simple class method to show a modal popup
+Popup.showModal = function(divObject, referenceObject, position, options) {
+       Popup.show(divObject, referenceObject, position, options, true);
+};
+
+// A method to retrieve a popup object based on a div ID
+Popup.get = function(divId) {
+       if (defined(Popup.objectsById[divId])) {
+               return Popup.objectsById[divId];
+       }
+       return null;
+};
+
+// A method to hide a popup based on a div id
+Popup.hide = function(divId) {
+       var popup = Popup.get(divId);
+       if (popup!=null) {
+               popup.hide();
+       }
+};
+
+// PROTOTYPE PROPERTIES
+// --------------------------------------------------------------------
+Popup.prototype.content = null;
+Popup.prototype.className = "PopupDiv";
+Popup.prototype.style = null; // Styles to be applied to the DIV
+Popup.prototype.width = null;
+Popup.prototype.height = null;
+Popup.prototype.top = null;
+Popup.prototype.left = null;
+Popup.prototype.offsetLeft = 0;
+Popup.prototype.offsetTop = 0;
+Popup.prototype.constrainToScreen = true;
+Popup.prototype.autoHide = true;
+Popup.prototype.useIframeShim = false; /*@cc_on @*/ /*@if (@_win32) {Popup.prototype.useIframeShim = true;} @end @*/ 
+Popup.prototype.iframe = null;
+Popup.prototype.position = null; // vertical: "above top center bottom below", horizontal: "adjacent-left,left,center,right,adjacent-right"
+Popup.prototype.reference = null;
+Popup.prototype.modal = false;
+Popup.prototype.destroyDivOnHide = false;
+Popup.prototype.destroyObjectsOnHide = false;
+Popup.prototype.screen = null;
+Popup.prototype.screenIframeShim = null;
+Popup.prototype.screenOpacity=.4;
+Popup.prototype.screenColor="#cccccc";
+
+// INSTANCE METHODS
+// --------------------------------------------------------------------
+
+// Show the popup
+// --------------------------------------------------------------------
+Popup.prototype.show = function(options, modal) {
+       this.modal = this.modal || (typeof(modal)=="boolean" && modal);
+       if (defined(options) && options!=null && typeof(options)=="object") {
+               for (var i in options) {
+                       this[i] = options[i];
+               }
+       }
+       this.div = DOM.resolve(this.div);
+       CSS.setStyle(this.div,'position','absolute');
+       
+       // If there is no div pre-defined to use, create one
+       if (this.div==null) {
+               this.div = this.createDiv();
+       }
+       if (this.content!=null) {
+               this.div.innerHTML = this.content;
+               this.content = null;
+       }
+       if (this.className!=null) {
+               this.div.className = this.className;
+       }
+       if (this.style!=null) {
+               this.applyStyle();
+       }
+       if (this.width!=null) {
+               this.div.style.width = this.width+"px";
+               this.div.style.overflowX="auto";
+       }
+       if (this.height!=null) {
+               this.div.style.height = this.height+"px";
+               this.div.style.overflowY="auto";
+       }
+
+       // Do the actual display - this is a separate method so display transitions can be implemented
+       this.transition();
+       
+       // Make sure clicks on the DIV don't bubble up to the document
+       this.div.onclick = function(e) { 
+               Event.cancelBubble(Event.resolve(e));
+       };
+       this.div.onmouseup = this.div.onclick;
+       
+       // Focus to the DIV if possible 
+       if (this.modal && this.div.focus) {
+               this.div.focus();
+       }
+};
+
+// Show the popup but make it modal
+// --------------------------------------------------------------------
+Popup.prototype.transition = function() {
+       if (this.modal) {
+               this.addScreen();
+       }
+       
+       // Make the DIV displayed but hidden so its size can be measured
+       CSS.setStyle(this.div,'visibility','hidden');
+       CSS.setStyle(this.div,'display','block');
+
+       // Position the popup
+       this.setPosition();
+
+       // Add the shim if necessary    
+       if (this.useIframeShim) {
+               this.addIframeShim();
+       }
+
+       // Make sure the DIV is higher than the shim
+       this.div.style.zIndex = Popup.minZIndex++;
+
+       CSS.setStyle(this.div,'display','block');
+       CSS.setStyle(this.div,'visibility','visible');
+};
+
+// Show the popup but make it modal
+// --------------------------------------------------------------------
+Popup.prototype.showModal = function(options) {
+       this.show(options,true);
+};
+
+// Apply user styles to the DIV
+// --------------------------------------------------------------------
+Popup.prototype.applyStyle = function() {
+       if (this.div!=null && this.style!=null && typeof(this.style)=="object") {
+               for (var i in this.style) {
+                       this.div.style[i] = this.style[i];
+               }
+       }
+};
+
+// Hide the popup
+// --------------------------------------------------------------------
+Popup.prototype.hide = function() {
+       // If this was a temp object creating on-the-fly, then remove objects from the DOM so
+       // The document doesn't get littered with extra objects
+       if (this.destroyDivOnHide) {
+               DOM.removeNode(this.div);
+               this.div = null;
+               delete Popup.objects[this.id];
+       }
+       else if (this.div!=null) {
+               CSS.setStyle(this.div,'display','none');
+       }
+
+       if (this.destroyObjectsOnHide) {
+               DOM.removeNode(this.iframe);
+               DOM.removeNode(this.screen);
+               DOM.removeNode(this.screenIframeShim);
+       }
+       else {
+               if (this.iframe!=null) {
+                       this.iframe.style.display = "none";
+               }
+               if (this.screen!=null) {
+                       this.screen.style.display = "none";
+               }
+               if (this.screenIframeShim!=null) {
+                       this.screenIframeShim.style.display = "none";
+               }
+       }
+};
+
+// Util funcs for position
+// --------------------------------------------------------------------
+Popup.prototype.setTop = function(top) {
+       this.div.style.top = top+"px";
+};
+Popup.prototype.setLeft = function(left) {
+       this.div.style.left = left+"px";
+};
+Popup.prototype.getTop = function() {
+       return parseInt(CSS.getStyle(this.div,"top"),10);
+};
+Popup.prototype.getLeft = function() {
+       return parseInt(CSS.getStyle(this.div,"left"),10);
+};
+
+// All the logic to position the popup based on various criteria
+// --------------------------------------------------------------------
+Popup.prototype.setPosition = function() {
+       if (this.position!=null) {
+               var m = this.position.match(/^(\S+)\s+(\S+)/); 
+               if (m!=null && m.length==3) {
+                       var v = m[1];
+                       var h = m[2];
+
+                       var ref = this.reference;
+                       if (ref==null) { ref = Screen.getBody(); }
+                       var p = Position.get(ref);
+                       var refTop = p.top;
+                       var refLeft = p.left;
+                       var refWidth = DOM.getOuterWidth(ref);
+                       var refHeight = DOM.getOuterHeight(ref);
+                       
+                       var width = DOM.getOuterWidth(this.div);
+                       var height = DOM.getOuterHeight(this.div);
+                       
+                       var scrollLeft = Screen.getScrollLeft();
+                       var scrollTop = Screen.getScrollTop();
+
+                       // Set vertical position relative to reference object
+                       if (v=="above") { this.setTop(refTop-height+this.offsetTop); }
+                       else if (v=="top") { this.setTop(refTop+this.offsetTop); }
+                       else if (v=="center") { this.setTop(refTop+(refHeight/2)-(height/2)+this.offsetTop); }
+                       else if (v=="bottom") { this.setTop(refTop+refHeight-height+this.offsetTop); }
+                       else if (v=="below") { this.setTop(refTop+refHeight+this.offsetTop); }
+
+                       // Set horizontal position relative to reference object
+                       if (h=="adjacent-left") { this.setLeft(refLeft-width+this.offsetLeft); }
+                       else if (h=="left") { this.setLeft(refLeft+this.offsetLeft); }
+                       else if (h=="center") { this.setLeft(refLeft+(refWidth/2)-(width/2)+this.offsetLeft); }
+                       else if (h=="right") { this.setLeft(refLeft+refWidth-width+this.offsetLeft); }
+                       else if (h=="adjacent-right") { this.setLeft(refLeft+refWidth+this.offsetLeft); }
+               }
+       }
+       else if (this.top==null && this.left==null) {
+               this.center();
+       }
+       else {
+               if (this.top==null) { this.top=0; }
+               if (this.left==null) { this.left=0; }
+               this.div.style.top = this.top+this.offsetTop+"px";
+               this.div.style.left = this.left+this.offsetLeft+"px";
+       }
+
+       // Re-position to make sure it stays on the screen
+       if (this.constrainToScreen) {
+               this.fitToScreen();
+       }
+};
+
+// Append an object to the body
+// --------------------------------------------------------------------
+Popup.prototype.appendToBody = function(o) {
+       var body = Screen.getBody();
+       if (body && body.appendChild) {
+               body.appendChild(o);
+       }
+};
+
+// Create a new DIV object to be used for a popup
+// --------------------------------------------------------------------
+Popup.prototype.createDiv = function() {
+       if (document.createElement) {
+               var d = document.createElement("DIV");
+               d.style.position="absolute";
+               d.style.display="block";
+               d.style.visibility="hidden";
+               this.appendToBody(d);
+               return d;
+       }
+       alert("ERROR: Couldn't create DIV element in Popup.prototype.createDiv()");
+       return null;
+};
+
+// Create a new IFRAME object to be used behind the popup
+// --------------------------------------------------------------------
+Popup.prototype.createIframe = function() {
+       if (document.createElement) {
+               var i= document.createElement("IFRAME");
+               i.style.position="absolute";
+               i.style.display="block";
+               i.style.visibility="hidden";
+               i.style.background="none";
+               this.appendToBody(i);
+               return i;
+       }
+       else {
+               alert("ERROR: Couldn't create IFRAME object in Popup.prototype.createIframe()");
+       }
+};
+
+// Add an IFRAME shim for the DIV
+// --------------------------------------------------------------------
+Popup.prototype.addIframeShim = function() {
+       if (this.iframe==null) {
+               this.iframe = this.createIframe();
+       }
+       this.iframe.className = Popup.iframeClass;
+       CSS.setStyle(this.iframe,'top',this.getTop()+"px");
+       CSS.setStyle(this.iframe,'left',this.getLeft()+"px");
+       CSS.setStyle(this.iframe,'width',DOM.getOuterWidth(this.div) + "px");
+       CSS.setStyle(this.iframe,'height',DOM.getOuterHeight(this.div) + "px");
+       CSS.setStyle(this.iframe,'zIndex',Popup.minZIndex++);
+       CSS.setStyle(this.iframe,'opacity',0);
+       CSS.setStyle(this.iframe,'visibility','visible');
+       CSS.setStyle(this.iframe,'display','block');
+};
+
+// Create a "screen" to make a popup modal
+// --------------------------------------------------------------------
+Popup.prototype.addScreen = function() {
+       if (this.screen==null) {
+               this.screen = this.createDiv();
+               this.screen.style.top="0px";
+               this.screen.style.left="0px";
+               this.screen.style.backgroundColor = this.screenColor;
+               this.screen.className=Popup.screenClass;;
+               CSS.setStyle(this.screen,"opacity",this.screenOpacity);
+               this.screen.onclick = function(e) { Event.cancelBubble(Event.resolve(e)); }
+       }
+       if (this.screenIframeShim==null) {
+               this.screenIframeShim = this.createIframe();
+               this.screenIframeShim.style.top="0px";
+               this.screenIframeShim.style.left="0px";
+               this.screenIframeShim.className=Popup.screenIframeClass;
+               CSS.setStyle(this.screenIframeShim,"opacity",0);
+       }
+       this.screen.style.width = Screen.getDocumentWidth()+"px";
+       this.screen.style.height = Screen.getDocumentHeight()+"px";
+       this.screenIframeShim.style.width = Screen.getDocumentWidth()+"px";
+       this.screenIframeShim.style.height = Screen.getDocumentHeight()+"px";
+       this.screenIframeShim.style.zIndex = Popup.minZIndex++;
+       this.screenIframeShim.style.visibility="visible";
+       this.screenIframeShim.style.display="block";
+       this.screen.style.zIndex = Popup.minZIndex++;
+       this.screen.style.visibility="visible";
+       this.screen.style.display="block";
+};
+
+// Re-position the DIV so it stays on the screen
+// --------------------------------------------------------------------
+Popup.prototype.fitToScreen = function() {
+       var width = DOM.getOuterWidth(this.div);
+       var height = DOM.getOuterHeight(this.div);
+       var top = this.getTop();
+       var left = this.getLeft();
+       
+       var clientWidth = Screen.getViewportWidth();
+       var clientHeight = Screen.getViewportHeight();
+       
+       var scrollLeft = Screen.getScrollLeft();
+       var scrollTop = Screen.getScrollTop();
+
+       if (top-scrollTop+height>clientHeight) {
+               top = top - ((top+height) - (scrollTop+clientHeight));
+               this.div.style.top = top + "px";
+       }
+       if (left-scrollLeft+width>clientWidth) {
+               left = left - ((left+width) - (scrollLeft+clientWidth));
+               this.div.style.left = left + "px";
+       }
+       if (top<scrollTop) {
+               this.div.style.top=scrollTop+"px";
+       }
+       if (left<scrollLeft) {
+               this.div.style.left=scrollLeft+"px";
+       }
+};
+
+// Center the DIV object
+// --------------------------------------------------------------------
+Popup.prototype.center = function() {
+       var left = DOM.getOuterWidth(this.div);
+       var top = DOM.getOuterHeight(this.div);
+       if (isNaN(left)) { left=0; }
+       if (isNaN(top)) { top=0; }      
+       var clientW = Screen.getViewportWidth();
+       var clientH = Screen.getViewportHeight();
+       if (clientW!=null && clientH!=null) {
+               top = (clientH-top)/2;
+               left = (clientW-left)/2;
+       }
+       top += Screen.getScrollTop();
+       left += Screen.getScrollLeft();
+       
+       this.div.style.top = top+this.offsetTop+"px";
+       this.div.style.left = left+this.offsetLeft+"px";
+};
+
diff --git a/automated-tests/style/red.jpg b/automated-tests/style/red.jpg
new file mode 100644 (file)
index 0000000..ab67c5a
Binary files /dev/null and b/automated-tests/style/red.jpg differ
diff --git a/automated-tests/style/summary.xsl b/automated-tests/style/summary.xsl
new file mode 100644 (file)
index 0000000..c034df8
--- /dev/null
@@ -0,0 +1,352 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+       <xsl:output method="html" version="1.0" encoding="UTF-8"
+               indent="yes" />
+       <xsl:template match="/">
+               <html>
+                       <STYLE type="text/css">
+                               @import "./style/tests.css";
+                       </STYLE>
+                       <head>
+                               <script type="text/javascript" src="./style/jquery.min.js" />
+                       </head>
+                       <body>
+                               <div id="testcasepage">
+                                       <div id="title">
+                                               <table>
+                                                       <tr>
+                                                               <td>
+                                                                       <h1>TCT Report</h1>
+                                                               </td>
+                                                       </tr>
+                                               </table>
+                                       </div>
+                                       <div id="overview">
+                                       <table>
+                                               <tr>
+                                                       <td>
+                                       <div id="summary">
+                                               <table>
+                                                       <tr>
+                                                               <th colspan="2">Test Summary</th>
+                                                       </tr>
+                                                       <!-- tr>
+                                                               <td>TCT Version</td>
+                                                               <td>
+                                                                       <xsl:value-of select="result_summary/environment/@cts_version" />
+                                                               </td>
+                                                       </tr -->
+                                                       <tr>
+                                                               <td>Test Plan Name</td>
+                                                               <td>
+                                                                       <xsl:value-of select="result_summary/@plan_name" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Build ID</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@build_id">
+                                                                                       <xsl:if test="result_summary/environment/@build_id = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@build_id" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Test Total</td>
+                                                               <td>
+                                                                       <xsl:value-of select="sum(result_summary//suite/total_case)" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Test Passed</td>
+                                                               <td>
+                                                                       <xsl:value-of select="sum(result_summary//suite/pass_case)" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Test Failed</td>
+                                                               <td>
+                                                                       <xsl:value-of select="sum(result_summary//suite/fail_case)" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Test Blocked</td>
+                                                               <td>
+                                                                       <xsl:value-of select="sum(result_summary//suite/block_case)" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Test Not Executed</td>
+                                                               <td>
+                                                                       <xsl:value-of select="sum(result_summary//suite/na_case)" />
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Time</td>
+                                                               <td>
+                                                                       <xsl:value-of select="result_summary/summary/start_at" />
+                                                                       ~
+                                                                       <xsl:value-of select="result_summary/summary/end_at" />
+                                                               </td>
+                                                       </tr>
+                                               </table>
+                                       </div>
+                                       </td>
+                                       <td>
+                                       <div id="device">
+                                               <table>
+                                                       <tr>
+                                                               <th colspan="2">Device Information</th>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Host Device</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@host">
+                                                                                       <xsl:if test="result_summary/environment/@host = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@host" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Manufacturer</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@manufacturer">
+                                                                                       <xsl:if test="result_summary/environment/@manufacturer = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@manufacturer" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Device Model</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@device_model">
+                                                                                       <xsl:if test="result_summary/environment/@device_model = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@device_model" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Device ID</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@device_id">
+                                                                                       <xsl:if test="result_summary/environment/@device_id = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@device_id" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Screen Size</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@screen_size">
+                                                                                       <xsl:if test="result_summary/environment/@screen_size = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@screen_size" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                                       <tr>
+                                                               <td>Resolution</td>
+                                                               <td>
+                                                                       <xsl:choose>
+                                                                               <xsl:when test="result_summary/environment/@resolution">
+                                                                                       <xsl:if test="result_summary/environment/@resolution = ''">
+                                                                                               N/A
+                                                                                       </xsl:if>
+                                                                                       <xsl:value-of select="result_summary/environment/@resolution" />
+                                                                               </xsl:when>
+                                                                               <xsl:otherwise>
+                                                                                       N/A
+                                                                               </xsl:otherwise>
+                                                                       </xsl:choose>
+                                                               </td>
+                                                       </tr>
+                                               </table>
+                                       </div>
+                                       </td>
+                                       </tr>
+                                       </table>
+                                       </div>
+
+                                       <div id="capability">
+                                               <div id="title">
+                                                       <a name="contents"></a>
+                                                       <table>
+                                                               <tr>
+                                                                       <td class="title">
+                                                                               <h1><a href="#" class="see_capabilities">Device Capability</a></h1>
+                                                                       </td>
+                                                               </tr>
+                                                       </table>
+                                               </div>
+                                               <xsl:choose>
+                                                       <xsl:when test="result_summary/capabilities">
+                                                               <div id="capability_table" style="display:none;">
+                                                               <table>
+                                                                       <tr>
+                                                                               <th>Capability Name</th>
+                                                                               <th>Type</th>
+                                                                               <th>Value</th>
+                                                                       </tr>
+                                                                       <xsl:for-each select="result_summary/capabilities/capability">
+                                                                               <xsl:sort select="@name" />
+                                                                               <tr>
+                                                                                       <td>
+                                                                                               <xsl:value-of select="@name" />
+                                                                                       </td>
+                                                                                       <td>
+                                                                                               <xsl:value-of select="@type" />
+                                                                                       </td>
+                                                                                       <td>
+                                                                                               <xsl:choose>
+                                                                                                       <xsl:when test="value">
+                                                                                                               <xsl:value-of select="value" />
+                                                                                                       </xsl:when>
+                                                                                                       <xsl:otherwise>
+                                                                                                               <xsl:value-of select="@support" />
+                                                                                                       </xsl:otherwise>
+                                                                                               </xsl:choose>
+                                                                                       </td>
+                                                                               </tr>
+                                                                       </xsl:for-each>
+                                                               </table>
+                                                               </div>
+                                                       </xsl:when>
+                                                       <xsl:otherwise>
+                                                               The information of device capability is not available.
+                                                       </xsl:otherwise>
+                                               </xsl:choose>
+                                       </div>
+
+                                       <div id="suite_summary">
+                                               <div id="title">
+                                                       <a name="contents"></a>
+                                                       <table>
+                                                               <tr>
+                                                                       <td class="title">
+                                                                               <h1>Test Summary by Suite</h1>
+                                                                       </td>
+                                                               </tr>
+                                                       </table>
+                                               </div>
+                                               <table>
+                                                       <tr>
+                                                               <th>Suite</th>
+                                                               <th>Total</th>
+                                                               <th>Passed</th>
+                                                               <th>Failed</th>
+                                                               <th>Blocked</th>
+                                                               <th>Not Executed</th>
+                                                               <th class="Ratio">Ratio</th>
+                                                       </tr>
+                                                       <xsl:for-each select="result_summary/suite">
+                                                               <xsl:sort select="@name" />
+                                                               <tr class="suite_item">
+                                                                       <xsl:attribute name="id">
+                                                <xsl:value-of
+                                                                               select="@name" />
+                                    </xsl:attribute>
+                                                                       <td>
+                                                                               <a>
+                                                                                       <xsl:attribute name="href"><xsl:value-of
+                                                                                               select="@name" />.xml</xsl:attribute>
+                                                                                       <xsl:value-of select="@name" />
+                                                                               </a>
+                                                                       </td>
+                                                                       <td class="total">
+                                                                               <xsl:value-of select="total_case" />
+                                                                       </td>
+                                                                       <td class="pass">
+                                                                               <xsl:value-of select="pass_case" />
+                                                                       </td>
+                                                                       <td class="fail">
+                                                                               <xsl:value-of select="fail_case" />
+                                                                       </td>
+                                                                       <td class="block">
+                                                                               <xsl:value-of select="block_case" />
+                                                                       </td>
+                                                                       <td class="na">
+                                                                               <xsl:value-of select="na_case" />
+                                                                       </td>
+                                                                       <td class="Ratio">
+                                                                               <div class="RatioGraphic" />
+                                                                       </td>
+                                                               </tr>
+                                                       </xsl:for-each>
+                                               </table>
+                                       </div>
+
+                               </div>
+                               <div id="goTopBtn">
+                                       <img border="0" src="./style/back_top.png" />
+                               </div>
+                               <script type="text/javascript" src="./style/application.js" />
+                               <script language="javascript" type="text/javascript">
+                                       $(document).ready(function(){
+                                       goTopEx();
+                                       drawRatio();
+                                       });
+                               </script>
+                       </body>
+               </html>
+       </xsl:template>
+       <xsl:template name="br-replace">
+               <xsl:param name="word" />
+               <xsl:variable name="cr">
+                       <xsl:text>\n</xsl:text>
+               </xsl:variable>
+               <xsl:choose>
+                       <xsl:when test="contains($word,$cr)">
+                               <xsl:value-of select="substring-before($word,$cr)" />
+                               <br />
+                               <xsl:call-template name="br-replace">
+                                       <xsl:with-param name="word" select="substring-after($word,$cr)" />
+                               </xsl:call-template>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <xsl:value-of select="$word" />
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+</xsl:stylesheet>
diff --git a/automated-tests/style/testresult.xsl b/automated-tests/style/testresult.xsl
new file mode 100644 (file)
index 0000000..019b445
--- /dev/null
@@ -0,0 +1,571 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+       xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+       <xsl:output method="html" version="1.0" encoding="UTF-8"
+               indent="yes" />
+       <xsl:template match="/">
+               <html>
+                       <STYLE type="text/css">
+                               @import "./style/tests.css";
+                       </STYLE>
+                       <head>
+                               <script type="text/javascript" src="./style/jquery.min.js" />
+                               <script type="text/javascript" src="./style/popup.js" />
+                       </head>
+                       <body>
+                               <div id="title">
+                                       <table>
+                                               <tr>
+                                                       <td class="title">
+                                                               <h1 align="center">Suite Test Results</h1>
+                                                       </td>
+                                               </tr>
+                                       </table>
+                               </div>
+                               <div id="btc">
+                                       <table>
+                                               <tr>
+                                                       <td>
+                                                               <a href="#" class="see_all">Show all</a>
+                                                       </td>
+                                                       <td>
+                                                               <a href="#" class="see_failed">Show only failed</a>
+                                                       </td>
+                                                       <td>
+                                                               <a href="#" class="see_blocked">Show only blocked</a>
+                                                       </td>
+                                                       <td>
+                                                               <a href="#" class="see_na">Show only not executed</a>
+                                                       </td>
+                                                       <td>
+                                                               <a href="summary.xml">Summary</a>
+                                                       </td>
+                                               </tr>
+                                       </table>
+                               </div>
+                               <div id="testcasepage">
+                                       <div id="cases">
+                                               <div id="see_all">
+                                                       <xsl:for-each select="test_definition/suite">
+                                                               <xsl:sort select="@name" />
+                                                               <div id="suite_title">
+                                                                       <h2>
+                                                                               Test Suite:
+                                                                               <xsl:value-of select="@name" />
+                                                                               (All)
+                                                                       </h2>
+                                                                       <a>
+                                                                               <xsl:attribute name="name">
+                                                                     <xsl:value-of
+                                                                                       select="@name" />
+                                                                  </xsl:attribute>
+                                                                       </a>
+                                                               </div>
+                                                               <table>
+                                                                       <tr>
+                                                                               <th>Case_ID</th>
+                                                                               <th>Purpose</th>
+                                                                               <th>Result</th>
+                                                                               <th>Stderr</th>
+                                                                       </tr>
+                                                                       <xsl:for-each select=".//set">
+                                                                               <xsl:sort select="@name" />
+                                                                               <tr>
+                                                                                       <xsl:choose>
+                                                                                               <xsl:when test="@name">
+                                                                                                       <td colspan="3">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                                       <td colspan="1">
+                                                                                                               <h4>
+                                                                                                                       <a>
+                                                                                                                               <xsl:attribute name="href"><xsl:value-of
+                                                                                                                                       select="@set_debug_msg" /></xsl:attribute>
+                                                                                                                               dlog
+                                                                                                                       </a>
+                                                                                                               </h4>
+                                                                                                       </td>
+                                                                                               </xsl:when>
+                                                                                               <xsl:otherwise>
+                                                                                                       <td colspan="4">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                               </xsl:otherwise>
+                                                                                       </xsl:choose>
+                                                                               </tr>
+                                                                               <xsl:for-each select=".//testcase">
+                                                                                       <xsl:sort select="@id" />
+                                                                                       <tr>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                               style="background-color:#F5DEB3;border:1px solid black;display:none;">
+                                                                                                               <xsl:attribute name="id"><xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <p>
+                                                                                                                       <xsl:for-each select="./description/steps//step">
+                                                                                                                               <xsl:sort select="@order" />
+                                                                                                                               <B>
+                                                                                                                                       Step
+                                                                                                                                       <xsl:value-of select="@order" />
+                                                                                                                                       :
+                                                                                                                               </B>
+                                                                                                                               <br />
+                                                                                                                               <xsl:value-of select=".//step_desc" />
+                                                                                                                               <br />
+                                                                                                                               <B>Expected:</B>
+                                                                                                                               <xsl:value-of select=".//expected" />
+                                                                                                                               <br />
+                                                                                                                       </xsl:for-each>
+                                                                                                               </p>
+                                                                                                               <p>
+                                                                                                                       <br />
+                                                                                                                       <B>
+                                                                                                                               Entry:
+                                                                                                                               <br />
+                                                                                                                       </B>
+                                                                                                                       <xsl:value-of select="./description//test_script_entry" />
+                                                                                                                       <br />
+                                                                                                               </p>
+                                                                                                       </div>
+                                                                                                       <a href="#" class="test_case_popup">
+                                                                                                               <xsl:attribute name="id"><xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <xsl:value-of select="@id" />
+                                                                                                       </a>
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:value-of select="@purpose" />
+                                                                                               </td>
+
+                                                                                               <xsl:choose>
+                                                                                                       <xsl:when test="@result">
+                                                                                                               <xsl:if test="@result = 'FAIL'">
+                                                                                                                       <td class="red_rate">
+                                                                                                                               <xsl:value-of select="@result" />
+                                                                                                                       </td>
+                                                                                                               </xsl:if>
+                                                                                                               <xsl:if test="@result = 'PASS'">
+                                                                                                                       <td class="green_rate">
+                                                                                                                               <xsl:value-of select="@result" />
+                                                                                                                       </td>
+                                                                                                               </xsl:if>
+                                                                                                               <xsl:if test="@result = 'BLOCK' ">
+                                                                                                                       <td class="orange_rate">
+                                                                                                                               BLOCK
+                                                                                                                       </td>
+                                                                                                               </xsl:if>
+                                                                                                               <xsl:if
+                                                                                                                       test="@result != 'BLOCK' and @result != 'FAIL' and @result != 'PASS' ">
+                                                                                                                       <td class="gray_rate">
+                                                                                                                               Not Run
+                                                                                                                       </td>
+                                                                                                               </xsl:if>
+                                                                                                       </xsl:when>
+                                                                                                       <xsl:otherwise>
+                                                                                                               <td>
+
+                                                                                                               </td>
+                                                                                                       </xsl:otherwise>
+                                                                                               </xsl:choose>
+                                                                                               <td>
+                                                                                                       <xsl:call-template name="br-replace">
+                                                                                                               <xsl:with-param name="word"
+                                                                                                                       select=".//result_info/stderr" />
+                                                                                                       </xsl:call-template>
+                                                                                                       <xsl:if test=".//result_info/stderr = ''">
+                                                                                                               N/A
+                                                                                                       </xsl:if>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                               </xsl:for-each>
+                                                                       </xsl:for-each>
+                                                               </table>
+                                                       </xsl:for-each>
+                                               </div>
+                                               <div id="see_fail" style="display:none;">
+                                                       <xsl:for-each select="test_definition/suite">
+                                                               <xsl:sort select="@name" />
+                                                               <div id="suite_title">
+                                                                       <h2>
+                                                                               Test Suite:
+                                                                               <xsl:value-of select="@name" />
+                                                                               (Failed only)
+                                                                       </h2>
+                                                                       <a>
+                                                                               <xsl:attribute name="name">
+                                                                     <xsl:value-of
+                                                                                       select="@name" />
+                                                                  </xsl:attribute>
+                                                                       </a>
+                                                               </div>
+                                                               <table>
+                                                                       <tr>
+                                                                               <th>Case_ID</th>
+                                                                               <th>Purpose</th>
+                                                                               <th>Result</th>
+                                                                               <th>Stderr</th>
+                                                                       </tr>
+                                                                       <xsl:for-each select=".//set">
+                                                                               <xsl:sort select="@name" />
+                                                                               <tr>
+                                                                                       <xsl:choose>
+                                                                                               <xsl:when test="@name">
+                                                                                                       <td colspan="3">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                                       <td colspan="1">
+                                                                                                               <h4>
+                                                                                                                       <a>
+                                                                                                                               <xsl:attribute name="href"><xsl:value-of
+                                                                                                                                       select="@set_debug_msg" /></xsl:attribute>
+                                                                                                                               dlog
+                                                                                                                       </a>
+                                                                                                               </h4>
+                                                                                                       </td>
+                                                                                               </xsl:when>
+                                                                                               <xsl:otherwise>
+                                                                                                       <td colspan="4">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                               </xsl:otherwise>
+                                                                                       </xsl:choose>
+                                                                               </tr>
+                                                                               <xsl:for-each select=".//testcase[@result='FAIL']">
+                                                                                       <xsl:sort select="@id" />
+                                                                                       <tr>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                               style="background-color:#F5DEB3;border:1px solid black;display:none;">
+                                                                                                               <xsl:attribute name="id">fail_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <p>
+                                                                                                                       <xsl:for-each select="./description/steps//step">
+                                                                                                                               <xsl:sort select="@order" />
+                                                                                                                               <B>
+                                                                                                                                       Step
+                                                                                                                                       <xsl:value-of select="@order" />
+                                                                                                                                       :
+                                                                                                                               </B>
+                                                                                                                               <br />
+                                                                                                                               <xsl:value-of select=".//step_desc" />
+                                                                                                                               <br />
+                                                                                                                               <B>Expected:</B>
+                                                                                                                               <xsl:value-of select=".//expected" />
+                                                                                                                               <br />
+                                                                                                                       </xsl:for-each>
+                                                                                                               </p>
+                                                                                                               <p>
+                                                                                                                       <br />
+                                                                                                                       <B>
+                                                                                                                               Entry:
+                                                                                                                               <br />
+                                                                                                                       </B>
+                                                                                                                       <xsl:value-of select="./description//test_script_entry" />
+                                                                                                                       <br />
+                                                                                                               </p>
+                                                                                                       </div>
+                                                                                                       <a href="#" class="test_case_popup">
+                                                                                                               <xsl:attribute name="id">fail_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <xsl:value-of select="@id" />
+                                                                                                       </a>
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:value-of select="@purpose" />
+                                                                                               </td>
+
+                                                                                               <td class="red_rate">
+                                                                                                       <xsl:value-of select="@result" />
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:call-template name="br-replace">
+                                                                                                               <xsl:with-param name="word"
+                                                                                                                       select=".//result_info/stderr" />
+                                                                                                       </xsl:call-template>
+                                                                                                       <xsl:if test=".//result_info/stderr = ''">
+                                                                                                               N/A
+                                                                                                       </xsl:if>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                               </xsl:for-each>
+                                                                       </xsl:for-each>
+                                                               </table>
+                                                       </xsl:for-each>
+                                               </div>
+                                               <div id="see_block" style="display:none;">
+                                                       <xsl:for-each select="test_definition/suite">
+                                                               <xsl:sort select="@name" />
+                                                               <div id="suite_title">
+                                                                       <h2>
+                                                                               Test Suite:
+                                                                               <xsl:value-of select="@name" />
+                                                                               (Blocked Only)
+                                                                       </h2>
+                                                                       <a>
+                                                                               <xsl:attribute name="name">
+                                                                     <xsl:value-of
+                                                                                       select="@name" />
+                                                                  </xsl:attribute>
+                                                                       </a>
+                                                               </div>
+                                                               <table>
+                                                                       <tr>
+                                                                               <th>Case_ID</th>
+                                                                               <th>Purpose</th>
+                                                                               <th>Result</th>
+                                                                               <th>Stderr</th>
+                                                                       </tr>
+                                                                       <xsl:for-each select=".//set">
+                                                                               <xsl:sort select="@name" />
+                                                                               <tr>
+                                                                                       <xsl:choose>
+                                                                                               <xsl:when test="@name">
+                                                                                                       <td colspan="3">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                                       <td colspan="1">
+                                                                                                               <h4>
+                                                                                                                       <a>
+                                                                                                                               <xsl:attribute name="href"><xsl:value-of
+                                                                                                                                       select="@set_debug_msg" /></xsl:attribute>
+                                                                                                                               dlog
+                                                                                                                       </a>
+                                                                                                               </h4>
+                                                                                                       </td>
+                                                                                               </xsl:when>
+                                                                                               <xsl:otherwise>
+                                                                                                       <td colspan="4">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                               </xsl:otherwise>
+                                                                                       </xsl:choose>
+                                                                               </tr>
+                                                                               <xsl:for-each select=".//testcase[@result='BLOCK']">
+                                                                                       <xsl:sort select="@id" />
+                                                                                       <tr>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                               style="background-color:#F5DEB3;border:1px solid black;display:none;">
+                                                                                                               <xsl:attribute name="id">block_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <p>
+                                                                                                                       <xsl:for-each select="./description/steps//step">
+                                                                                                                               <xsl:sort select="@order" />
+                                                                                                                               <B>
+                                                                                                                                       Step
+                                                                                                                                       <xsl:value-of select="@order" />
+                                                                                                                                       :
+                                                                                                                               </B>
+                                                                                                                               <br />
+                                                                                                                               <xsl:value-of select=".//step_desc" />
+                                                                                                                               <br />
+                                                                                                                               <B>Expected:</B>
+                                                                                                                               <xsl:value-of select=".//expected" />
+                                                                                                                               <br />
+                                                                                                                       </xsl:for-each>
+                                                                                                               </p>
+                                                                                                               <p>
+                                                                                                                       <br />
+                                                                                                                       <B>
+                                                                                                                               Entry:
+                                                                                                                               <br />
+                                                                                                                       </B>
+                                                                                                                       <xsl:value-of select="./description//test_script_entry" />
+                                                                                                                       <br />
+                                                                                                               </p>
+                                                                                                       </div>
+                                                                                                       <a href="#" class="test_case_popup">
+                                                                                                               <xsl:attribute name="id">block_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <xsl:value-of select="@id" />
+                                                                                                       </a>
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:value-of select="@purpose" />
+                                                                                               </td>
+
+                                                                                               <td class="orange_rate">
+                                                                                                       <xsl:value-of select="@result" />
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:call-template name="br-replace">
+                                                                                                               <xsl:with-param name="word"
+                                                                                                                       select=".//result_info/stderr" />
+                                                                                                       </xsl:call-template>
+                                                                                                       <xsl:if test=".//result_info/stderr = ''">
+                                                                                                               N/A
+                                                                                                       </xsl:if>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                               </xsl:for-each>
+                                                                       </xsl:for-each>
+                                                               </table>
+                                                       </xsl:for-each>
+                                               </div>
+                                               <div id="see_na" style="display:none;">
+                                                       <xsl:for-each select="test_definition/suite">
+                                                               <xsl:sort select="@name" />
+                                                               <div id="suite_title">
+                                                                       <h2>
+                                                                               Test Suite:
+                                                                               <xsl:value-of select="@name" />
+                                                                               (Not executed Only)
+                                                                       </h2>
+                                                                       <a>
+                                                                               <xsl:attribute name="name">
+                                                                     <xsl:value-of
+                                                                                       select="@name" />
+                                                                  </xsl:attribute>
+                                                                       </a>
+                                                               </div>
+                                                               <table>
+                                                                       <tr>
+                                                                               <th>Case_ID</th>
+                                                                               <th>Purpose</th>
+                                                                               <th>Result</th>
+                                                                               <th>Stderr</th>
+                                                                       </tr>
+                                                                       <xsl:for-each select=".//set">
+                                                                               <xsl:sort select="@name" />
+                                                                               <tr>
+                                                                                       <xsl:choose>
+                                                                                               <xsl:when test="@name">
+                                                                                                       <td colspan="3">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                                       <td colspan="1">
+                                                                                                               <h4>
+                                                                                                                       <a>
+                                                                                                                               <xsl:attribute name="href"><xsl:value-of
+                                                                                                                                       select="@set_debug_msg" /></xsl:attribute>
+                                                                                                                               dlog
+                                                                                                                       </a>
+                                                                                                               </h4>
+                                                                                                       </td>
+                                                                                               </xsl:when>
+                                                                                               <xsl:otherwise>
+                                                                                                       <td colspan="4">
+                                                                                                               <h3>
+                                                                                                                       Test Set:
+                                                                                                                       <xsl:value-of select="@name" />
+                                                                                                               </h3>
+                                                                                                       </td>
+                                                                                               </xsl:otherwise>
+                                                                                       </xsl:choose>
+                                                                               </tr>
+                                                                               <xsl:for-each select=".//testcase[@result='N/A']">
+                                                                                       <xsl:sort select="@id" />
+                                                                                       <tr>
+                                                                                               <td>
+                                                                                                       <div
+                                                                                                               style="background-color:#F5DEB3;border:1px solid black;display:none;">
+                                                                                                               <xsl:attribute name="id">na_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <p>
+                                                                                                                       <xsl:for-each select="./description/steps//step">
+                                                                                                                               <xsl:sort select="@order" />
+                                                                                                                               <B>
+                                                                                                                                       Step
+                                                                                                                                       <xsl:value-of select="@order" />
+                                                                                                                                       :
+                                                                                                                               </B>
+                                                                                                                               <br />
+                                                                                                                               <xsl:value-of select=".//step_desc" />
+                                                                                                                               <br />
+                                                                                                                               <B>Expected:</B>
+                                                                                                                               <xsl:value-of select=".//expected" />
+                                                                                                                               <br />
+                                                                                                                       </xsl:for-each>
+                                                                                                               </p>
+                                                                                                               <p>
+                                                                                                                       <br />
+                                                                                                                       <B>
+                                                                                                                               Entry:
+                                                                                                                               <br />
+                                                                                                                       </B>
+                                                                                                                       <xsl:value-of select="./description//test_script_entry" />
+                                                                                                                       <br />
+                                                                                                               </p>
+                                                                                                       </div>
+                                                                                                       <a href="#" class="test_case_popup">
+                                                                                                               <xsl:attribute name="id">na_<xsl:value-of
+                                                                                                                       select="@id" /></xsl:attribute>
+                                                                                                               <xsl:value-of select="@id" />
+                                                                                                       </a>
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:value-of select="@purpose" />
+                                                                                               </td>
+
+                                                                                               <td class="gray_rate">
+                                                                                                       <xsl:value-of select="@result" />
+                                                                                               </td>
+                                                                                               <td>
+                                                                                                       <xsl:call-template name="br-replace">
+                                                                                                               <xsl:with-param name="word"
+                                                                                                                       select=".//result_info/stderr" />
+                                                                                                       </xsl:call-template>
+                                                                                                       <xsl:if test=".//result_info/stderr = ''">
+                                                                                                               N/A
+                                                                                                       </xsl:if>
+                                                                                               </td>
+                                                                                       </tr>
+                                                                               </xsl:for-each>
+                                                                       </xsl:for-each>
+                                                               </table>
+                                                       </xsl:for-each>
+                                               </div>
+                                       </div>
+                               </div>
+                               <div id="goTopBtn">
+                                       <img border="0" src="./style/back_top.png" />
+                               </div>
+                               <script type="text/javascript" src="./style/application.js" />
+                               <script language="javascript" type="text/javascript">
+                                       $(document).ready(function(){
+                                       goTopEx();
+                                       });
+                               </script>
+                       </body>
+               </html>
+       </xsl:template>
+       <xsl:template name="br-replace">
+               <xsl:param name="word" />
+               <xsl:variable name="cr">
+                       <xsl:text>\n</xsl:text>
+               </xsl:variable>
+               <xsl:choose>
+                       <xsl:when test="contains($word,$cr)">
+                               <xsl:value-of select="substring-before($word,$cr)" />
+                               <br />
+                               <xsl:call-template name="br-replace">
+                                       <xsl:with-param name="word" select="substring-after($word,$cr)" />
+                               </xsl:call-template>
+                       </xsl:when>
+                       <xsl:otherwise>
+                               <xsl:value-of select="$word" />
+                       </xsl:otherwise>
+               </xsl:choose>
+       </xsl:template>
+</xsl:stylesheet>
diff --git a/automated-tests/style/tests.css b/automated-tests/style/tests.css
new file mode 100644 (file)
index 0000000..487bca0
--- /dev/null
@@ -0,0 +1,195 @@
+@charset "UTF-8";\r
+/* CSS Document */\r
+#testcasepage div,#testcasepage h1,#testcasepage p,#testcasepage table,#testcasepage tr,#testcasepage th,#testcasepage td\r
+       {\r
+       margin: 0;\r
+       padding: 0;\r
+       border: 0;\r
+       font-weight: inherit;\r
+       font-style: inherit;\r
+       font-size: 0.96em;\r
+       font-family: arial;\r
+       vertical-align: baseline;\r
+}\r
+\r
+#title td, #btc td{\r
+       margin: 0;\r
+       padding: 0;\r
+       border: 0;\r
+       font-weight: inherit;\r
+       font-style: inherit;\r
+       font-size: 0.96em;\r
+       font-family: arial;\r
+       vertical-align: baseline;\r
+}\r
+\r
+td.Ratio {\r
+       text-align: left;\r
+       font-weight: normal;\r
+       padding: 4px 10px 4px 5px;\r
+       vertical-align: middle;\r
+}\r
+\r
+th.Ratio {\r
+       width: 400px;\r
+}\r
+\r
+#testcasepage p {\r
+       text-align: left;\r
+}\r
+\r
+#suite_title {\r
+       text-align: left;\r
+}\r
+\r
+#btc {\r
+       text-align: right;\r
+}\r
+\r
+#btc table {\r
+       position: absolute;\r
+       right: 0px;\r
+       width: 600px;\r
+}\r
+\r
+#testcasepage table {\r
+       border-collapse: separate;\r
+       border-spacing: 0;\r
+       margin-bottom: 1.4em;\r
+       vertical-align: middle;\r
+}\r
+\r
+#testcasepage th,#testcasepage td {\r
+       text-align: left;\r
+       font-weight: normal;\r
+       padding: 4px 10px 4px 5px;\r
+       vertical-align: middle;\r
+}\r
+\r
+#cases table {\r
+       width: 101%;\r
+}\r
+\r
+#cases td {\r
+       border-left: 0px;\r
+       font-weight: normal;\r
+       border-bottom: 0px;\r
+}\r
+\r
+#suite_summary table {\r
+       width: 100%;\r
+}\r
+\r
+\r
+#overview table {\r
+       width: 101%;\r
+}\r
+\r
+#overview table, #overview td, #overview tr {\r
+       border-left: none;\r
+       border-bottom: none;\r
+       border-right: none;\r
+       vertical-align: top;\r
+}\r
+\r
+#overview td{\r
+       width: 50%;\r
+}\r
+\r
+#capability table {\r
+       width: 50%;\r
+}\r
+\r
+#fail_cases table {\r
+       width: 101%;\r
+}\r
+\r
+#title table {\r
+       width: 101%;\r
+}\r
+\r
+#device table {\r
+       width: 100%;\r
+}\r
+\r
+#summary table {\r
+       width: 100%;\r
+}\r
+\r
+#testcasepage th {\r
+       border-bottom: 1px solid #000;\r
+       background-color: #AAAAAA;\r
+       border-left: 1px solid #000;\r
+       border-top: 1px solid #000;\r
+       color: #000;\r
+       font-weight: bold;\r
+       vertical-align: bottom;\r
+}\r
+\r
+#summary th:last-child,#summary td:last-child, #device th:last-child,#device td:last-child, #suite_summary th:last-child,#suite_summary td:last-child,#cases th:last-child,#cases td:last-child,#capability th:last-child,#capability td:last-child {\r
+       border-right: 1px solid #000;\r
+}\r
+\r
+#testcasepage td {\r
+       font-weight: normal;\r
+}\r
+\r
+#summary td, #device td, #capability td, #suite_summary td, #cases td{\r
+       border-left: 1px solid;\r
+       font-weight: normal;\r
+       border-bottom: 1px solid;\r
+}\r
+\r
+#testcasepage td.yellow_rate {\r
+       background-color: #ffcc00;\r
+}\r
+\r
+#testcasepage td.green_rate {\r
+       background-color: #1E90FF;\r
+}\r
+\r
+#testcasepage td.dgreen_rate {\r
+       background-color: #339933;\r
+}\r
+\r
+#testcasepage td.red_rate {\r
+       background-color: #FF3333;\r
+}\r
+\r
+#testcasepage td.orange_rate {\r
+       background-color: #FFA500;\r
+}\r
+\r
+#testcasepage td.gray_rate {\r
+       background-color: #AAAAAA;\r
+}\r
+\r
+#title table,#title tr,#title td {\r
+       border-left: none;\r
+       border-bottom: none;\r
+       text-align: center;\r
+}\r
+\r
+#title td:last-child {\r
+       border-right: none;\r
+}\r
+\r
+#testcasepage h1 {\r
+       font-size: 2em;\r
+       font-family: Arial, sans-serif;\r
+       font-weight: bold;\r
+       line-height: 1;\r
+       color: #000;\r
+       margin-bottom: 0.75em;\r
+       padding-top: 0.25em;\r
+       font-weight: bold;\r
+}\r
+\r
+#goTopBtn {\r
+       right: 0px;\r
+       bottom: 0px;\r
+       position: fixed; +\r
+       position: absolute;\r
+       top: expression(parseInt(document.body.scrollTop)+document.body.clientHeight-40\r
+               );\r
+}\r
diff --git a/automated-tests/tcbuild b/automated-tests/tcbuild
new file mode 120000 (symlink)
index 0000000..89c2de7
--- /dev/null
@@ -0,0 +1 @@
+scripts/tcbuild.sh
\ No newline at end of file
diff --git a/automated-tests/templates/tct-package/README b/automated-tests/templates/tct-package/README
new file mode 100644 (file)
index 0000000..0af341f
--- /dev/null
@@ -0,0 +1,43 @@
+The scripts contained in the automated-tests/scripts folder are based on
+the Web Application Security & Privacy module test suite from Intel,
+with the following license:
+
+----------------------------------------------
+License
+----------------------------------------------
+Copyright (c) 2012 Intel Corporation.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of works must retain the original copyright notice, this list
+  of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the original 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 Intel Corporation nor the names of its contributors
+  may be used to endorse or promote products derived from this work without
+  specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION "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 INTEL CORPORATION 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.
+
+Authors:
+        Yue, Jianhui <jianhuix.a.yue@intel.com>
+
+Modifications to scripts:
+Added mechanism to build and execute tests with finer granularity.
+Added option to generate tests for executing on desktop
+
+Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+Authors:
+        Steele, David <david.steele@partner.samsung.com>
diff --git a/automated-tests/templates/tct-package/inst.sh b/automated-tests/templates/tct-package/inst.sh
new file mode 100755 (executable)
index 0000000..c2888df
--- /dev/null
@@ -0,0 +1,37 @@
+#!/bin/bash
+NAME=$(basename $(cd $(dirname $0);pwd))
+PKG_DIR=%{PKG_DIR} # directory supplied by external script
+PKG_NAME=%{PKG_NAME} # name supplied by external script
+PKG_FULLNAME=%{PKG_FULLNAME} # name supplied by external script
+
+#parse params
+USAGE="Usage: ./inst.sh [-i] [-u]
+  -i install wgt and config environment
+  -u uninstall wgt and remove source file
+[-i] option was set as default."
+
+function installpkg(){
+    rpm -e `rpm -qa | grep $PKG_NAME`
+    rpm -ivh --quiet /$PKG_DIR/$PKG_FULLNAME
+    /tmp/add_all_smack_rule.sh
+}
+
+function uninstallpkg(){
+### remove source file ###
+if [ -d /opt/usr/media/tct/opt/$NAME ];then
+    rm -rf /opt/usr/media/tct/opt/$NAME
+    rpm -e $PKG_NAME
+else
+    echo "Remove source file fail, please check if the source file exist: /opt/usr/media/tct/opt/$NAME ..."
+fi
+}
+
+case "$1" in
+    -h|--help) echo "$USAGE"
+               exit ;;
+    ""|-i) installpkg;;
+    -u) uninstallpkg;;
+    *) echo "Unknown option: $1"
+       echo "$USAGE"
+       exit ;;
+esac
diff --git a/build/scripts/dali_env b/build/scripts/dali_env
new file mode 100755 (executable)
index 0000000..d0a9416
--- /dev/null
@@ -0,0 +1,602 @@
+#!/usr/bin/perl
+
+# Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+use Config;
+use Cwd;
+use Cwd 'abs_path';
+use File::Basename;
+use File::Path;
+use File::Copy;
+use File::Copy::Recursive qw(dircopy);
+use strict;
+use Getopt::Long;
+use Pod::Usage;
+
+################################################################################
+#                                SYSTEM PACKAGES                               #
+################################################################################
+# Add any required system packages to this list - if they are not present, then
+# this script will attempt to install them for you.
+my @system_packages = (
+    "automake",
+    "cmake",
+    "g++",
+    "pkg-config",
+    "libtool",
+    "ccache",
+    "libboost-dev",
+    "libboost-thread-dev",
+    "libelementary-dev",
+    "libexif-dev",
+    "libgles2-mesa-dev",
+    "libdrm-dev",
+    "libgif-dev",
+    "libturbojpeg",
+    "libfribidi-dev",
+    "libharfbuzz-dev",
+    "doxygen",
+    "lcov",
+    "libcurl4-gnutls-dev"
+);
+
+# Some packages like require building from source
+my @source_pkgs = (
+
+    {"name" => "v8",
+     "force-rebuild" => 0,
+     "use_depot_tools" => 1,
+     "repo" => "https://chromium.googlesource.com/v8/v8.git",
+     "depot_tools_repo" => "https://chromium.googlesource.com/chromium/tools/depot_tools.git",
+
+     # original version used with DALi is 3.25.19. 3.32.7 is the latest we can use before
+     # upgrading DALi to use  c++0x or c++11
+     "version" => " 3.32.7", "make" => "make -j8 library=shared", "build-mode" =>"debug" }
+);
+
+### Detect any http proxy, part of v8 installation requires this information
+my $http_proxy_port;
+my $http_proxy_ip;
+
+if( exists $ENV{http_proxy} )
+{
+  # string  split into 3 items  http, //ip, port
+  my @http_proxy_info =  split( /:/,$ENV{http_proxy}, );
+
+  $http_proxy_ip =  @http_proxy_info[1];
+  $http_proxy_ip =~ s/[\/]//g;;  # remove forward slashes
+  $http_proxy_port =  @http_proxy_info[2];
+}
+
+# Make best guess as to where this program was run from (note, it is
+# always possible to override the location of $0 by the calling
+# program, so we can't really tell for sure that this is where we
+# expect it to be. :/
+
+my $new_env   = 0;
+my $exec_path = $0;
+if($0 !~ m!^/!)
+{
+    $exec_path = abs_path($0);
+}
+$exec_path = dirname($exec_path);
+
+my $root_path = getcwd();
+if($exec_path =~ m!dali-env/opt/bin!)
+{
+    $root_path = $exec_path;
+    while($root_path !~ m!dali-env$!)
+    {
+        $root_path = dirname($root_path);
+    }
+}
+elsif($root_path =~ m!dali-env!)
+{
+    while($root_path !~ m!dali-env$!)
+    {
+        $root_path = dirname($root_path);
+    }
+}
+else
+{
+    $new_env = 1;
+    $root_path .= "/dali-env";
+}
+
+my $src_path     = "$root_path/src-packages";
+my $sbs_path     = "$root_path/target";
+my $install_path = "$root_path/opt";
+
+my $opt_create=0;
+my $opt_setenv=0;
+my $opt_help=0;
+my $opt_man=0;
+
+GetOptions("create"     => \$opt_create,
+           "setenv"     => \$opt_setenv,
+           "help"       => \$opt_help,
+           "man"        => \$opt_man) or pod2usage(2);
+
+pod2usage(1) if $opt_help;
+pod2usage(-exitstatus => 0, -verbose => 2) if $opt_man;
+
+
+################################################################################
+
+sub create_env
+{
+    mkpath("$install_path/bin");
+    mkpath("$install_path/lib/pkgconfig");
+    mkpath("$install_path/include");
+    mkpath("$install_path/share/aclocal");
+    mkpath("$src_path");
+    mkpath("$sbs_path");
+
+    copy($0, "$install_path/bin/dali_env");
+    chmod(0755, "$install_path/bin/dali_env");
+}
+
+################################################################################
+
+sub in_dali_env
+{
+    my $cwd = substr(getcwd(), 0, length($root_path));
+    #print "cwd = $cwd\nroot = $root_path\n";
+    return $cwd eq $root_path;
+}
+
+################################################################################
+
+sub create_setenv
+{
+    print <<"EOF";
+# To use the desktop libraries, please add the following lines to your .bashrc or
+# create a setenv script from them, e.g. by running this command as follows
+# \$ dali_env -s > setenv
+#
+# You can then source this script by using
+# \$ . setenv
+#
+# Use DESKTOP_PREFIX when running configure in dali/build/tizen:
+# \$ CXXFLAGS="-g -O0" ./configure --prefix=\$DESKTOP_PREFIX
+
+export DESKTOP_PREFIX=$install_path
+export PATH=$install_path/bin:\$PATH
+export LD_LIBRARY_PATH=$install_path/lib:\$LD_LIBRARY_PATH
+export INCLUDEDIR=$install_path/include
+export PKG_CONFIG_PATH=$install_path/lib/pkgconfig:/usr/lib/pkgconfig:/usr/share/pkgconfig
+
+EOF
+}
+
+################################################################################
+
+sub check_system_package
+{
+    my $package;
+    foreach $package (@_)
+    {
+        my @x=split(/\s+/, `dpkg -l $package|grep $package`);
+        if($x[0] ne "ii")
+        {
+            print "Attempting to install $package\n";
+            system("sudo apt-get -y install $package");
+        }
+    }
+}
+
+sub check_system_packages
+{
+    print "Checking for required system packages (may require sudo password)\n";
+
+    check_system_package(@system_packages);
+    my $gnome_v =`dpkg -l gnome-common| tail -1| sed "s/ \\+/ /g" | cut -d' ' -f 3`;
+    my @am = split(/\./, `automake --version | head -1 | cut -f4 -d' '`);
+    if($gnome_v =~ /$2.24/ && $am[1]>10)
+    {
+        die "Gnome common and automake are not compatible - automake is too new\n";
+    }
+    my @gpp_v = (`g++ --version  | head -1` =~ /(\d+)\.(\d+)\.(\d+)/);
+
+    if(! (($gpp_v[0] > 4)
+          ||
+          ($gpp_v[0] == 4 && $gpp_v[1] > 4)
+          ||
+          ($gpp_v[0] == 4 && $gpp_v[1] == 4 && $gpp_v[2] >= 5)))
+    {
+        die "You need g++ 4.5.1 or greater to build dali\n";
+    }
+}
+
+sub check_source_packages
+{
+    my $pkgref;
+
+    foreach $pkgref (@source_pkgs)
+    {
+        my $pkg = $pkgref->{"name"};
+        if($pkg eq "v8")
+        {
+            install_v8( $pkgref );
+        }
+    }
+}
+
+################################################################################
+
+sub create_link
+{
+    my $arch=`uname -i`;
+    $arch =~ s/\r|\n//g;
+
+    my $link = "/usr/lib/$arch-linux-gnu/libturbojpeg.so";
+
+    unless (-e $link)
+    {
+       print "Creating libjpegturbo symbolic link\n";
+       system("sudo ln -s $link.0 $link");
+    }
+}
+
+################################################################################
+# Helper to run and print out the command being run and quit if it fails
+#
+sub run_command
+{
+  my $command = $_[0];
+  my $ret;
+  print("Running: $command\n");
+  $ret = system("$command");
+  if($ret >> 8) { die "$command failed \n"; }
+}
+
+################################################################################
+# later versions of v8 (post mid 2014) require googles depot_tools to build.
+#
+sub install_google_depot_tools
+{
+
+####
+# clone the depo_tools into the source directory and set the path up
+####
+    my $v8 = $_[0];
+
+    my $depot_tools_directory = $src_path . "/depot_tools";
+    my $depot_tools_repo = $v8->{"depot_tools_repo"};
+
+    # clear the directory if exists
+    rmtree( $depot_tools_directory );
+
+    # clone the depot tools
+    run_command( "git clone " . $depot_tools_repo. " " . $depot_tools_directory );
+
+    # add it the the path
+    $ENV{PATH} = "$ENV{PATH}:$depot_tools_directory";
+
+    # need to setup a config file for the proxy
+    create_boto_config_file( $v8 , $depot_tools_directory );
+
+    # set the config location as an environment variable ( used by scripts depot_tools)
+    $ENV{NO_AUTH_BOTO_CONFIG}="$src_path/depot_tools/.boto";
+
+    # change to depot tools directory
+    chdir( $depot_tools_directory );
+
+    # fetch v8
+    run_command("fetch --nohooks v8");
+
+}
+
+
+################################################################################
+# later versions of v8 use boto, which currently requires having proxy manually set
+#
+sub create_boto_config_file
+{
+    my $v8 = $_[0];
+    my $depot_tools_directory = $_[1];
+    print(" depot_tools directory = $depot_tools_directory\n");
+
+    print("Configuring boto with http proxy IP = ". $http_proxy_ip . ", Port = " . $http_proxy_port . "\n");
+
+# Create the proxy info for the boto file
+my $fileContents = <<"END";
+[Boto]
+debug = 0
+num_retries = 2
+
+proxy = $http_proxy_ip
+proxy_port = $http_proxy_port
+END
+      # Place the config file in the depot tools folder
+    my $filename = $depot_tools_directory . "/" . ".boto";
+    print("Creating Boto config file with proxy settings to file ". $filename . "\n");
+    my $fh;
+    open( $fh, '>',  $filename );
+    print { $fh } $fileContents;
+    close( $fh );
+
+    # export the environment variable
+    run_command("gclient config https://gclient.googlecode.com/svn/trunk/gclient");
+
+    run_command("gclient runhooks");
+
+
+
+}
+################################################################################
+# We need a specific version of V8 to work with DALi
+# - Check a txt file in dali-env to see if v8 needs upgrading (checks gcc version too)
+# - Clones the source
+# - builds dependencies (v8 automatically clones it's GYP build system)
+# - Builds it
+# - Create a package file
+# It is cloned, then built from source, we create a package file for it, then
+# it's copied into dali-env
+sub install_v8
+{
+    my $v8 = $_[0];
+    my $ret;
+    my $v8Version = $v8->{"version"} ;
+    print( "Checking if V8 ". $v8Version. " is installed \n");
+
+####
+# Check currently installed version
+# We create a text file with v8 and gcc version in the filename to compare with
+# Version file is stored as "v8_2.3.4_installed_built_with_gcc_4_8_3.txt"
+####
+    # get the gcc version, so if the compiler is updated v8 is re-built
+    # note: v8 requires gcc version GCC >= 4.6
+    my $gccVersion = `gcc --version | grep ^gcc | sed 's/^.* //g'`;
+    chomp( $gccVersion );
+    my $versionTextFile = $src_path . "/v8_" . $v8Version. "_" . $v8->{"build-mode"} . "_installed_built_with_gcc_". $gccVersion .".txt";
+
+    # use stat to see if file exists
+    my @install_stats = stat $versionTextFile;
+    if( (scalar(@install_stats)) && $v8->{"force-rebuild"} != 1 )
+    {
+      print("Correct V8 version installed\n");
+      return;
+    }
+    else
+    {
+      # delete older versions of the version file first ( otherwise when downgrading it thinks version is still installed)
+      system( "rm " . $src_path . "/v8_*.txt  >/dev/null 2>&1");
+    }
+
+
+####
+# Clone the v8 source repository and checkout the version we want
+####
+    # Need to clone it from repo
+    my $v8_source_directory;
+
+
+
+    # newer version of v8 use depot_tools with gclient, git cloned builds do not work
+    if( $v8->{"use_depot_tools"} == 1)
+    {
+      install_google_depot_tools( $v8 );
+
+      # v8 is checkout out under depot_tools path
+      $v8_source_directory = $src_path . "/depot_tools/v8";
+    }
+    else
+    {
+      $v8_source_directory = $src_path . "/v8";
+
+      # delete the old v8 source directpry if exists
+      rmtree( $v8_source_directory );
+
+      # clone the repository
+      run_command( "git clone " . $v8->{"repo"} . " " . $v8_source_directory );
+    }
+
+    # change to the source directoy for the checkout
+    chdir( $v8_source_directory );
+
+    # checkout the version DALi is compatible with
+    run_command( "git checkout ". $v8Version );
+
+####
+# Run make dependencies then make for the specific target
+####
+    if( $v8->{"use_depot_tools"} == 1)
+    {
+      run_command("gclient sync");
+    }
+    else
+    {
+      run_command("make dependencies");
+    }
+
+    # assemble the make command
+    my $makeCommand = $v8->{"make"};
+
+    # need to append architecture and build mode, e.g. x64.debug
+    my $buildTarget;
+    if( $Config{use64bitint} ) {
+       print("Building 64 bit version of V8\n");
+       $buildTarget= "x64." . $v8->{"build-mode"}
+    }
+    else{
+      print("Building 32 bit version of V8\n");
+       $buildTarget= "ia32." . $v8->{"build-mode"}
+    }
+    $makeCommand .= " " . $buildTarget;
+    print("Running: $makeCommand\n");
+    run_command( $makeCommand );
+
+####
+# Manually install the library / header files
+####
+
+    # Need to manually install (make install not available on v8 )
+    my $libSourceDir = "$v8_source_directory/out/$buildTarget/lib.target/";
+    my $headerSourceDir = "$v8_source_directory/include/";
+
+    my $libDestinationDir = $install_path . "/lib/";
+    my $headerDestinationDir = $install_path . "/include/v8/";
+
+    # delete any current v8 libs
+    system( "rm " . $libDestinationDir . "libv8*");
+    system( "rm " . $libDestinationDir . "libicu*");
+
+
+    # copy the library and header files
+    dircopy( $libSourceDir, $libDestinationDir);
+    dircopy( $headerSourceDir, $headerDestinationDir);
+
+
+    # Copy libv8.so to libv8.so.version (  e.g. libv8.so.1.2.4)
+    my $v8SoFile = $libDestinationDir . "libv8.so";
+    my $v8SoVersionFile = $libDestinationDir . "libv8.so." . $v8Version;
+    move( $v8SoFile, $v8SoVersionFile );
+
+    # symlink the libv8.so.1.2.3 to libv8.so
+    symlink( $v8SoVersionFile, $v8SoFile );
+    print( "source dir = " . $libSourceDir . " dest dir ". $libDestinationDir . " \n" );
+
+
+####
+# Create the package file in,
+# we keep the library files and header files in v8 sub-directories
+####
+my $fileContents = <<"END";
+prefix=$install_path
+exec_prefix=\${prefix}
+apiversion=$v8Version
+libdir=\${exec_prefix}/lib
+includedir=\${prefix}/include/v8
+
+Name: v8 JavaScript engine - runtime library
+Description: V8 is Google's open source JavaScript engine.
+Version: \${apiversion}
+Libs: -L\${libdir} -lv8 -licuuc -licui18n
+Cflags: -I\${includedir}
+END
+
+  my $filename = $install_path . "/lib/pkgconfig/" . "v8.pc";
+  print("writing to file ". $filename . "\n");
+  my $fh;
+  if( open( $fh, '>',  $filename ) )
+  {
+    print { $fh } $fileContents;
+    close( $fh );
+  }
+  else
+  {
+    die "failed to create " . $filename ."\n";
+  }
+
+  print("Installed V8 " .$v8Version . " OK\n");
+
+#####
+#
+####
+      my $versionFile;
+      open( $versionFile, '>',  $versionTextFile );
+      close( $versionFile );
+      print("Installing V8 version $v8Version\n");
+
+}
+
+
+################################################################################
+#                                       MAIN
+################################################################################
+
+
+if($opt_create)
+{
+    my $new_root = getcwd() . "/dali-env";
+
+    if($exec_path =~ m!dali-env/opt/bin!)
+    {
+        die "Already in a dali-env directory\n";
+        # Could query if user wants to re-create?
+    }
+    elsif(-e $new_root)
+    {
+        die "A dali-env directory already exists here\n";
+    }
+
+    check_system_packages();
+
+    create_link();
+
+    create_env();
+
+    # do this after source directory structure created in create_env
+    check_source_packages();
+
+    create_setenv();
+}
+elsif($opt_setenv)
+{
+    if(! -d $root_path)
+    {
+        die "$root_path does not exist\n";
+    }
+    elsif($new_env)
+    {
+        die "$root_path is not an existing environment\n";
+    }
+    create_setenv();
+}
+else
+{
+    pod2usage(1);
+}
+
+__END__
+
+=head1 NAME
+
+dali_env - Create the DALi environment for Ubuntu
+
+=head1 SYNOPSIS
+
+dali_env [-c] [-s] [-h|-m]
+
+=head1 OPTIONS
+
+=over 28
+
+=item B<-c|--create>
+
+Create a DALi environment directory in the current directory.
+
+=item B<-s|--setenv>
+
+Display environment variables to setup.
+
+=item B<-h|--help>
+
+Display this help
+
+=item B<-m|--man>
+
+Display the manual page
+
+=back
+
+=head1 DESCRIPTION
+
+B<dali_env>
+
+Gets the required dependencies for DALi and them to a local directory. Can also create a setenv script to point to the installation.
+
+=cut
diff --git a/build/scripts/generate-shader-strings.pl b/build/scripts/generate-shader-strings.pl
new file mode 100755 (executable)
index 0000000..cafaa23
--- /dev/null
@@ -0,0 +1,390 @@
+#!/usr/bin/perl -w
+
+###############################################################################
+
+use strict;
+use FileHandle;
+use Getopt::Long;
+use Pod::Usage;
+
+###############################################################################
+
+sub OpenFileForWriting
+{
+  my($fileName) = shift;
+
+  my $fh = FileHandle->new;
+  if (!$fh->open("> $fileName"))
+  {
+    die "Can't open $fileName for writing: $!\n";
+  }
+  return $fh;
+}
+
+###############################################################################
+
+sub CloseFile
+{
+  my($fh) = shift;
+  $fh->close;
+}
+
+###############################################################################
+
+sub GenerateHeaderFileHeader
+{
+  my($headerFile) = shift;
+  my $time=localtime();
+  print $headerFile <<"H_HEADER_END";
+//
+// Automatically Generated on $time
+//
+
+#ifndef __DALI_GENERATED_SHADERS_H_
+#define __DALI_GENERATED_SHADERS_H_
+
+namespace Dali
+{
+namespace Internal
+{
+
+H_HEADER_END
+}
+
+###############################################################################
+
+sub GenerateHeaderFileFooter
+{
+  my($headerFile) = shift;
+  print $headerFile <<"H_FOOTER_END";
+
+} // namespace Internal
+} // namespace Dali
+
+#endif // __DALI_GENERATED_SHADERS_H_
+H_FOOTER_END
+}
+
+###############################################################################
+
+sub GenerateSourceFileHeader
+{
+  my($sourceFile) = shift;
+  my $time=localtime();
+  print $sourceFile <<"CPP_HEADER_END";
+//
+// Automatically Generated on $time
+//
+
+namespace Dali
+{
+namespace Internal
+{
+
+CPP_HEADER_END
+}
+
+###############################################################################
+
+sub GenerateSourceFileFooter
+{
+  my($sourceFile) = shift;
+  print $sourceFile <<"CPP_FOOTER_END";
+} // namespace Internal
+} // namespace Dali
+CPP_FOOTER_END
+}
+
+###############################################################################
+
+my %shaders=();
+
+sub GenerateStringsFromFile
+{
+  my($file) = shift;
+  my($dir) = shift;
+
+  my $shadername = $file;
+  $shadername =~ s/-([a-z])/uc($1)/eg;
+  $shadername =~ s/^([a-z])/uc($1)/e;
+  $shadername =~ s/\.txt$//;
+
+  my $state = 0;
+
+  my $shader="";
+  open MEM, "$dir/$file" || die "Can't open $file for reading: $!\n";
+  while(<MEM>)
+  {
+    chomp;
+    if ($state == 0)
+    {
+      if (/<VertexShader>/)
+      {
+        $state = 1;
+        $shader = "";
+      }
+      elsif (/<FragmentShader>/)
+      {
+        $state = 1;
+        $shader = "";
+      }
+    }
+    elsif ($state == 1)
+    {
+      if (m!</VertexShader>!)
+      {
+        $state = 0;
+        $shaders{$shadername}->{"vertex"} = $shader;
+      }
+      elsif( m!</FragmentShader>!)
+      {
+        $state = 0;
+        $shaders{$shadername}->{"fragment"} = $shader;
+      }
+      else
+      {
+        ## Accumulate
+        $shader .= "$_\n";
+#       print $sourceFile "\"$_\\n\"\n";
+      }
+    }
+  }
+  close MEM;
+}
+
+###############################################################################
+
+sub GetShaderFiles
+{
+  my ($dir) = shift;
+  opendir (DIR, $dir) || die "Can't open $dir for reading: $!\n";
+  my @shaderFiles = grep { /\.txt$/ && -f "$dir/$_" } readdir DIR;
+  closedir DIR;
+  return @shaderFiles;
+}
+
+###############################################################################
+
+sub PrintSourceLine
+{
+    my $sourceFile=shift;
+    my $line=shift;
+    chomp $line;
+    $line =~ s!//.*$!!; # Strip out comments
+    $line =~ s!\s*$!!; # Strip out trailing space
+    if( $line !~ m!^\s*$! )
+    {
+        print $sourceFile "\"$line\\n\"\n";
+    }
+}
+
+sub PrintMacroLine
+{
+    my $sourceFile=shift;
+    my $line=shift;
+    chomp $line;
+    $line =~ s!//.*$!!; # Strip out comments
+    $line =~ s!\s*$!!; # Strip out trailing space
+    if( $line !~ m!^\s*$! )
+    {
+        print $sourceFile "\"$line\\n\" \\\n";
+    }
+}
+
+
+sub PrintShaderProgramWithMacros
+{
+    my $sourceFile=shift;
+    my $shadername=shift;
+    my $SHADERNAME=$shadername;
+    $SHADERNAME =~ s/([A-Z])/_$1/g;
+    substr($SHADERNAME,0,1)="";
+    $SHADERNAME = uc($SHADERNAME);
+
+    my $program_type=shift;
+    my $ProgramType=ucfirst($program_type);
+    my $PROGRAM_TYPE=uc($program_type);
+    my $custom=shift;
+
+    my @lines=split(/\n/, $shaders{$shadername}->{$program_type} );
+
+    print $sourceFile "#define ${SHADERNAME}_PREFIX_${PROGRAM_TYPE} \\\n";
+    LINE: while( scalar(@lines) )
+    {
+        last LINE if $lines[0] =~ /main()/;
+        PrintMacroLine($sourceFile, shift(@lines));
+    }
+    print $sourceFile "\n\n";
+
+    print $sourceFile "#define ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE} \\\n";
+    LINE: while( scalar(@lines) )
+    {
+        PrintMacroLine($sourceFile, shift(@lines));
+    }
+    print $sourceFile "\n\n";
+
+    if($custom)
+    {
+        print $sourceFile "extern const char* const Custom${shadername}Prefix${ProgramType};\n";
+        print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n";
+        print $sourceFile "  ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n";
+        print $sourceFile ");\n\n";
+
+        print $sourceFile "extern const char* const Custom${shadername}Postfix${ProgramType};\n";
+        print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n";
+        print $sourceFile "  ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n";
+        print $sourceFile ");\n\n";
+    }
+    print $sourceFile "extern const char* const ${shadername}${ProgramType};\n";
+    print $sourceFile "const char* const ${shadername}${ProgramType}(\n";
+    print $sourceFile "  ${SHADERNAME}_PREFIX_${PROGRAM_TYPE}\n";
+    print $sourceFile "  ${SHADERNAME}_POSTFIX_${PROGRAM_TYPE}\n";
+    print $sourceFile ");\n\n";
+
+}
+
+sub PrintShaderProgram
+{
+    my $sourceFile=shift;
+    my $shadername=shift;
+    my $program_type=shift;
+    my $custom=shift;
+    my $ProgramType=ucfirst($program_type);
+
+    my @lines=split(/\n/, $shaders{$shadername}->{$program_type} );
+
+    print $sourceFile "const char* const ${shadername}${ProgramType}(\n";
+    for my $i (0..scalar(@lines)-1)
+    {
+        PrintSourceLine($sourceFile, $lines[$i]);
+    }
+    print $sourceFile ");\n\n";
+
+    if( $custom )
+    {
+        print $sourceFile "const char* const Custom${shadername}Prefix${ProgramType}(\n";
+      LINE:
+        while( scalar(@lines) )
+        {
+            last LINE if $lines[0] =~ /main()/;
+            PrintSourceLine($sourceFile, shift(@lines));
+        }
+        print $sourceFile ");\n\n";
+
+        print $sourceFile "const char* const Custom${shadername}Postfix${ProgramType}(\n";
+
+        while( scalar(@lines) )
+        {
+            PrintSourceLine($sourceFile, shift(@lines));
+        }
+        print $sourceFile ");\n\n";
+    }
+}
+
+
+sub PrintShaderSources
+{
+  my($headerFile) = shift;
+  my($sourceFile) = shift;
+  my $shadername;
+
+  # Strings are now in memory. Dump them back out again:
+  foreach $shadername (sort(keys(%shaders)))
+  {
+    print $headerFile "extern const char* const ${shadername}Vertex;\n";
+    print $headerFile "extern const char* const ${shadername}Fragment;\n";
+
+    my $custom = 0;
+    if( $shadername !~ /TextDistanceField/ || $shadername eq "TextDistanceField" )
+    {
+        print $headerFile "extern const char* const Custom${shadername}PrefixVertex;\n";
+        print $headerFile "extern const char* const Custom${shadername}PostfixVertex;\n";
+        print $headerFile "extern const char* const Custom${shadername}PrefixFragment;\n";
+        print $headerFile "extern const char* const Custom${shadername}PostfixFragment;\n";
+        $custom = 1;
+    }
+    PrintShaderProgramWithMacros($sourceFile, $shadername, "vertex", $custom);
+    PrintShaderProgramWithMacros($sourceFile, $shadername, "fragment", $custom);
+  }
+}
+
+###############################################################################
+
+my($optHelp);
+my($optMan);
+my($shaderDir) = "";
+my($fileName) = "";
+
+GetOptions(
+  "help"           => \$optHelp,
+  "man"            => \$optMan,
+  "shader-dir=s"   => \$shaderDir,
+  "file-name=s"  => \$fileName
+) or pod2usage(2);
+
+pod2usage(1) if $optHelp;
+pod2usage(-exitstatus => 0, -verbose => 2) if $optMan;
+
+if ($shaderDir eq "" || $fileName eq "")
+{
+  pod2usage(1);
+}
+else
+{
+  my $dir = $shaderDir;
+  my @shaderFiles = GetShaderFiles($dir);
+
+  my $headerFile = OpenFileForWriting("$fileName.h");
+  my $sourceFile = OpenFileForWriting("$fileName.cpp");
+
+  GenerateHeaderFileHeader($headerFile);
+  GenerateSourceFileHeader($sourceFile);
+
+  my $file;
+  foreach $file (@shaderFiles)
+  {
+    GenerateStringsFromFile($file, $dir);
+  }
+
+  PrintShaderSources($headerFile, $sourceFile);
+
+  GenerateHeaderFileFooter($headerFile);
+  GenerateSourceFileFooter($sourceFile);
+
+  CloseFile($headerFile);
+  CloseFile($sourceFile);
+}
+
+###############################################################################
+
+__END__
+
+=head1 NAME
+
+generate-shader-strings.pl - Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays.
+
+=head1 SYNOPSIS
+
+generate-shader-strings.pl -s=<shader-dir> -f=<file-name>
+
+generate-shader-strings.pl -shader-dir=<shader-dir> -file-name=<file-name>
+
+=head1 DESCRIPTION
+
+Given a shader directory and a file name, this script generates a header and source file where all the shaders in the directory are stored as vertex and fragment shader const char arrays.
+
+The shader files in the specified directory should have the suffix ".txt" and the vertex and fragment shaders should be encapsulated within <VertexShader>*</VertexShader> and <FragmentShader>*</FragmentShader> respectively in this text file.
+
+The generated source files will be called <file-name>.h and <file-name>.cpp.
+
+=head1 OPTIONS
+
+=over 36
+
+=item B<-s|--shader-dir=<shader-directory>>
+
+The directory the shader files should be loaded from.
+
+=item B<-f|--file-name>
+
+The name of the output files.
diff --git a/build/tizen/.gitignore b/build/tizen/.gitignore
new file mode 100644 (file)
index 0000000..644f5f5
--- /dev/null
@@ -0,0 +1,21 @@
+/gmon.out
+/aclocal.m4
+/autom4te.cache
+/ar-lib
+/compile
+/config.guess
+/config.log
+/config.status
+/config.sub
+/configure
+/depcomp
+/install-sh
+/libtool
+/ltmain.sh
+/missing
+/demo/dali-demo
+/dali-core.pc
+/dali.pc
+/dali-core/dali-shaders.cpp
+/dali-core/dali-shaders.h
+/documentation.list
diff --git a/build/tizen/Makefile.am b/build/tizen/Makefile.am
new file mode 100644 (file)
index 0000000..c1296f3
--- /dev/null
@@ -0,0 +1,59 @@
+# Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+SUBDIRS = dali-core
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = dali-core.pc
+
+MAINTAINERCLEANFILES = \
+    aclocal.m4 \
+    autom4te.cache \
+    config.guess \
+    config.sub \
+    configure \
+    depcomp \
+    install-sh \
+    ltmain.sh \
+    missing \
+    `find "$(srcdir)" -type f -name Makefile.in -print` \
+    `find . \( -name "*.gcov" -o -name "*.gcno" -o -name "*.gcda" \) -print`
+
+CLEANFILES = \
+    `find . \( -name "*.gcov" -o -name "*.gcno" -o -name "*.gcda" \) -print`
+
+COVERAGE_DIR=.cov
+COVERAGE_OUTPUT_DIR=doc/coverage
+
+# From lcov version 1.10 onwards, branch coverage is off by default and earlier versions do not support the rc option
+LCOV_OPTS=`if [ \`printf "\\\`lcov --version | cut -d' ' -f4\\\`\n1.10\n" | sort -V | head -n 1\` = 1.10 ] ; then echo "--rc lcov_branch_coverage=1" ; fi`
+
+cov_data:
+       @test -z $(COVERAGE_DIR) || mkdir -p $(COVERAGE_DIR)
+       @rm -f $(COVERAGE_DIR)/*
+       @cp dali-core/.libs/*.gcda dali-core/.libs/*.gcno $(COVERAGE_DIR)
+       @for i in `find $(COVERAGE_DIR) -name "libdali_core_la-*.gcda" -o -name "libdali_core_la-*.gcno"` ;\
+               do mv $$i `echo $$i | sed s/libdali_core_la-//` ; echo $$i ; done
+       @for i in `find $(COVERAGE_DIR) -name "libdali_la-*.gcda" -o -name "libdali_la-*.gcno"` ;\
+               do mv $$i `echo $$i | sed s/libdali_la-//` ; done
+       @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --base-directory . --directory . -c -o dali.info
+       @cd $(COVERAGE_DIR) ; lcov $(LCOV_OPTS) --remove dali.info "*/dali-env/*" "/usr/include/*" -o dali.info
+       @test -z $(COVERAGE_OUTPUT_DIR) || mkdir -p $(COVERAGE_OUTPUT_DIR)
+
+coverage: cov_data
+       @genhtml $(LCOV_OPTS) -o $(COVERAGE_OUTPUT_DIR) $(COVERAGE_DIR)/dali.info
+
+reset_coverage:
+       @lcov -z --directory `pwd`
diff --git a/build/tizen/configure.ac b/build/tizen/configure.ac
new file mode 100644 (file)
index 0000000..5560206
--- /dev/null
@@ -0,0 +1,117 @@
+# Copyright (c) 2014 Samsung Electronics Co., Ltd.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+m4_define([dali_version],[0.1.1])
+AC_INIT([dali], [dali_version])
+AM_INIT_AUTOMAKE([-Wall foreign])
+
+AC_PROG_CXX
+AC_PROG_LIBTOOL
+AC_PROG_MKDIR_P
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+LT_INIT
+
+DALI_VERSION=dali_version
+AC_SUBST(DALI_VERSION)
+
+DALI_CFLAGS=-DPLATFORM_TIZEN
+
+AC_ARG_ENABLE(exportall,
+              [AC_HELP_STRING([--enable-exportall],
+                              [enables the exporting of all the symbols in the library])],
+              [enable_exportall=yes],
+              [enable_exportall=no])
+
+AC_ARG_ENABLE([debug],
+              [AC_HELP_STRING([--enable-debug],
+                              [Turns on debugging])],
+              [enable_debug=$enableval],
+              [enable_debug=no])
+
+AC_ARG_ENABLE([emscripten],
+              [AC_HELP_STRING([--enable-emscripten],
+                              [Emscripten builds])],
+              [enable_emscripten=$enableval],
+              [enable_emscripten=no])
+
+AC_ARG_ENABLE([backtrace],
+              [AC_HELP_STRING([--enable-backtrace],
+                              [Backtrace for exceptions])],
+              [enable_backtrace=$enableval],
+              [enable_backtrace=yes])
+
+if test "x$enable_debug" = "xyes"; then
+  DALI_CFLAGS="$DALI_CFLAGS -DDEBUG_ENABLED"
+fi
+
+if test "x$enable_debug" = "xno" -a "x$enable_exportall" = "xno"; then
+  DALI_CFLAGS="$DALI_CFLAGS -fvisibility=hidden -DHIDE_DALI_INTERNALS"
+fi
+
+if test "x$enable_emscripten" = "xyes"; then
+  DALI_CFLAGS="$DALI_CFLAGS -DEMSCRIPTEN -std=c++11"
+  # Automatically turn off backtrace support
+  enable_backtrace="no"
+fi
+
+# Must come after Emscripten feature test
+if test "x$enable_backtrace" = "xyes"; then
+  DALI_CFLAGS="$DALI_CFLAGS -DBACKTRACE_ENABLED"
+fi
+
+if test x$DALI_DATA_RW_DIR != x; then
+  dataReadWriteDir=$DALI_DATA_RW_DIR
+else
+  dataReadWriteDir=${prefix}/share/dali/
+fi
+
+if test x$DALI_DATA_RO_DIR != x; then
+  dataReadOnlyDir=$DALI_DATA_RO_DIR
+else
+  dataReadOnlyDir=${prefix}/share/dali/
+fi
+
+DALI_CFLAGS="$DALI_CFLAGS -I${includedir}"
+DALI_LDFLAGS="-L${libdir}"
+
+AC_SUBST(dataReadWriteDir)
+AC_SUBST(dataReadOnlyDir)
+AC_SUBST(DALI_CFLAGS)
+AC_SUBST(DALI_LDFLAGS)
+
+# Specify the include directory for development headers
+devincludepath=${includedir}
+AC_SUBST(devincludepath)
+
+AC_CONFIG_FILES([
+ Makefile
+ dali-core/Makefile
+ dali-core.pc
+])
+
+AC_OUTPUT
+
+echo "
+Configuration
+-------------
+  Prefix:                           $prefix
+  Debug Build:                      $enable_debug
+  Data Dir (Read/Write):            $dataReadWriteDir
+  Data Dir (Read Only):             $dataReadOnlyDir
+  Emscripten:                       $enable_emscripten
+  Backtrace:                        $enable_backtrace
+"
diff --git a/build/tizen/dali-core.pc.in b/build/tizen/dali-core.pc.in
new file mode 100644 (file)
index 0000000..429a595
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+apiversion=@DALI_VERSION@
+libdir=@libdir@
+includedir=@devincludepath@
+
+Name: Samsung OpenGLES Toolkit
+Description: 3D Canvas Toolkit using OpenGLES
+Version: ${apiversion}
+Requires:
+Libs: -L${libdir} -ldali-core
+Cflags: -I${includedir}
diff --git a/build/tizen/dali-core/Makefile.am b/build/tizen/dali-core/Makefile.am
new file mode 100644 (file)
index 0000000..0f5f12e
--- /dev/null
@@ -0,0 +1,159 @@
+# Copyright (c) 2015 Samsung Electronics Co., Ltd.
+
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+
+# http://www.apache.org/licenses/LICENSE-2.0
+
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Parse each file.list
+# These files define <module>_src_files & <module>_header_files,
+# where <module> is the subdirectory from core_src_dir
+
+emoticons_dir = /usr/share/emoticons/
+
+internal_src_dir = ../../../dali/internal
+include ../../../dali/internal/file.list
+
+public_api_src_dir = ../../../dali/public-api
+include ../../../dali/public-api/file.list
+
+devel_api_src_dir = ../../../dali/devel-api
+include ../../../dali/devel-api/file.list
+
+platform_abstraction_src_dir = ../../../dali/integration-api
+include ../../../dali/integration-api/file.list
+
+# Build the Dali libtool library
+
+src_files = $(internal_src_files) \
+            $(effects_src_files) \
+            $(platform_abstraction_src_files) \
+            $(public_api_src_files) \
+            $(devel_api_src_files)
+
+lib_LTLIBRARIES = libdali-core.la
+
+libdali_core_la_SOURCES = $(dali_shaders_src_file) \
+                          $(src_files)
+
+scripts_dir = ../../scripts
+dali_shaders_script = $(scripts_dir)/generate-shader-strings.pl
+dali_shaders_dir = ../../../dali/internal/render/shader-source
+
+$(nodist_libdali_core_la_OBJECTS): $(dali_shaders_src_file)
+
+dali_shaders_src_file = dali-shaders.cpp
+
+dali-shaders.cpp: $(dali_shaders_script) $(dali_shaders_dir)/*.txt
+       $< --shader-dir=$(dali_shaders_dir) --file-name=dali-shaders
+
+dali_core_includes = \
+        -I../../..
+
+cxx_flags = -Werror -Wall -Wextra -Wno-unused-parameter -Wfloat-equal
+
+libdali_core_la_CXXFLAGS = -DDALI_COMPILATION \
+                           -DDALI_DATA_RW_DIR="\"${daliReadWriteDir}\"" \
+                           -DDALI_DATA_RO_DIR="\"${daliReadOnlyDir}\"" \
+                           -DDALI_EMOTICON_DIR="\"${emoticons_dir}\"" \
+                           $(cxx_flags) \
+                           $(dali_core_includes) \
+                           $(DALI_CFLAGS)
+
+libdali_core_la_LIBADD = $(DALI_LDFLAGS) \
+                         -lpthread
+
+# Install headers under the correct subdirectories
+platformabstractiondir = $(includedir)/dali/integration-api
+platformabstractioneventsdir = $(includedir)/dali/integration-api/events
+
+platformabstraction_HEADERS = $(platform_abstraction_header_files)
+platformabstractionevents_HEADERS = $(platform_abstraction_events_header_files)
+
+#devel api (used by adaptor / toolkit
+develapidir = $(devincludepath)/dali/devel-api
+develapiactorsdir = $(develapidir)/actors
+develapianimationdir = $(develapidir)/animation
+develapicommondir = $(develapidir)/common
+develapieventsdir = $(develapidir)/events
+develapigeometrydir = $(develapidir)/geometry
+develapiimagesdir = $(develapidir)/images
+develapimodelingdir = $(develapidir)/modeling
+develapiobjectdir = $(develapidir)/object
+develapirenderingdir = $(develapidir)/rendering
+develapiscriptingdir = $(develapidir)/scripting
+
+develapi_HEADERS = $(devel_api_header_files)
+develapiactors_HEADERS = $(devel_api_core_actors_header_files)
+develapianimation_HEADERS = $(devel_api_core_animation_header_files)
+develapicommon_HEADERS = $(devel_api_core_common_header_files)
+develapievents_HEADERS = $(devel_api_core_events_header_files)
+develapiimages_HEADERS = $(devel_api_core_images_header_files)
+develapimodeling_HEADERS = $(devel_api_core_modeling_header_files)
+develapiobject_HEADERS = $(devel_api_core_object_header_files)
+develapirendering_HEADERS = $(devel_api_core_rendering_header_files)
+develapiscripting_HEADERS = $(devel_api_core_scripting_header_files)
+
+
+
+#public api
+publicapidir = $(devincludepath)/dali/public-api
+publicapiactorsdir = $(publicapidir)/actors
+publicapianimationdir = $(publicapidir)/animation
+publicapicommondir = $(publicapidir)/common
+publicapieventsdir = $(publicapidir)/events
+publicapiimagesdir = $(publicapidir)/images
+publicapimathdir = $(publicapidir)/math
+publicapiobjectdir = $(publicapidir)/object
+publicapirendertasksdir = $(publicapidir)/render-tasks
+publicapishadereffectsdir = $(publicapidir)/shader-effects
+publicapisignalsdir = $(publicapidir)/signals
+
+publicapisizenegotiationdir = $(publicapidir)/size-negotiation
+
+publicapi_HEADERS = $(public_api_header_files)
+publicapiactors_HEADERS = $(public_api_core_actors_header_files)
+publicapianimation_HEADERS = $(public_api_core_animation_header_files)
+publicapicommon_HEADERS = $(public_api_core_common_header_files)
+publicapievents_HEADERS = $(public_api_core_events_header_files)
+publicapiimages_HEADERS = $(public_api_core_images_header_files)
+publicapimath_HEADERS = $(public_api_core_math_header_files)
+publicapirendertasks_HEADERS = $(public_api_core_render_tasks_header_files)
+publicapiobject_HEADERS = $(public_api_core_object_header_files)
+publicapisizenegotiation_HEADERS = $(public_api_core_size_negotiation_header_files)
+publicapishadereffects_HEADERS = $(public_api_core_shader_effects_header_files)
+publicapisignals_HEADERS = $(public_api_core_signals_header_files)
+
+CLEANFILES = dali-shaders.cpp \
+             dali-shaders.h
+
+# linking test
+
+noinst_PROGRAMS = linker.test
+
+linker_test_SOURCES = linker-test.cpp  \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-application.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-platform-abstraction.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-render-controller.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-gesture-manager.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-gl-sync-abstraction.cpp \
+    ../../../automated-tests/src/dali/dali-test-suite-utils/test-trace-call-stack.cpp
+
+linker_test_CXXFLAGS = \
+  $(cxx_flags) \
+  -I../../../automated-tests/src/dali/dali-test-suite-utils \
+  $(dali_core_includes) \
+  $(DALI_CFLAGS)
+
+linker_test_DEPENDENCIES = libdali-core.la
+linker_test_LDADD = \
+  libdali-core.la
diff --git a/build/tizen/dali-core/linker-test.cpp b/build/tizen/dali-core/linker-test.cpp
new file mode 100644 (file)
index 0000000..274c0dc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "dali/public-api/dali-core.h"
+
+#include <cstdio>
+#include <stdarg.h>
+
+// Link with TET Test application, need to redefine TET functions
+void tet_infoline(const char* str)
+{
+  puts(str);
+}
+
+void tet_printf(const char* str, ...)
+{
+  va_list args;
+  va_start(args, str);
+  vprintf(str, args);
+  va_end(args);
+}
+
+
+#include "test-application.h"
+
+/*****************************************************************************
+ * Test to see if dali is linking correctly.
+ * Only really tests that the internal function/method definitions exist and
+ * links to functions/methods in other libraries linked by Dali-Core.
+ * If a definition of the Public or Integration API does not exist, then it
+ * will not be checked here.
+ * Also ensures TET Test Application is kept up-to-date.
+ */
+
+int main(int argc, char **argv)
+{
+#ifndef _ARCH_ARM_
+  Dali::TestApplication application;
+#endif
+  return 0;
+}
diff --git a/dali.manifest b/dali.manifest
new file mode 100644 (file)
index 0000000..97e8c31
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
diff --git a/dali/.gitignore b/dali/.gitignore
new file mode 100644 (file)
index 0000000..6e92f57
--- /dev/null
@@ -0,0 +1 @@
+tags
diff --git a/dali/devel-api/animation/path-constrainer.cpp b/dali/devel-api/animation/path-constrainer.cpp
new file mode 100644 (file)
index 0000000..cb32010
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/animation/path-constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/path-constrainer-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+namespace Dali
+{
+
+PathConstrainer PathConstrainer::New()
+{
+  Internal::PathConstrainer* internal = Internal::PathConstrainer::New();
+  return PathConstrainer(internal);
+}
+
+PathConstrainer PathConstrainer::DownCast( BaseHandle handle )
+{
+  return PathConstrainer( dynamic_cast<Dali::Internal::PathConstrainer*>(handle.GetObjectPtr()) );
+}
+
+PathConstrainer::PathConstrainer()
+{
+}
+
+PathConstrainer::~PathConstrainer()
+{
+}
+
+PathConstrainer::PathConstrainer(const PathConstrainer& handle)
+:Handle(handle)
+{
+}
+
+PathConstrainer::PathConstrainer(Internal::PathConstrainer* internal)
+: Handle(internal)
+{
+}
+
+PathConstrainer& PathConstrainer::operator=(const PathConstrainer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void PathConstrainer::Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap )
+{
+  GetImplementation(*this).Apply( target, source, range, wrap );
+}
+
+void PathConstrainer::Remove( Dali::Handle& target )
+{
+  GetImplementation(*this).Remove( target );
+}
+
+
+} // Dali
diff --git a/dali/devel-api/animation/path-constrainer.h b/dali/devel-api/animation/path-constrainer.h
new file mode 100644 (file)
index 0000000..6790a25
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef __DALI_PATH_CONSTRAINER_H__
+#define __DALI_PATH_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//EXTERNAL INCLUDES
+#include <cfloat> //For FLT_MAX
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/path.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+  class PathConstrainer;
+}
+/**
+ * @brief
+ *
+ * PathConstrainer applies constraints to objects to follow a path.
+ * A Vector3 property will be constrained to the position of the path and a Rotation property will be constrained to follow
+ * the tangent of the path given a forward vector in object's local space.
+ *
+ */
+class DALI_IMPORT_API PathConstrainer : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the PathConstrainer class.
+   */
+  struct Property
+  {
+    enum
+    {
+      FORWARD   =  DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "forward" type Vector3
+      POINTS,                                           ///< name "points" type Array of Vector3
+      CONTROL_POINTS                                    ///< name "control-points" type Array of Vector3
+    };
+  };
+
+  /**
+   * @brief Create an initialized PathConstrainer handle.
+   *
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static PathConstrainer New();
+
+  /**
+   * @brief Downcast an Object handle to PathConstrainer handle.
+   *
+   * If handle points to a PathConstrainer object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @param[in] handle to An object
+   * @return handle to a PathConstrainer object or an uninitialized handle
+   */
+  static PathConstrainer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized PathConstrainer handle.
+   *
+   * This can be initialized with PathConstrainer::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   */
+  PathConstrainer();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~PathConstrainer();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  PathConstrainer(const PathConstrainer& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  PathConstrainer& operator=(const PathConstrainer& rhs);
+
+  /**
+   * @brief Applies the path constraint to the target property
+   *
+   * @param[in] target Property to be constrained
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  void Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap = Vector2(-FLT_MAX, FLT_MAX) );
+
+  /**
+   * @brief Removes the path constraint in the target object
+   *
+   * @param[in] target A handle to an object constrained by the PathConstrainer
+   */
+  void Remove( Dali::Handle& target );
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @param[in] pathConstrainer A pointer to an internal PathConstrainer resource
+   */
+  explicit DALI_INTERNAL PathConstrainer(Internal::PathConstrainer* pathConstrainer);
+};
+
+} // namespace Dali
+
+#endif // __DALI_PATH_CONSTRAINER_H__
diff --git a/dali/devel-api/common/hash.cpp b/dali/devel-api/common/hash.cpp
new file mode 100644 (file)
index 0000000..1cfcf11
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/common/hash.h>
+
+namespace Dali
+{
+
+namespace //unnamed namespace
+{
+
+/*
+ * djb2 (http://www.cse.yorku.ca/~oz/hash.html)
+ */
+const std::size_t INITIAL_HASH_VALUE = 5381;
+
+inline void HashString( const char* string, std::size_t& hash )
+{
+  while( int c = *string++ )
+  {
+    hash = hash * 33 + c;
+  }
+}
+
+} // unnamed namespace
+
+std::size_t CalculateHash( const std::string& toHash)
+{
+  std::size_t hash( INITIAL_HASH_VALUE );
+
+  HashString( toHash.c_str(), hash );
+
+  return hash;
+}
+
+std::size_t CalculateHash( const std::string& string1, const std::string& string2 )
+{
+  std::size_t hash( INITIAL_HASH_VALUE );
+
+  HashString( string1.c_str(), hash);
+  HashString( string2.c_str(), hash );
+
+  return hash;
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/common/hash.h b/dali/devel-api/common/hash.h
new file mode 100644 (file)
index 0000000..246907b
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_HASH__
+#define __DALI_HASH__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+//INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Create a hash code for a string
+ * @param toHash string to hash
+ * @return hash code
+ */
+DALI_IMPORT_API std::size_t CalculateHash( const std::string& toHash );
+
+/**
+ * @brief Create a hash code for 2 strings combined.
+ * Allows a hash to be calculated without concatenating the strings and allocating any memory.
+ * @param string1 first string
+ * @param string2 second string
+ * @return hash code
+ */
+DALI_IMPORT_API std::size_t CalculateHash( const std::string& string1, const std::string& string2 );
+
+} // namespace Dali
+
+#endif // __DALI_HASH__
diff --git a/dali/devel-api/common/map-wrapper.h b/dali/devel-api/common/map-wrapper.h
new file mode 100644 (file)
index 0000000..070f0e9
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_MAP_H__
+#define __DALI_MAP_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+
+#ifndef HIDE_DALI_INTERNALS
+
+# include <map>
+
+#else
+
+// ensure that default visibility is used with any class that is used as an exception type
+# include <memory>
+# include <new>
+# include <stdexcept>
+
+# include <bits/c++config.h>
+# include <bits/stl_tree.h>
+# undef _GLIBCXX_VISIBILITY_ATTR
+# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden")))
+# include <map>
+# undef _GLIBCXX_VISIBILITY_ATTR
+# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR`
+
+#endif //ifndef HIDE_DALI_INTERNALS
+
+
+#endif /* __DALI_MAP_H__ */
diff --git a/dali/devel-api/common/mutex.cpp b/dali/devel-api/common/mutex.cpp
new file mode 100644 (file)
index 0000000..37f9d33
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/common/mutex.h>
+
+// EXTERNAL INCLUDES
+#include <pthread.h>
+
+namespace Dali
+{
+
+struct Mutex::MutexImpl
+{
+  pthread_mutex_t mutex;
+  bool locked;
+};
+
+Mutex::Mutex()
+: mImpl( new MutexImpl )
+{
+  pthread_mutex_init( &mImpl->mutex, NULL );
+  mImpl->locked = false;
+}
+
+Mutex::~Mutex()
+{
+  pthread_mutex_destroy( &mImpl->mutex );
+  // nothing else to do as there is no Lock/Unlock API
+  // ScopedLock destructor will always unlock the mutex
+  delete mImpl;
+}
+
+bool Mutex::IsLocked()
+{
+  return mImpl->locked;
+}
+
+Mutex::ScopedLock::ScopedLock( Mutex& mutex )
+: mMutex( mutex )
+{
+  pthread_mutex_lock( &mMutex.mImpl->mutex );
+  mMutex.mImpl->locked = true;
+}
+
+Mutex::ScopedLock::~ScopedLock()
+{
+  mMutex.mImpl->locked = false;
+  pthread_mutex_unlock( &mMutex.mImpl->mutex );
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/common/mutex.h b/dali/devel-api/common/mutex.h
new file mode 100644 (file)
index 0000000..cd41f9a
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef __DALI_MUTEX_H__
+#define __DALI_MUTEX_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+/**
+ * The top level DALi namespace
+ */
+namespace Dali
+{
+
+/**
+ * Class to synchronize access to critical resources from multiple threads
+ */
+class DALI_IMPORT_API Mutex
+{
+public:
+
+  /**
+   * @brief Constructor, acquires the mutex from the underlying OS
+   */
+  Mutex();
+
+  /**
+   * @brief Destructor, non virtual as this is not meant as a base class
+   */
+  ~Mutex();
+
+  /**
+   * @brief Check if the mutex is locked
+   * @return true if the mutex is locked
+   */
+  bool IsLocked();
+
+public:
+
+  /**
+   * Helper class to do a scoped lock on a mutex implementing the RAII idiom.
+   * Note! this class *does not* prevent a deadlock in the case when same thread is
+   * locking the same mutex twice.
+   */
+  class ScopedLock
+  {
+  public:
+
+    /**
+     * Constructor
+     * @param mutex to lock
+     */
+    ScopedLock( Mutex& mutex );
+
+    /**
+     * Destructor, releases the lock
+     */
+    ~ScopedLock();
+
+  private:
+    Mutex& mMutex;
+  };
+
+private:
+
+  /// Not implemented as Mutex is not copyable
+  Mutex( const Mutex& );
+  const Mutex& operator= ( const Mutex& );
+
+  struct MutexImpl;
+  MutexImpl* mImpl;
+
+};
+
+} // namespace Dali
+
+#endif // __DALI_MUTEX_H__
diff --git a/dali/devel-api/common/ref-counted-dali-vector.h b/dali/devel-api/common/ref-counted-dali-vector.h
new file mode 100644 (file)
index 0000000..d3719d7
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __REF_COUNTED_DALI_VECTOR_H__
+#define __REF_COUNTED_DALI_VECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+/**
+ * @brief A reference counting wrapper for a vector class that allows
+ * a set of referencing smart pointers to collaborate in managing its
+ * lifetime and eventually cleaning it up.
+ *
+ * This should only be allocated on the new/delete heap, not a thread's
+ * stack.
+ * @tparam T type of the data that the vector holds
+ */
+template< typename T >
+class RefCountedVector : public RefObject
+{
+public:
+  /**
+   * @brief Construct empty vector.
+   */
+  RefCountedVector()
+  {
+  }
+
+  /**
+   * @brief Get the referenced vector.
+   *
+   * @return A reference to the vector that this object wraps.
+   */
+  Vector< T >& GetVector()
+  {
+    return mVector;
+  }
+
+protected:
+  virtual ~RefCountedVector()
+  {
+  }
+
+private:
+  // Disable copy-constructing and copying:
+  RefCountedVector(const RefCountedVector &); ///< Undefined
+  RefCountedVector & operator = (const RefCountedVector &); ///< Undefined
+
+  Vector< T > mVector; ///< The vector of data
+};
+
+} // namespace Dali
+
+#endif /* __REF_COUNTED_DALI_VECTOR_H__ */
diff --git a/dali/devel-api/common/set-wrapper.h b/dali/devel-api/common/set-wrapper.h
new file mode 100644 (file)
index 0000000..d3b3ab1
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DALI_SET_H__
+#define __DALI_SET_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// EXTERNAL INCLUDES
+
+#ifndef HIDE_DALI_INTERNALS
+
+# include <set>
+
+#else
+
+// ensure that default visibility is used with any class that is used as an exception type
+# include <memory>
+# include <new>
+# include <stdexcept>
+
+# include <bits/c++config.h>
+# include <bits/stl_tree.h>
+# undef _GLIBCXX_VISIBILITY_ATTR
+# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden")))
+# include <set>
+# undef _GLIBCXX_VISIBILITY_ATTR
+# define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR`
+
+#endif //ifndef HIDE_DALI_INTERNALS
+
+#endif /* __DALI_SET_H__ */
diff --git a/dali/devel-api/events/hit-test-algorithm.cpp b/dali/devel-api/events/hit-test-algorithm.cpp
new file mode 100644 (file)
index 0000000..666143c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/events/hit-test-algorithm.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace HitTestAlgorithm
+{
+
+bool HitTest( Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func )
+{
+  return Internal::HitTestAlgorithm::HitTest( GetImplementation(stage), screenCoordinates, results, func );
+}
+
+bool HitTest( RenderTask& renderTask, const Vector2& screenCoordinates, Results& results, HitTestFunction func )
+{
+  Stage stage = Stage::GetCurrent();
+  return Internal::HitTestAlgorithm::HitTest( GetImplementation( stage ), GetImplementation(renderTask), screenCoordinates, results, func );
+}
+
+} // namespace HitTestAlgorithm
+
+} // namespace Dali
diff --git a/dali/devel-api/events/hit-test-algorithm.h b/dali/devel-api/events/hit-test-algorithm.h
new file mode 100644 (file)
index 0000000..913a2af
--- /dev/null
@@ -0,0 +1,163 @@
+#ifndef  __DALI_HIT_TEST_ALGORITHM_H__
+#define  __DALI_HIT_TEST_ALGORITHM_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/stage.h>
+
+
+namespace Dali
+{
+
+class RenderTask;
+
+/**
+ * @brief This namespace is provided for application developers to do hit-test for the actors.
+ *
+ * <h3>Hit Test Algorithm:</h3>
+ *
+ * Hit testing is dependent on the camera used, which is specific to each RenderTask. For each RenderTask,
+ * hit testing starts from the top-most layer and we go through all the layers until we have a hit or there
+ * are none left. Before we perform a hit test within a layer, we check if all the layer's parents meet the
+ * conditions defined by the function ((e.g. whether it is visible)). If they are not, we skip hit testing
+ * the actors in that layer altogether. Otherwise, we walk through the actor tree within a layer to check
+ * whether the actors within the actor tree should be hit-tested.
+ *
+ * The following pseudocode gives an example of what the function can typically check, which should normally
+ * be provided by the application code:
+ *
+ *   @code
+ *   HIT-TEST-FUNCTION( ACTOR, TRAVERSE-TYPE )
+ *   {
+ *     if( TRAVERSE-TYPE == CHECK_ACTOR ) // Check whether current actor should be hit-tested
+ *     {
+ *       if( ACTOR-IS-VISIBLE &&
+ *           ACTOR-WORLD-COLOR-IS-NOT-TRANSPARENT )
+ *       {
+ *         HITTABLE = TRUE
+ *       }
+ *     }
+ *     else if( TRAVERSE-TYPE == DESCEND_ACTOR_TREE ) ///< Check whether the actor tree should be descended to hit-test its children.
+ *     {
+ *       if( ACTOR-IS-VISIBLE )
+ *       {
+ *         HITTABLE = TRUE
+ *       }
+ *     }
+ *   }
+ *   @endcode
+ *
+ * The following pseudocode explains how the algorithm performs the hit-test with the above functor:
+ *
+ *   @code
+ *   HIT-TEST-WITHIN-LAYER( ACTOR )
+ *   {
+ *     // Depth-first traversal within current layer, visiting parent first
+ *
+ *     // Check whether current actor should be hit-tested
+ *     IF ( HIT-TEST-FUNCTION( ACTOR, CHECK_ACTOR ) &&
+ *          ACTOR-HAS-NON-ZERO-SIZE )
+ *     {
+ *       // Hit-test current actor
+ *       IF ( ACTOR-HIT )
+ *       {
+ *         IF ( DISTANCE-TO-ACTOR < DISTANCE-TO-LAST-HIT-ACTOR )
+ *         {
+ *           // The current actor is the closest actor that was underneath the touch
+ *           LAST-HIT-ACTOR = CURRENT-ACTOR
+ *         }
+ *       }
+ *     }
+ *
+ *     // Keep checking children, in case we hit something closer
+ *     FOR-EACH CHILD (in order)
+ *     {
+ *       IF ( HIT-TEST-FUNCTION( ACTOR, DESCEND_ACTOR_TREE ) &&
+ *            ACTOR-IS-NOT-A-LAYER )
+ *       {
+ *         // Continue traversal for this child's sub-tree
+ *         HIT-TEST-WITHIN-LAYER ( CHILD )
+ *       }
+ *       // else we skip the sub-tree with from this child
+ *     }
+ *   }
+ *   @endcode
+ */
+namespace HitTestAlgorithm
+{
+
+/**
+ * @brief How the actor tree should be traversed.
+ */
+enum TraverseType
+{
+  CHECK_ACTOR,            ///< Hit test the given actor.
+  DESCEND_ACTOR_TREE      ///< Check whether the actor tree should be descended to hit-test its children.
+};
+
+/**
+ * @brief Results structure containing the hit actor and where it was hit.
+ */
+struct Results
+{
+  Actor      actor;            ///< The hit actor.
+  Vector2    actorCoordinates; ///< The actor coordinates.
+};
+
+/**
+ * @brief Definition of a hit-test function to use in HitTest() method to check if the actor is hittable (e.g. touchable or focusable).
+ *
+ * @return true, if the actor is hittable, false otherwise.
+ */
+typedef bool (*HitTestFunction)(Actor actor, TraverseType type);
+
+/**
+ * @brief Given screen coordinates, this method returns the hit actor & the local coordinates relative to
+ * the top-left (0.0f, 0.0f, 0.5f) of the actor.
+ *
+ * An actor is only hittable if the actor meets all the conditions
+ * defined by the given function (see HitTestAlgorithm).
+ *
+ * Typically, if an actor has a zero size or its world color is fully transparent, it should not be
+ * hittable; and if an actor's visibility flag is unset, its children should not be hittable either.
+ *
+ * @param[in] stage The stage.
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] results The results of the hit-test, only modified if something is hit
+ * @param[in] func The function to use in the hit-test algorithm.
+ * @return true if something was hit
+ */
+DALI_IMPORT_API bool HitTest( Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func );
+
+/**
+ * @brief Hit test specific to a given RenderTask.
+ *
+ * @param[in] renderTask The render task for hit test
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] results The results of the hit-test, only modified if something is hit
+ * @param[in] func The function to use in the hit-test algorithm.
+ * @return true if something was hit
+ */
+DALI_IMPORT_API bool HitTest( RenderTask& renderTask, const Vector2& screenCoordinates, Results& results, HitTestFunction func );
+
+} // namespace HitTestAlgorithm
+
+} // namespace Dali
+
+#endif // __DALI_HIT_TEST_ALGORITHM_H__
diff --git a/dali/devel-api/file.list b/dali/devel-api/file.list
new file mode 100644 (file)
index 0000000..5c00ebf
--- /dev/null
@@ -0,0 +1,55 @@
+# Add devel source files here for DALi internal developer files used by Adaptor & Toolkit
+
+devel_api_src_files = \
+  $(devel_api_src_dir)/animation/path-constrainer.cpp \
+  $(devel_api_src_dir)/common/hash.cpp \
+  $(devel_api_src_dir)/common/mutex.cpp \
+  $(devel_api_src_dir)/events/hit-test-algorithm.cpp \
+  $(devel_api_src_dir)/images/atlas.cpp \
+  $(devel_api_src_dir)/images/distance-field.cpp \
+  $(devel_api_src_dir)/object/property-buffer.cpp \
+  $(devel_api_src_dir)/object/weak-handle.cpp \
+  $(devel_api_src_dir)/rendering/cull-face.cpp \
+  $(devel_api_src_dir)/rendering/geometry.cpp \
+  $(devel_api_src_dir)/rendering/material.cpp \
+  $(devel_api_src_dir)/rendering/renderer.cpp \
+  $(devel_api_src_dir)/rendering/sampler.cpp \
+  $(devel_api_src_dir)/rendering/shader.cpp \
+  $(devel_api_src_dir)/scripting/scripting.cpp
+
+# Add devel header files here DALi internal developer files used by Adaptor & Toolkit
+
+devel_api_core_animation_header_files = \
+  $(devel_api_src_dir)/animation/path-constrainer.h
+
+devel_api_core_common_header_files = \
+  $(devel_api_src_dir)/common/hash.h \
+  $(devel_api_src_dir)/common/map-wrapper.h \
+  $(devel_api_src_dir)/common/mutex.h \
+  $(devel_api_src_dir)/common/ref-counted-dali-vector.h \
+    $(devel_api_src_dir)/common/set-wrapper.h
+
+devel_api_core_events_header_files = \
+  $(devel_api_src_dir)/events/hit-test-algorithm.h
+
+devel_api_core_images_header_files = \
+  $(devel_api_src_dir)/images/atlas.h \
+  $(devel_api_src_dir)/images/distance-field.h
+
+devel_api_core_object_header_files = \
+  $(devel_api_src_dir)/object/property-buffer.h \
+  $(devel_api_src_dir)/object/type-registry-helper.h \
+  $(devel_api_src_dir)/object/weak-handle.h
+
+devel_api_core_rendering_header_files = \
+  $(devel_api_src_dir)/rendering/cull-face.h \
+  $(devel_api_src_dir)/rendering/geometry.h \
+  $(devel_api_src_dir)/rendering/material.h \
+  $(devel_api_src_dir)/rendering/renderer.h \
+  $(devel_api_src_dir)/rendering/sampler.h \
+  $(devel_api_src_dir)/rendering/shader.h
+
+devel_api_core_scripting_header_files = \
+  $(devel_api_src_dir)/scripting/scripting.h
+
+
diff --git a/dali/devel-api/images/atlas.cpp b/dali/devel-api/images/atlas.cpp
new file mode 100644 (file)
index 0000000..f7f96d1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/images/atlas.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/atlas-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
+
+namespace Dali
+{
+
+Atlas Atlas::New( SizeType width,
+                  SizeType height,
+                  Pixel::Format pixelFormat,
+                  bool recoverContext )
+{
+  DALI_ASSERT_ALWAYS( 0u != width  && "Invalid Atlas width requested" );
+  DALI_ASSERT_ALWAYS( 0u != height && "Invalid Atlas height requested" );
+
+  return Atlas( Internal::Atlas::New( width, height, pixelFormat, recoverContext ) );
+}
+
+Atlas::Atlas()
+{
+}
+
+void Atlas::Clear( const Vector4& color  )
+{
+  GetImplementation( *this ).Clear( color );
+}
+
+bool Atlas::Upload( BufferImage bufferImage,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  return GetImplementation(*this).Upload( GetImplementation(bufferImage), xOffset, yOffset );
+}
+
+bool Atlas::Upload( const std::string& url,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  return GetImplementation(*this).Upload( url, xOffset, yOffset );
+}
+
+Atlas Atlas::DownCast( BaseHandle handle )
+{
+  return Atlas( dynamic_cast<Dali::Internal::Atlas*>(handle.GetObjectPtr()) );
+}
+
+Atlas::~Atlas()
+{
+}
+
+Atlas::Atlas( const Atlas& handle )
+: Image( handle )
+{
+}
+
+Atlas& Atlas::operator=( const Atlas& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+Atlas::Atlas( Internal::Atlas* internal )
+: Image( internal )
+{
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/images/atlas.h b/dali/devel-api/images/atlas.h
new file mode 100644 (file)
index 0000000..025b9ad
--- /dev/null
@@ -0,0 +1,156 @@
+#ifndef __DALI_ATLAS_H__
+#define __DALI_ATLAS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/buffer-image.h>
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Atlas;
+}
+
+/**
+ * @brief An Atlas is a large image containing multiple smaller images.
+ *
+ * Buffer image and resource image( by providing the url ) are supported for uploading.
+ * Images must be uploaded at a specified position, to populate the Atlas.
+ * The client is responsible for generating the appropriate geometry (UV coordinates) needed to draw images within the Atlas.
+ *
+ * For context recovery after loss:
+ * By default, the atlas will re-upload the resource images automatically,
+ * while the buffer images are left to the client to upload again by connecting to the Stage::ContextRegainedSignal().
+ * If resource and buffer images are mixed and they overlap inside the atlas, the recovered contents may be incorrect.
+ * In these case, switch off the context recovery by calling SetContextRecovery( false ),
+ * and upload both buffer images and resource image to the atlas in order to restore the atlas.
+ */
+class DALI_IMPORT_API Atlas : public Image
+{
+public:
+
+  typedef uint32_t SizeType;
+
+public:
+
+  /**
+   * @brief Create a new Atlas.
+   *
+   * @pre width & height are greater than zero.
+   * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format (rgba 32 bit by default).
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context( true by default )
+   * @return A handle to a new Atlas.
+   */
+  static Atlas New( SizeType width,
+                    SizeType height,
+                    Pixel::Format pixelFormat = Pixel::RGBA8888,
+                    bool recoverContext = true );
+
+  /**
+   * @brief Create an empty handle.
+   *
+   * Calling member functions of an empty handle is not allowed.
+   */
+  Atlas();
+
+  /**
+   * @brief Clear the Atlas with the given color
+   *
+   * @note The Atlas does not clear itself automatically during construction.
+   * Application should call this clear function to avoid getting garbage pixels in the atlas.
+   * By calling Clear, all the current uploaded image information will be lost.
+   * @param [in] color The color used to clear the Atlas.
+   */
+  void Clear( const Vector4& color  );
+
+  /**
+   * @brief Upload a buffer image to the atlas.
+   *
+   * @pre The pixel format of this buffer image must match the Atlas format.
+   * @param [in] bufferImage The buffer image to upload.
+   * @param [in] xOffset Specifies an offset in the x direction within the atlas.
+   * @param [in] yOffset Specifies an offset in the y direction within the atlas.
+   * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
+   */
+  bool Upload( BufferImage bufferImage,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
+   * @brief Upload a resource image to atlas
+   *
+   * @param [in] url The URL of the resource image file to use
+   * @param [in] xOffset Specifies an offset in the x direction within the atlas.
+   * @param [in] yOffset Specifies an offset in the y direction within the atlas.
+   * @return True if the image has compatible pixel format and fits within the atlas at the specified offset.
+   */
+  bool Upload( const std::string& url,
+               SizeType xOffset,
+               SizeType yOffset );
+  /**
+   * @brief Downcast an Object handle to Atlas.
+   *
+   * If handle points to a Atlas the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @param[in] handle to An object
+   * @return handle to a Atlas or an empty handle
+   */
+  static Atlas DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~Atlas();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @param [in] handle A reference to the copied handle
+   */
+  Atlas( const Atlas& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Atlas& operator=( const Atlas& rhs);
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL Atlas( Internal::Atlas* );
+};
+
+} // namespace Dali
+
+#endif // __DALI_ATLAS_H__
diff --git a/dali/devel-api/images/distance-field.cpp b/dali/devel-api/images/distance-field.cpp
new file mode 100644 (file)
index 0000000..134f9c4
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/images/distance-field.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+#include <math.h>
+#include <stdio.h>
+#include <time.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/math-utils.h>
+
+namespace Dali
+{
+
+namespace
+{
+
+float Interpolate( float a, float b, float factor )
+{
+  return a * (1.0f - factor) + b * factor;
+}
+
+float Bilinear( float a, float b, float c, float d, float dx, float dy )
+{
+  return Interpolate( Interpolate( a, b, dx), Interpolate( c, d, dx ), dy );
+}
+
+void ScaleField( int width, int height, float* in, int targetWidth, int targetHeight, float* out )
+{
+  float xScale = static_cast< float >(width) / targetWidth;
+  float yScale = static_cast< float >(height) / targetHeight;
+
+  // for each row in target
+  for(int y = 0; y < targetHeight; ++y)
+  {
+    const int sampleY = static_cast< int >( yScale * y );
+    const int otherY = std::min( sampleY + 1, height - 1 );
+    const float dy = (yScale * y ) - sampleY;
+
+    // for each column in target
+    for (int x = 0; x < targetWidth; ++x)
+    {
+      const int sampleX = static_cast< int >( xScale * x );
+      const int otherX = std::min( sampleX + 1, width - 1 );
+      const float dx = (xScale * x) - sampleX;
+
+      float value = Bilinear( in[ sampleY * width + sampleX ],
+                              in[ sampleY * width + otherX ],
+                              in[ otherY * width + sampleX ],
+                              in[ otherY * width + otherX ],
+                              dx, dy );
+
+      out[y * targetWidth + x] = std::min( value, 1.0f );
+    }
+  }
+}
+
+#define SQUARE(a) ((a) * (a))
+const float MAX_DISTANCE( 1e20 );
+
+/**
+ * Distance transform of 1D function using squared distance
+ */
+void DistanceTransform( float *source, float* dest, unsigned int length )
+{
+  int parabolas[length];    // Locations of parabolas in lower envelope
+  float edge[length + 1];   // Locations of boundaries between parabolas
+  int rightmost(0);         // Index of rightmost parabola in lower envelope
+
+  parabolas[0] = 0;
+  edge[0] = -MAX_DISTANCE;
+  edge[1] = +MAX_DISTANCE;
+  for( unsigned int i = 1; i <= length - 1; i++ )
+  {
+    const float initialDistance( source[i] + SQUARE( i ) );
+    int parabola = parabolas[rightmost];
+    float newDistance( (initialDistance - (source[parabola] + SQUARE( parabola ))) / (2 * i - 2 * parabola) );
+    while( rightmost > 0 && newDistance <= edge[rightmost] )
+    {
+      rightmost--;
+      parabola = parabolas[rightmost];
+      newDistance = (initialDistance - (source[parabola] + SQUARE( parabola ))) / (2 * i - 2 * parabola);
+    }
+
+    rightmost++;
+    parabolas[rightmost] = i;
+    edge[rightmost] = newDistance;
+    edge[rightmost + 1] = MAX_DISTANCE;
+  }
+
+  rightmost = 0;
+  for( unsigned int i = 0; i <= length - 1; ++i )
+  {
+    while( edge[rightmost + 1] < i )
+    {
+      ++rightmost;
+    }
+    dest[i] = SQUARE( i - parabolas[rightmost] ) + source[parabolas[rightmost]];
+  }
+}
+
+/**
+ * Distance transform of 2D function using squared distance
+ */
+void DistanceTransform( float* data, unsigned int width, unsigned int height, float* sourceBuffer, float* destBuffer )
+{
+  // transform along columns
+  for( unsigned int x = 0; x < width; ++x )
+  {
+    for( unsigned int y = 0; y < height; ++y )
+    {
+      sourceBuffer[y] = data[ y * width + x ];
+    }
+
+    DistanceTransform( sourceBuffer, destBuffer, height );
+
+    for( unsigned int y = 0; y < height; y++ )
+    {
+      data[y * width + x] = destBuffer[y];
+    }
+  }
+
+  // transform along rows
+  for( unsigned int y = 0; y < height; ++y )
+  {
+    for( unsigned int x = 0; x < width; ++x )
+    {
+      sourceBuffer[x] = data[ y * width + x ];
+    }
+
+    DistanceTransform( sourceBuffer, destBuffer, width );
+
+    for( unsigned int x = 0; x < width; x++ )
+    {
+      data[y * width + x] = destBuffer[x];
+    }
+  }
+}
+
+} // namespace
+
+void GenerateDistanceFieldMap(const unsigned char* const imagePixels, const Size& imageSize,
+                              unsigned char* const distanceMap, const Size& distanceMapSize,
+                              const float fieldRadius, const unsigned int fieldBorder, bool highQuality)
+{
+  GenerateDistanceFieldMap( imagePixels, imageSize, distanceMap, distanceMapSize, fieldBorder, imageSize, highQuality );
+}
+
+void GenerateDistanceFieldMap(const unsigned char* const imagePixels, const Size& imageSize,
+                              unsigned char* const distanceMap, const Size& distanceMapSize,
+                              const unsigned int fieldBorder,
+                              const Vector2& maxSize,
+                              bool highQuality)
+{
+  // constants to reduce redundant calculations
+  const int originalWidth( static_cast<int>(imageSize.width) );
+  const int originalHeight( static_cast<int>(imageSize.height) );
+  const int paddedWidth( originalWidth + (fieldBorder * 2 ) );
+  const int paddedHeight( originalHeight + (fieldBorder * 2 ) );
+  const int scaledWidth( static_cast<int>(distanceMapSize.width) );
+  const int scaledHeight( static_cast<int>(distanceMapSize.height) );
+  const int maxWidth( static_cast<int>(maxSize.width) + (fieldBorder * 2 ));
+  const int maxHeight( static_cast<int>(maxSize.height) + (fieldBorder * 2 ) );
+
+  const int bufferLength( std::max( maxWidth, std::max(paddedWidth, scaledWidth) ) *
+                          std::max( maxHeight, std::max(paddedHeight, scaledHeight) ) );
+
+  std::vector<float> outsidePixels( bufferLength, 0.0f );
+  std::vector<float> insidePixels( bufferLength, 0.0f );
+
+  float* outside( outsidePixels.data() );
+  float* inside( insidePixels.data() );
+
+  for( int y = 0; y < paddedHeight; ++y )
+  {
+    for ( int x = 0; x < paddedWidth; ++x)
+    {
+      if( y < (int)fieldBorder || y >= (paddedHeight - (int)fieldBorder) ||
+          x < (int)fieldBorder || x >= (paddedWidth - (int)fieldBorder) )
+      {
+        outside[ y * paddedWidth + x ] = MAX_DISTANCE;
+        inside[ y * paddedWidth + x ] = 0.0f;
+      }
+      else
+      {
+        unsigned int pixel( imagePixels[ (y - fieldBorder) * originalWidth + (x - fieldBorder) ] );
+        outside[ y * paddedWidth + x ] = (pixel == 0) ? MAX_DISTANCE : SQUARE((255 - pixel) / 255.0f);
+        inside[ y * paddedWidth + x ] = (pixel == 255) ? MAX_DISTANCE : SQUARE(pixel / 255.0f);
+      }
+    }
+  }
+
+  // perform distance transform if high quality requested, else use original figure
+  if( highQuality )
+  {
+    // create temporary buffers for DistanceTransform()
+    const int tempBufferLength( std::max(paddedWidth, paddedHeight) );
+    std::vector<float> tempSourceBuffer( tempBufferLength, 0.0f );
+    std::vector<float> tempDestBuffer( tempBufferLength, 0.0f );
+
+    // Perform distance transform for pixels 'outside' the figure
+    DistanceTransform( outside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() );
+
+    // Perform distance transform for pixels 'inside' the figure
+    DistanceTransform( inside, paddedWidth, paddedHeight, tempSourceBuffer.data(), tempDestBuffer.data() );
+  }
+
+  // distmap = outside - inside; % Bipolar distance field
+  for( int y = 0; y < paddedHeight; ++y)
+  {
+    for( int x = 0; x < paddedWidth; ++x )
+    {
+      const int offset( y * paddedWidth + x );
+      float pixel( sqrtf(outside[offset]) - sqrtf(inside[offset]) );
+      pixel = 128.0f + pixel * 16.0f;
+      pixel = Clamp( pixel, 0.0f, 255.0f );
+      outside[offset] = (255.0f - pixel) / 255.0f;
+    }
+  }
+
+  // scale the figure to the distance field tile size
+  ScaleField( paddedWidth, paddedHeight, outside, scaledWidth, scaledHeight, inside );
+
+  // convert from floats to integers
+  for( int y = 0; y < scaledHeight; ++y )
+  {
+    for( int x = 0; x < scaledWidth; ++x )
+    {
+      float pixel( inside[ y * scaledWidth + x ] );
+      distanceMap[y * scaledWidth + x ] = static_cast< unsigned char >(pixel * 255.0f);
+    }
+  }
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/images/distance-field.h b/dali/devel-api/images/distance-field.h
new file mode 100644 (file)
index 0000000..d0ebf2a
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __DALI_DISTANCE_FIELD_H__
+#define __DALI_DISTANCE_FIELD_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+struct Vector2;
+
+/**
+ * @brief Generate a distance field map from a source image.
+ *
+ * @param[in]  imagePixels     A pointer to a buffer containing the source image
+ * @param[in]  imageSize       The size, width and height, of the source image
+ * @param[out] distanceMap     A pointer to a buffer to receive the calculated distance field map.
+ *                             Note: This must not overlap with imagePixels for correct distance field map generation.
+ * @param[in]  distanceMapSize The size, width and height, of the distance field map
+ * @param[in]  fieldBorder     The amount of distance field cells to add around the data (for glow/shadow effects)
+ * @param[in]  maxSize         The image is scaled from this size to distanceMapSize
+ * @param[in]  highQuality     Set true to generate high quality distance fields
+ */
+DALI_IMPORT_API void GenerateDistanceFieldMap( const unsigned char* const imagePixels, const Vector2& imageSize,
+                                               unsigned char* const distanceMap, const Vector2& distanceMapSize,
+                                               const unsigned int fieldBorder,
+                                               const Vector2& maxSize,
+                                               bool highQuality = true);
+
+} //namespace Dali
+
+#endif // ifndef __DALI_DISTANCE_FIELD_H__
diff --git a/dali/devel-api/object/property-buffer.cpp b/dali/devel-api/object/property-buffer.cpp
new file mode 100644 (file)
index 0000000..9eb3d39
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/object/property-buffer.h> // Dali::PropertyBuffer
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-map.h> // Dali::Property::Map
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
+
+namespace Dali
+{
+
+PropertyBuffer PropertyBuffer::New( Dali::Property::Map& bufferFormat, std::size_t size )
+{
+  Internal::PropertyBufferPtr propertyBuffer = Internal::PropertyBuffer::New();
+
+  propertyBuffer->SetFormat( bufferFormat );
+  propertyBuffer->SetSize( size );
+
+  return PropertyBuffer( propertyBuffer.Get() );
+}
+
+PropertyBuffer::PropertyBuffer()
+{
+}
+
+PropertyBuffer::~PropertyBuffer()
+{
+}
+
+PropertyBuffer::PropertyBuffer( const PropertyBuffer& handle )
+: Handle( handle )
+{
+}
+
+PropertyBuffer PropertyBuffer::DownCast( BaseHandle handle )
+{
+  return PropertyBuffer( dynamic_cast<Dali::Internal::PropertyBuffer*>(handle.GetObjectPtr()));
+}
+
+PropertyBuffer& PropertyBuffer::operator=( const PropertyBuffer& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+void PropertyBuffer::SetSize( std::size_t size )
+{
+  GetImplementation(*this).SetSize( size );
+}
+
+std::size_t PropertyBuffer::GetSize() const
+{
+  return  GetImplementation(*this).GetSize();
+}
+
+void PropertyBuffer::SetData( void* data )
+{
+  GetImplementation(*this).SetData( data );
+}
+
+PropertyBuffer::PropertyBuffer( Internal::PropertyBuffer* pointer )
+: Handle( pointer )
+{
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/object/property-buffer.h b/dali/devel-api/object/property-buffer.h
new file mode 100644 (file)
index 0000000..a29c4b5
--- /dev/null
@@ -0,0 +1,183 @@
+#ifndef DALI_PROPERTY_BUFFER_H
+#define DALI_PROPERTY_BUFFER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef> // std::size_t
+#include <string> // std::string
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/object/property.h> // Dali::Property::Index
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+#include <dali/public-api/object/property-map.h> // Dali::Property::Map
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class PropertyBuffer;
+}
+
+/**
+ * @brief PropertyBuffer is a handle to an object that contains a buffer of structured properties
+ *
+ * PropertyBuffers can be used to provide data to Geometry objects.
+ *
+ * Example:
+ *
+ *  const float halfQuadSize = .5f;
+ *  struct TexturedQuadVertex { Vector2 position; Vector2 textureCoordinates; };
+ *  TexturedQuadVertex texturedQuadVertexData[4] = {
+ *    { Vector2(-halfQuadSize, -halfQuadSize), Vector2(0.f, 0.f) },
+ *    { Vector2( halfQuadSize, -halfQuadSize), Vector2(1.f, 0.f) },
+ *    { Vector2(-halfQuadSize,  halfQuadSize), Vector2(0.f, 1.f) },
+ *    { Vector2( halfQuadSize,  halfQuadSize), Vector2(1.f, 1.f) } };
+ *
+ *  Property::Map texturedQuadVertexFormat;
+ *  texturedQuadVertexFormat["aPosition"] = Property::VECTOR2;
+ *  texturedQuadVertexFormat["aTexCoord"] = Property::VECTOR2;
+ *  PropertyBuffer texturedQuadVertices = PropertyBuffer::New( texturedQuadVertexFormat, 4 );
+ *  texturedQuadVertices.SetData(texturedQuadVertexData);
+ *
+ *  // Create indices
+ *  unsigned int indexData[6] = { 0, 3, 1, 0, 2, 3 };
+ *  Property::Map indexFormat;
+ *  indexFormat["indices"] = Property::INTEGER;
+ *  PropertyBuffer indices = PropertyBuffer::New( indexFormat, 6 );
+ *  indices.SetData(indexData);
+ *
+ *  // Create the geometry object
+ *  Geometry texturedQuadGeometry = Geometry::New();
+ *  texturedQuadGeometry.AddVertexBuffer( texturedQuadVertices );
+ *  texturedQuadGeometry.SetIndexBuffer( indices );
+ *
+ */
+class DALI_IMPORT_API PropertyBuffer : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the PropertyBuffer class.
+   */
+  struct Property
+  {
+    enum
+    {
+      SIZE = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "size",           type INTEGER
+      BUFFER_FORMAT,                              ///< name "buffer-format",  type MAP
+    };
+  };
+
+  /**
+   * @brief Create a PropertyBuffer
+   *
+   * Static property buffers use less memory.
+   *
+   * @param[in] bufferFormat Map of names and types that describes the components of the buffer
+   * @param[in] size The number of elements in the property buffer
+   * @return Handle to a newly allocated PropertyBuffer
+   */
+  static PropertyBuffer New( Dali::Property::Map& bufferFormat, std::size_t size );
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  PropertyBuffer();
+
+  /**
+   * @brief Destructor
+   */
+  ~PropertyBuffer();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  PropertyBuffer( const PropertyBuffer& handle );
+
+  /**
+   * @brief Downcast to a property buffer handle.
+   *
+   * If not a property buffer the returned property buffer handle is left uninitialized.
+   * @param[in] handle to an object
+   * @return property buffer handle or an uninitialized handle
+   */
+  static PropertyBuffer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  PropertyBuffer& operator=( const PropertyBuffer& handle );
+
+  /**
+   * @brief Set the number of elements in the buffer
+   *
+   * Calling this function is equivalent to setting the property SIZE
+   *
+   * @param[in] size Number of elements to expand or contract the buffer
+   */
+  void SetSize( std::size_t size );
+
+  /**
+   * @brief Get the number of elements in the buffer
+   *
+   * @return Number of elements to expand or contract the buffer
+   */
+  std::size_t GetSize() const;
+
+  /**
+   * @brief Update the whole buffer information
+   *
+   * This function expects a pointer to an array of structures with the same
+   * format that was given in the construction, and the number of elements to
+   * be the same as the size of the buffer.
+   *
+   * If the initial structure was: { { "position", VECTOR3}, { "uv", VECTOR2 } }
+   * and a size of 10 elements, this function should be called with a pointer equivalent to:
+   * <pre>
+   * struct Vertex {
+   *   Dali::Vector3 position;
+   *   Dali::Vector2 uv;
+   * };
+   * Vertex vertices[ 10 ] = { ... };
+   * propertyBuffer.SetData( vertices );
+   * </pre>
+   *
+   * @param[in] data A pointer to the data that will be copied to the buffer.
+   */
+  void SetData( void* data );
+
+public:
+  /**
+   * @brief The constructor
+   *
+   * @param [in] pointer A pointer to a newly allocated PropertyBuffer
+   */
+  explicit DALI_INTERNAL PropertyBuffer( Internal::PropertyBuffer* pointer );
+};
+
+} // namespace Dali
+
+#endif // DALI_PROPERTY_BUFFER_H
diff --git a/dali/devel-api/object/type-registry-helper.h b/dali/devel-api/object/type-registry-helper.h
new file mode 100644 (file)
index 0000000..7d6b90b
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __DALI_TYPE_REGISTRY_HELPER_H__
+#define __DALI_TYPE_REGISTRY_HELPER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/compile-time-assert.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief These macros are used to use the type-registry to register properties and signals.
+ * This forces registration to be done in a standard way across actors and controls and facilitates future compile-time checks to be added.
+ *
+ * Note: Currently a compile time check is done for the order of the properties. The order is not critical to registration, but helps maintain the ordering between the header and implementations to avoid properties being added out of place.
+ *
+ * Note: The signal macro also generates string const chars.
+ */
+#define DALI_TOKEN_PASTE_EXPAND( x, y ) x ## y
+#define DALI_TOKEN_PASTE( x, y ) DALI_TOKEN_PASTE_EXPAND(x, y)
+
+#define DALI_PROPERTY_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, valueType, enumIndex ) \
+  PropertyRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, Property::valueType, &objectType::SetProperty, &objectType::GetProperty ); \
+  DALI_COMPILE_TIME_ASSERT( ( objectNamespace::objectType::Property::enumIndex - objectNamespace::objectType::PROPERTY_START_INDEX ) == count );
+
+#define DALI_ANIMATABLE_PROPERTY_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, valueType, enumIndex) \
+  AnimatablePropertyRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, Property::valueType );
+
+#define DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex) \
+  AnimatablePropertyComponentRegistration DALI_TOKEN_PASTE( property, count ) ( typeRegistrationObject, text, objectNamespace::objectType::Property::enumIndex, objectNamespace::objectType::Property::baseEnumIndex, componentIndex );
+
+#define DALI_SIGNAL_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, textVariable ) \
+  const char* const textVariable = text; \
+  SignalConnectorType DALI_TOKEN_PASTE( signalConnector, count ) ( typeRegistrationObject, text, &objectNamespace::Internal::objectType::DoConnectSignal );
+
+#define DALI_ACTION_REGISTRATION_INTERNAL( count, typeRegistrationObject, objectNamespace, objectType, text, textVariable ) \
+  const char* const textVariable = text; \
+  TypeAction DALI_TOKEN_PASTE( signalConnector, count ) ( typeRegistrationObject, text, &objectNamespace::Internal::objectType::DoAction );
+
+// For use within implementations:
+
+#define DALI_TYPE_REGISTRATION_BEGIN( thisType, baseType, createFunction ) \
+  TypeRegistration typeRegistration( typeid( thisType ), typeid( baseType ), createFunction );
+
+#define DALI_TYPE_REGISTRATION_BEGIN_CREATE( thisType, baseType, createFunction, createAtStartup ) \
+  TypeRegistration typeRegistration( typeid( thisType ), typeid( baseType ), createFunction, createAtStartup );
+
+#define DALI_PROPERTY_REGISTRATION( objectNamespace, objectType, text, valueType, enumIndex ) \
+  DALI_PROPERTY_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, valueType, enumIndex )
+
+#define DALI_ANIMATABLE_PROPERTY_REGISTRATION( objectNamespace, objectType, text, valueType, enumIndex ) \
+  DALI_ANIMATABLE_PROPERTY_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, valueType, enumIndex )
+
+#define DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION( objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex ) \
+  DALI_ANIMATABLE_PROPERTY_COMPONENT_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, enumIndex, baseEnumIndex, componentIndex )
+
+#define DALI_SIGNAL_REGISTRATION( objectNamespace, objectType, text, textVariable ) \
+  DALI_SIGNAL_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, textVariable )
+
+#define DALI_ACTION_REGISTRATION( objectNamespace, objectType, text, textVariable ) \
+  DALI_ACTION_REGISTRATION_INTERNAL( __COUNTER__, typeRegistration, objectNamespace, objectType, text, textVariable )
+
+#define DALI_TYPE_REGISTRATION_END( ) // Empty for now, can be used to perform checks.
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_TYPE_REGISTRY_HELPER_H__
diff --git a/dali/devel-api/object/weak-handle.cpp b/dali/devel-api/object/weak-handle.cpp
new file mode 100644 (file)
index 0000000..94bb88f
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/object/weak-handle.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+struct WeakHandleBase::Impl : public Internal::Object::Observer
+{
+  // Construction
+  Impl()
+  : mObject( NULL )
+  {
+  }
+
+  // Construction
+  Impl( Handle& handle )
+  : mObject( NULL )
+  {
+    if(handle)
+    {
+      mObject = static_cast<Internal::Object*>( handle.GetObjectPtr() );
+      if(mObject)
+      {
+        mObject->AddObserver( *this );
+      }
+    }
+  }
+
+  // Destruction
+  ~Impl()
+  {
+    if( mObject )
+    {
+      mObject->RemoveObserver( *this );
+    }
+  }
+
+  /**
+   * From Object::Observer
+   */
+  virtual void SceneObjectAdded( Internal::Object& object )
+  {
+  }
+
+  /**
+   * From Object::Observer
+   */
+  virtual void SceneObjectRemoved( Internal::Object& object )
+  {
+  }
+
+  /**
+   * From Object::Observer
+   */
+  virtual void ObjectDestroyed( Internal::Object& object )
+  {
+    mObject = NULL;
+  }
+
+  // Data
+  Internal::Object* mObject;
+};
+
+WeakHandleBase::WeakHandleBase()
+: mImpl( new Impl() )
+{
+}
+
+WeakHandleBase::WeakHandleBase( Handle& handle )
+: mImpl( new Impl( handle ) )
+{
+}
+
+WeakHandleBase::~WeakHandleBase()
+{
+  delete mImpl;
+  mImpl = NULL;
+}
+
+WeakHandleBase::WeakHandleBase(const WeakHandleBase& handle)
+: mImpl( NULL )
+{
+  Handle object = handle.GetBaseHandle();
+  mImpl = new Impl(object);
+}
+
+WeakHandleBase& WeakHandleBase::operator=( const WeakHandleBase& rhs )
+{
+  if( this != &rhs )
+  {
+    delete mImpl;
+
+    Handle handle = rhs.GetBaseHandle();
+    mImpl = new Impl(handle);
+  }
+
+  return *this;
+}
+
+bool WeakHandleBase::operator==( const WeakHandleBase& rhs ) const
+{
+  return this->mImpl->mObject == rhs.mImpl->mObject;
+}
+
+bool WeakHandleBase::operator!=( const WeakHandleBase& rhs ) const
+{
+  return !( *this == rhs );
+}
+
+Handle WeakHandleBase::GetBaseHandle() const
+{
+  return Handle( mImpl->mObject );
+}
+
+} // Dali
diff --git a/dali/devel-api/object/weak-handle.h b/dali/devel-api/object/weak-handle.h
new file mode 100644 (file)
index 0000000..2e24758
--- /dev/null
@@ -0,0 +1,220 @@
+#ifndef __DALI_WEAK_HANDLE_H__
+#define __DALI_WEAK_HANDLE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/actors/custom-actor.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Base class to store a weak pointer to an internal Dali object. The handle to the object
+ * can be accessed if the object exists, and such access is not reference counted. When the object
+ * is deleted, the weak pointer will be set to NULL, and any further attmpt to access to a deleted
+ * object will return an empty handle.
+ *
+ */
+class DALI_IMPORT_API WeakHandleBase
+{
+
+public:
+
+  /**
+   * @brief Default constructor which provides an uninitialized Dali::WeakHandleBase.
+   */
+  WeakHandleBase();
+
+  /**
+   * @brief This constructor creates a weak handle of the Dali object.
+   *
+   * @param [in] handle A reference to the handle of the Dali object.
+   */
+  WeakHandleBase( Handle& handle );
+
+  /**
+   * @brief Destructor to free resources.
+   */
+  ~WeakHandleBase();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @param [in] handle A reference to the copied WeakHandleBase
+   */
+  WeakHandleBase(const WeakHandleBase& handle);
+
+  /**
+   * @brief Assignment operator.
+   *
+   * It makes this WeakHandleBase point to the same internal Dali object as the copied WeakHandleBase
+   * @param [in] rhs  A reference to the copied WeakHandleBase
+   * @return A reference to this WeakHandleBase
+   */
+  WeakHandleBase& operator=( const WeakHandleBase& rhs );
+
+  /**
+   * @brief Equality operator overload.
+   *
+   * @param [in] rhs A reference to the compared WeakHandleBase.
+   * @return true if the handle points to the same Dali resource, or if both are uninitialized.
+   */
+  bool operator==(const WeakHandleBase& rhs) const;
+
+  /**
+   * @brief Inequality operator overload.
+   *
+   * @param [in] rhs A reference to the compared WeakHandleBase.
+   * @return true if the handle points to the different Dali resources.
+   */
+  bool operator!=(const WeakHandleBase& rhs) const;
+
+  /**
+   * @brief Gets the handle to the Dali object.
+   *
+   * @return The handle of the Dali object pointed by this WeakHandleBase or an empty handle if the Dali object doesn't exist.
+   */
+  Handle GetBaseHandle() const;
+
+protected:
+
+  struct Impl;
+  Impl* mImpl;
+};
+
+/**
+ * @brief Type CustomActors support
+ */
+template <typename Type>
+struct CustomActors
+{
+  /**
+   * This flag tells Dali if a class is derived from CustomActor.
+   */
+  enum { IS_CUSTOM_ACTOR = __is_base_of(Dali::CustomActor, Type) };
+};
+
+template <typename Type>
+struct TypeCustomActors : public CustomActors< Type >
+{
+};
+
+template < bool CustomActorType >
+class InternalTypeName
+{
+public: // Typedefs
+
+  typedef Dali::Internal::CustomActor InternalObjectType;
+};
+
+template <>
+class InternalTypeName< false >
+{
+public: // Typedefs
+
+  typedef Dali::Internal::Actor InternalObjectType;
+};
+
+/**
+ * @brief Weak handle for the given type of Dali object.
+ */
+template < class T >
+class WeakHandle : public WeakHandleBase
+{
+public: // Typedefs
+
+  typedef typename InternalTypeName< TypeCustomActors<T>::IS_CUSTOM_ACTOR >::InternalObjectType InternalObjectType;
+
+public:
+
+  /**
+   * @copydoc Dali::WeakHandleBase::WeakHandleBase()
+   */
+  WeakHandle()
+  : WeakHandleBase()
+  {
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::WeakHandleBase(Handle&)
+   */
+  WeakHandle( T& handle )
+  : WeakHandleBase( handle )
+  {
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::~WeakHandleBase()
+   */
+  ~WeakHandle() {}
+
+  /**
+   * @copydoc Dali::WeakHandleBase::WeakHandleBase(const WeakHandleBase&)
+   */
+  WeakHandle(const WeakHandle& handle)
+  : WeakHandleBase( handle )
+  {
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::operator=()
+   */
+  WeakHandle& operator=( const WeakHandle& rhs )
+  {
+    WeakHandleBase::operator=(rhs);
+    return *this;
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::operator==()
+   */
+  bool operator==(const WeakHandle& rhs) const
+  {
+    return WeakHandleBase::operator==(rhs);
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::operator!=()
+   */
+  bool operator!=(const WeakHandle& rhs) const
+  {
+    return WeakHandleBase::operator!=(rhs);
+  }
+
+  /**
+   * @copydoc Dali::WeakHandleBase::GetHandle()
+   */
+  T GetHandle()
+  {
+    Handle handle( GetBaseHandle() );
+    if( handle )
+    {
+      return T( reinterpret_cast< InternalObjectType* >( handle.GetObjectPtr() ) );
+    }
+    else
+    {
+      return T();
+    }
+  }
+};
+
+} // namespace Dali
+
+#endif // __DALI_WEAK_HANDLE_H__
diff --git a/dali/devel-api/rendering/cull-face.cpp b/dali/devel-api/rendering/cull-face.cpp
new file mode 100644 (file)
index 0000000..4f1cc99
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include <dali/devel-api/rendering/cull-face.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/image-actor-impl.h>
+
+namespace Dali
+{
+
+void SetCullFace( ImageActor actor, CullFaceMode mode )
+{
+  GetImplementation( actor ).SetCullFace( mode );
+}
+
+CullFaceMode GetCullFace( ImageActor actor )
+{
+  return GetImplementation( actor ).GetCullFace();
+}
+
+} //namespace Dali
diff --git a/dali/devel-api/rendering/cull-face.h b/dali/devel-api/rendering/cull-face.h
new file mode 100644 (file)
index 0000000..84aa9e3
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef DALI_CULL_FACE_H
+#define DALI_CULL_FACE_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+/**
+ * @brief Face culling modes.
+ */
+enum CullFaceMode
+{
+  CullNone,                 ///< Face culling disabled
+  CullFront,                ///< Cull front facing polygons
+  CullBack,                 ///< Cull back facing polygons
+  CullFrontAndBack          ///< Cull front and back facing polygons
+};
+
+class ImageActor;
+
+/**
+ * @brief Set the face-culling mode for an image-actor.
+ *
+ * @param[in] actor The image-actor to set the cull-face on.
+ * @param[in] mode The culling mode.
+ */
+DALI_IMPORT_API void SetCullFace( ImageActor actor, CullFaceMode mode);
+
+/**
+ * @brief Retrieve the face-culling mode for an image-actor.
+ *
+ * @param[in] actor The image-actor whose cull-face is required.
+ * @return mode The culling mode.
+ */
+DALI_IMPORT_API CullFaceMode GetCullFace( ImageActor actor );
+
+} //namespace Dali
+
+#endif // DALI_CULL_FACE_H
diff --git a/dali/devel-api/rendering/geometry.cpp b/dali/devel-api/rendering/geometry.cpp
new file mode 100644 (file)
index 0000000..4b12f05
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use *this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/rendering/geometry.h>  // Dali::Geometry
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/geometry-impl.h> // Dali::Internal::Geometry
+
+namespace Dali
+{
+
+Geometry Geometry::New()
+{
+  Internal::GeometryPtr geometry = Internal::Geometry::New();
+  return Geometry( geometry.Get() );
+}
+
+Geometry::Geometry()
+{
+}
+
+Geometry::~Geometry()
+{
+}
+
+Geometry::Geometry( const Geometry& handle )
+: Handle( handle )
+{
+}
+
+Geometry Geometry::DownCast( BaseHandle handle )
+{
+  return Geometry( dynamic_cast<Dali::Internal::Geometry*>(handle.GetObjectPtr()));
+}
+
+Geometry& Geometry::operator=( const Geometry& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+std::size_t Geometry::AddVertexBuffer( PropertyBuffer& vertexBuffer )
+{
+  DALI_ASSERT_ALWAYS( vertexBuffer && "VertexBuffer is not initialized ");
+  return GetImplementation(*this).AddVertexBuffer( GetImplementation( vertexBuffer ) );
+}
+
+std::size_t Geometry::GetNumberOfVertexBuffers() const
+{
+  return GetImplementation(*this).GetNumberOfVertexBuffers();
+}
+
+void Geometry::RemoveVertexBuffer( std::size_t index )
+{
+  GetImplementation(*this).RemoveVertexBuffer( index );
+}
+
+void Geometry::SetIndexBuffer( PropertyBuffer& indexBuffer )
+{
+  DALI_ASSERT_ALWAYS( indexBuffer && "indexBuffer is not initialized ");
+  GetImplementation(*this).SetIndexBuffer( GetImplementation( indexBuffer ) );
+}
+
+void Geometry::SetGeometryType( GeometryType geometryType )
+{
+  GetImplementation(*this).SetGeometryType( geometryType );
+}
+
+Geometry::GeometryType Geometry::GetGeometryType() const
+{
+  return GetImplementation(*this).GetGeometryType();
+}
+
+void Geometry::SetRequiresDepthTesting( bool requiresDepthTest )
+{
+  GetImplementation(*this).SetRequiresDepthTesting( requiresDepthTest );
+}
+
+bool Geometry::GetRequiresDepthTesting() const
+{
+  return GetImplementation(*this).GetRequiresDepthTesting();
+}
+
+Geometry::Geometry( Internal::Geometry* pointer )
+: Handle( pointer )
+{
+}
+
+} //namespace Dali
diff --git a/dali/devel-api/rendering/geometry.h b/dali/devel-api/rendering/geometry.h
new file mode 100644 (file)
index 0000000..cb8986e
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef DALI_GEOMETRY_H
+#define DALI_GEOMETRY_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef> // std::size_t
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+#include <dali/devel-api/object/property-buffer.h> // Dali::PropertyBuffer
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Geometry;
+}
+
+/**
+ * @brief Geometry is handle to an object that can be used to define a geometric elements.
+ */
+class DALI_IMPORT_API Geometry : public Handle
+{
+public:
+
+  enum GeometryType
+  {
+    POINTS,
+    LINES,
+    LINE_LOOP,
+    LINE_STRIP,
+    TRIANGLES,
+    TRIANGLE_FAN,
+    TRIANGLE_STRIP
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the Geometry class.
+   */
+  struct Property
+  {
+    enum
+    {
+      GEOMETRY_TYPE = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "depth-index",            type STRING
+      GEOMETRY_CENTER,                                      ///< name "geometry-center",        type VECTOR3
+      GEOMETRY_HALF_EXTENTS,                                ///< name "geometry-half-extents",  type VECTOR3
+      REQUIRES_DEPTH_TEST,                                  ///< name "requires-depth-testing", type BOOLEAN
+    };
+  };
+
+  /**
+   * @brief Creates a new Geometry object
+   *
+   * @return An handle to a newly allocated Geometry
+   */
+  static Geometry New();
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  Geometry();
+
+  /**
+   * @brief Destructor
+   */
+  ~Geometry();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  Geometry( const Geometry& handle );
+
+  /**
+   * @brief Downcast to a geometry.
+   *
+   * If not the returned handle is left uninitialized.
+   * @param[in] handle to an object
+   * @return geometry handle or an uninitialized handle
+   */
+  static Geometry DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  Geometry& operator=( const Geometry& handle );
+
+  /**
+   * @brief Add a PropertyBuffer to be used as source of geometry vertices
+   *
+   * @param[in] vertexBuffer PropertyBuffer to be used as source of geometry vertices
+   * @return Index of the newly added buffer, can be used with RemoveVertexBuffer to remove
+   *         this buffer if no longer required
+   */
+  std::size_t AddVertexBuffer( PropertyBuffer& vertexBuffer );
+
+  /**
+   * @brief Retrieve the number of vertex buffers that have been added to this geometry
+   *
+   * @return Number of vertex buffers that have been added to this geometry
+   */
+  std::size_t GetNumberOfVertexBuffers() const;
+
+  /**
+   * @brief Remove a vertex buffer
+   *
+   * The index must be between 0 and GetNumberOfVertexBuffers()
+   *
+   * @param[in] index Index to the vertex buffer to remove
+   */
+  void RemoveVertexBuffer( std::size_t index );
+
+  /**
+   * @brief Set a PropertyBuffer to be used as a source of indices for the geometry
+   *
+   * This buffer is required to have exactly one component and it must be of the type Property::INTEGER
+   *
+   * By setting this buffer the will case the geometry to be rendered using indices.
+   * To unset call SetIndexBuffer with an empty handle.
+   *
+   * @param[in] indexBuffer PropertyBuffer to be used as a source of indices for the geometry
+   */
+  void SetIndexBuffer( PropertyBuffer& indexBuffer );
+
+  /**
+   * @brief Set the type of primitives this geometry contains
+   *
+   * @param[in] geometryType Type of primitives this geometry contains
+   */
+  void SetGeometryType( GeometryType geometryType );
+
+  /**
+   * @brief Get the type of primitives this geometry contains
+   *
+   * Calling this function sets the property GEOMETRY_TYPE
+   *
+   * @return Type of primitives this geometry contains
+   */
+  GeometryType GetGeometryType() const;
+
+  /**
+   * @brief Set if the geometry requires depth testing
+   *
+   * Should be set to true if this geometry has overlapping triangles in arbitrary order
+   *
+   * Calling this function is equivalent to setting the REQUIRES_DEPTH_TESTING property
+   *
+   * @param[in] requiresDepthTest Specifies if the geometry requires depth testing
+   */
+  void SetRequiresDepthTesting( bool requiresDepthTest );
+
+  /**
+   * @brief Return if the geometry requires depth testing
+   *
+   * @return True if the geometry requires depth testing
+   */
+  bool GetRequiresDepthTesting() const;
+
+public:
+  /**
+   * @brief The constructor
+   *
+   * @param [in] pointer A pointer to a newly allocated Geometry
+   */
+  explicit DALI_INTERNAL Geometry( Internal::Geometry* pointer );
+};
+
+} //namespace Dali
+
+#endif // DALI_GEOMETRY_H
diff --git a/dali/devel-api/rendering/material.cpp b/dali/devel-api/rendering/material.cpp
new file mode 100644 (file)
index 0000000..af2fd92
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/rendering/material.h>  // Dali::Material
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/material-impl.h> // Dali::Internal::Material
+#include <dali/internal/event/rendering/sampler-impl.h> // Dali::Internal::Sampler
+#include <dali/internal/event/rendering/shader-impl.h> // Dali::Internal::Shader
+
+namespace Dali
+{
+
+Material Material::New( Shader shader )
+{
+  // TODO: MESH_REWORK
+  Internal::MaterialPtr material = Internal::Material::New();
+  material->SetShader( GetImplementation(shader) );
+
+  return Material( material.Get() );
+}
+
+Material::Material()
+{
+}
+
+Material::~Material()
+{
+}
+
+Material::Material( const Material& handle )
+: Handle( handle )
+{
+}
+
+Material Material::DownCast( BaseHandle handle )
+{
+  return Material( dynamic_cast<Dali::Internal::Material*>(handle.GetObjectPtr()));
+}
+
+Material& Material::operator=( const Material& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+void Material::SetShader( Shader& shader )
+{
+  DALI_ASSERT_ALWAYS( shader && "Shader handle is uninitialized" );
+  GetImplementation(*this).SetShader( GetImplementation( shader ) );
+}
+
+Shader Material::GetShader() const
+{
+  Internal::Shader* shaderPtr( GetImplementation(*this).GetShader() );
+  return Dali::Shader( shaderPtr );
+}
+
+void Material::AddSampler( Sampler& sampler )
+{
+  DALI_ASSERT_ALWAYS( sampler && "Sampler handle is uninitialized" );
+  GetImplementation(*this).AddSampler( GetImplementation( sampler ) );
+}
+
+std::size_t Material::GetNumberOfSamplers() const
+{
+  return GetImplementation(*this).GetNumberOfSamplers();
+}
+
+void Material::RemoveSampler( std::size_t index )
+{
+  GetImplementation(*this).RemoveSampler( index );
+}
+
+Sampler Material::GetSamplerAt( unsigned int index ) const
+{
+  Internal::Sampler* samplerPtr( GetImplementation(*this).GetSamplerAt(index) );
+  return Dali::Sampler( samplerPtr );
+}
+
+void Material::SetFaceCullingMode( FaceCullingMode cullingMode )
+{
+  GetImplementation(*this).SetFaceCullingMode( cullingMode );
+}
+
+void Material::SetBlendMode( BlendingMode::Type mode )
+{
+  GetImplementation(*this).SetBlendMode( mode );
+}
+
+BlendingMode::Type Material::GetBlendMode() const
+{
+  return GetImplementation(*this).GetBlendMode();
+}
+
+void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgba,
+                             BlendingFactor::Type destFactorRgba )
+{
+  GetImplementation(*this).SetBlendFunc( srcFactorRgba, destFactorRgba );
+}
+
+void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgb,
+                             BlendingFactor::Type destFactorRgb,
+                             BlendingFactor::Type srcFactorAlpha,
+                             BlendingFactor::Type destFactorAlpha )
+{
+  GetImplementation(*this).SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void Material::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,
+                             BlendingFactor::Type& destFactorRgb,
+                             BlendingFactor::Type& srcFactorAlpha,
+                             BlendingFactor::Type& destFactorAlpha ) const
+{
+  GetImplementation(*this).GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void Material::SetBlendEquation( BlendingEquation::Type equationRgba )
+{
+  GetImplementation(*this).SetBlendEquation( equationRgba );
+}
+
+void Material::SetBlendEquation( BlendingEquation::Type equationRgb,
+                                 BlendingEquation::Type equationAlpha )
+{
+  GetImplementation(*this).SetBlendEquation( equationRgb, equationAlpha );
+}
+
+void Material::GetBlendEquation( BlendingEquation::Type& equationRgb,
+                                 BlendingEquation::Type& equationAlpha ) const
+{
+  GetImplementation(*this).GetBlendEquation( equationRgb, equationAlpha );
+}
+
+void Material::SetBlendColor( const Vector4& color )
+{
+  GetImplementation(*this).SetBlendColor( color );
+}
+
+const Vector4& Material::GetBlendColor() const
+{
+  return GetImplementation(*this).GetBlendColor();
+}
+
+Material::Material( Internal::Material* pointer )
+: Handle( pointer )
+{
+}
+
+} //namespace Dali
diff --git a/dali/devel-api/rendering/material.h b/dali/devel-api/rendering/material.h
new file mode 100644 (file)
index 0000000..5751fff
--- /dev/null
@@ -0,0 +1,307 @@
+#ifndef DALI_MATERIAL_H
+#define DALI_MATERIAL_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef> // std::size_t
+#include <string> // std::string
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/blending.h> // Dali::BlendingMode, Dali::BlendingEquation, Dali::BlendingFactor
+#include <dali/public-api/images/image.h> // Dali::Image
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+#include <dali/devel-api/rendering/sampler.h> // Dali::Sampler
+#include <dali/devel-api/rendering/shader.h> // Dali::Shader
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Material;
+}
+
+/**
+ * @brief Material is a handle to an object that specifies the visual properties of the renderer.
+ */
+class DALI_IMPORT_API Material : public Handle
+{
+public:
+
+  /**
+   * @brief Set face culling mode.
+   */
+  enum FaceCullingMode
+  {
+    NONE,                     ///< None of the faces should be culled
+    CULL_BACK,                ///< Cull back face, back face should never be shown
+    CULL_BACK_HINT,           ///< Cull back face hinting, will still display correctly if no culling is done
+    CULL_FRONT,               ///< Cull front face, back face should never be shown
+    CULL_FRONT_HINT,          ///< Cull front face hinting, will still display correctly if no culling is done
+    CULL_BACK_AND_FRONT,      ///< Cull back and front faces, if the geometry is composed of triangles none of the faces will be shown
+    CULL_BACK_AND_FRONT_HINT, ///< Cull back and front hint, will still display correctly if no culling is done
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the Material class.
+   */
+  struct Property
+  {
+    enum
+    {
+      COLOR = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "color",                          type VECTOR4
+      FACE_CULLING_MODE,                            ///< name "face-culling-mode",              type STRING
+      BLENDING_MODE,                                ///< name "blending-mode",                  type STRING
+      BLEND_EQUATION_RGB,                           ///< name "blend-equation-rgb",             type STRING
+      BLEND_EQUATION_ALPHA,                         ///< name "blend-equation-alpha",           type STRING
+      BLENDING_SRC_FACTOR_RGB,                      ///< name "source-blend-factor-rgb",        type STRING
+      BLENDING_DEST_FACTOR_RGB,                     ///< name "destination-blend-factor-rgb",   type STRING
+      BLENDING_SRC_FACTOR_ALPHA,                    ///< name "source-blend-factor-alpha",      type STRING
+      BLENDING_DEST_FACTOR_ALPHA,                   ///< name "destination-blend-factor-alpha", type STRING
+      BLEND_COLOR,                                  ///< name "blend-color",                    type VECTOR4
+    };
+  };
+
+  /// @name Uniform Mapping
+  /** @{ */
+       ///< property "COLOR", uniform "uMaterialColor"
+  /** @} */
+
+  /**
+   * @brief Creates a new Material object
+   *
+   * @return A handle to a newly allocated Material
+   */
+  static Material New( Shader shader );
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  Material();
+
+  /**
+   * @brief Destructor
+   */
+  ~Material();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  Material( const Material& handle );
+
+  /**
+   * @brief Downcast to a material handle.
+   *
+   * If handle is not a material, the returned handle is left uninitialized.
+   * @param[in] handle to an object
+   * @return material handle or an uninitialized handle
+   */
+  static Material DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  Material& operator=( const Material& handle );
+
+  /**
+   * @brief Sets the Shader used by this material
+   *
+   * @param[in] shader Handle to a shader
+   */
+  void SetShader( Shader& shader );
+
+  /**
+   * @brief Gets the shader used by this material
+   *
+   * @return The shader used by the material
+   */
+  Shader GetShader() const;
+
+  /**
+   * @brief Add a sampler to this material
+   *
+   * param[in] sampler The sampler to add to this material
+   */
+  void AddSampler( Sampler& sampler );
+
+  /**
+   * @brief Get the number of samplers
+   *
+   * @return The number of samplers
+   */
+  std::size_t GetNumberOfSamplers() const;
+
+  /**
+   * @brief Remove a sampler
+   *
+   * The index must be between 0 and GetNumberOfSamplers()-1
+   *
+   * @param[in] index The index of the sampler to remove
+   */
+  void RemoveSampler( std::size_t index );
+
+  /**
+   * @brief Get the sampler at the given index for this material
+   *
+   * The index must be between 0 and GetNumberOfSamplers()-1
+   *
+   * @param[in] index The index of the sampler
+   * @return The sampler at that index
+   */
+  Sampler GetSamplerAt( unsigned int index ) const;
+
+  /**
+   * @brief Set the culling mode for this material
+   *
+   * Calling this function sets the properties CULLING_MODE
+   *
+   * @param[in] cullingMode The culling mode for this material
+   */
+  void SetFaceCullingMode( FaceCullingMode cullingMode );
+
+  /**
+   * @brief Sets the blending mode.
+   *
+   * Possible values are: BlendingMode::OFF, BlendingMode::AUTO and BlendingMode::ON. Default is BlendingMode::AUTO.
+   *
+   * If blending is disabled (BlendingMode::OFF) fade in and fade out animations do not work.
+   *
+   * <ul>
+   *   <li> \e OFF Blending is disabled.
+   *   <li> \e AUTO Blending is enabled only if the renderable actor has alpha channel.
+   *   <li> \e ON Blending is enabled.
+   * </ul>
+   *
+   * @param[in] mode The blending mode.
+   */
+  void SetBlendMode( BlendingMode::Type mode );
+
+  /**
+   * @brief Retrieves the blending mode.
+   *
+   * @return The blending mode, one of BlendingMode::OFF, BlendingMode::AUTO or BlendingMode::ON.
+   */
+  BlendingMode::Type GetBlendMode() const;
+
+  /**
+   * @brief Specify the pixel arithmetic used when the actor is blended.
+   *
+   * @param[in] srcFactorRgba Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE.
+   *
+   * @param[in] destFactorRgba Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA.
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba );
+
+  /**
+   * @brief Specify the pixel arithmetic used when the actor is blended.
+   *
+   * @param[in] srcFactorRgb Specifies how the red, green, and blue source blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE.
+   *
+   * @param[in] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA.
+   *
+   * @param[in] srcFactorAlpha Specifies how the alpha source blending factor is computed.
+   * The options are the same as for srcFactorRgb.
+   *
+   * @param[in] destFactorAlpha Specifies how the alpha source blending factor is computed.
+   * The options are the same as for destFactorRgb.
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @brief Query the pixel arithmetic used when the actor is blended.
+   *
+   * @param[out] srcFactorRgb Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * @param[out] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * @param[out] srcFactorAlpha Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * @param[out] destFactorAlpha Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   */
+  void GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
+
+  /**
+   * @brief Specify the equation used when the actor is blended.
+   *
+   * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT.
+   * @param[in] equationRgba The equation used for combining red, green, blue, and alpha components.
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgba );
+
+  /**
+   * @brief Specify the equation used when the actor is blended.
+   *
+   * @param[in] equationRgb The equation used for combining red, green, and blue components.
+   * @param[in] equationAlpha The equation used for combining the alpha component.
+   * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT.
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @brief Query the equation used when the actor is blended.
+   *
+   * @param[out] equationRgb The equation used for combining red, green, and blue components.
+   * @param[out] equationAlpha The equation used for combining the alpha component.
+   */
+  void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
+
+  /**
+   * @brief Specify the color used when the actor is blended; the default is Vector4::ZERO.
+   *
+   * @param[in] color The blend color.
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * @brief Query the color used when the actor is blended.
+   *
+   * @return The blend color.
+   */
+  const Vector4& GetBlendColor() const;
+
+public:
+  /**
+   * @brief The constructor
+   *
+   * @param [in] pointer A pointer to a newly allocated Material
+   */
+  explicit DALI_INTERNAL Material( Internal::Material* pointer );
+};
+
+} //namespace Dali
+
+
+
+#endif // DALI_MATERIAL_H
diff --git a/dali/devel-api/rendering/renderer.cpp b/dali/devel-api/rendering/renderer.cpp
new file mode 100644 (file)
index 0000000..a3080e9
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/rendering/renderer.h>  // Dali::Renderer
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/renderer-impl.h> // Dali::Internal::Renderer
+
+namespace Dali
+{
+
+Renderer Renderer::New( Geometry& geometry, Material& material )
+{
+  Internal::RendererPtr renderer = Internal::Renderer::New(  );
+  renderer->SetGeometry( GetImplementation(geometry) );
+  renderer->SetMaterial( GetImplementation(material) );
+  return Renderer( renderer.Get() );
+}
+
+Renderer::Renderer()
+{
+}
+
+Renderer::~Renderer()
+{
+}
+
+Renderer::Renderer( const Renderer& handle )
+: Handle( handle )
+{
+}
+
+Renderer Renderer::DownCast( BaseHandle handle )
+{
+  return Renderer( dynamic_cast<Dali::Internal::Renderer*>(handle.GetObjectPtr()));
+}
+
+Renderer& Renderer::operator=( const Renderer& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+void Renderer::SetGeometry( Geometry& geometry )
+{
+  DALI_ASSERT_ALWAYS( geometry && "Geometry handle not initialized" );
+  GetImplementation(*this).SetGeometry( GetImplementation(geometry) );
+}
+
+Geometry Renderer::GetGeometry() const
+{
+  Internal::Geometry* geometryPtr( GetImplementation(*this).GetGeometry() );
+  return Dali::Geometry( geometryPtr );
+}
+
+void Renderer::SetMaterial( Material& material )
+{
+  DALI_ASSERT_ALWAYS( material && "Material handle not initialized" );
+  GetImplementation(*this).SetMaterial( GetImplementation(material) );
+}
+
+Material Renderer::GetMaterial() const
+{
+  Internal::Material* materialPtr( GetImplementation(*this).GetMaterial() );
+  return Dali::Material( materialPtr );
+}
+
+void Renderer::SetDepthIndex( int depthIndex )
+{
+  GetImplementation(*this).SetDepthIndex( depthIndex );
+}
+
+int Renderer::GetDepthIndex()
+{
+  return GetImplementation(*this).GetDepthIndex();
+}
+
+Renderer::Renderer( Internal::Renderer* pointer )
+: Handle( pointer )
+{
+}
+
+} //namespace Dali
diff --git a/dali/devel-api/rendering/renderer.h b/dali/devel-api/rendering/renderer.h
new file mode 100644 (file)
index 0000000..42d541d
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef DALI_RENDERER_H
+#define DALI_RENDERER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string> // std::string
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+#include <dali/devel-api/rendering/geometry.h> // Dali::Geometry
+#include <dali/devel-api/rendering/material.h> // Dali::Material
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Renderer;
+}
+
+/**
+ * @brief Renderer is a handle to an object that can be used to provide an image to a material.
+ */
+class DALI_IMPORT_API Renderer : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the Renderer class.
+   */
+  struct Property
+  {
+    enum
+    {
+      DEPTH_INDEX = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "depth-index",  type INTEGER
+    };
+  };
+
+  /**
+   * @brief Creates a new Renderer object
+   *
+   * @param[in] geometry Geometry to be used by this renderer
+   * @param[in] material Material to be used by this renderer
+   */
+  static Renderer New( Geometry& geometry, Material& material );
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  Renderer();
+
+  /**
+   * @brief Destructor
+   */
+  ~Renderer();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  Renderer( const Renderer& handle );
+
+  /**
+   * @brief Downcast to a renderer handle.
+   *
+   * If not a renderer the returned renderer handle is left uninitialized.
+   * @param[in] handle to an object
+   * @return renderer handle or an uninitialized handle
+   */
+  static Renderer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  Renderer& operator=( const Renderer& handle );
+
+  /**
+   * @brief Sets the geometry to be used by this renderer
+   *
+   * @param[in] geometry The geometry to be used by this renderer
+   */
+  void SetGeometry( Geometry& geometry );
+
+  /**
+   * @brief Gets the geometry used by this renderer
+   *
+   * @return The geometry used by the renderer
+   */
+  Geometry GetGeometry() const;
+
+  /**
+   * @brief Sets the material to be used by this renderer
+   *
+   * @param[in] material The material to be used by this renderer
+   */
+  void SetMaterial( Material& material );
+
+  /**
+   * @brief Gets the material used by this renderer
+   *
+   * @return The material used by the renderer
+   */
+  Material GetMaterial() const;
+
+  /**
+   * @brief Set the depth index of this renderer
+   *
+   * Renderer with higher depth indices are rendered in front of other renderers with smaller values
+   *
+   * @param[in] depthIndex The depth index of this renderer
+   */
+  void SetDepthIndex( int depthIndex );
+
+  //@todo No interface to remove geometry / material? I guess you have to throw away
+  // this renderer if you don't want it to work any more...
+
+  /**
+   * @brief Get the depth index of this renderer
+   *
+   * @sa SetDepthIndex()
+   * @return the depth index
+   */
+  int GetDepthIndex();
+
+public:
+  /**
+   * @brief The constructor
+   *
+   * @param [in] pointer A pointer to a newly allocated Renderer
+   */
+  explicit DALI_INTERNAL Renderer( Internal::Renderer* pointer );
+};
+
+} //namespace Dali
+
+#endif // DALI_RENDERER_H
diff --git a/dali/devel-api/rendering/sampler.cpp b/dali/devel-api/rendering/sampler.cpp
new file mode 100644 (file)
index 0000000..d56ed24
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/rendering/sampler.h>  // Dali::Sampler
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/sampler-impl.h> // Dali::Internal::Sampler
+
+namespace Dali
+{
+
+Sampler Sampler::New( Image& image, const std::string& textureUnitUniformName )
+{
+  Internal::SamplerPtr sampler = Internal::Sampler::New(textureUnitUniformName);
+  Internal::ImagePtr imagePtr = &GetImplementation( image );
+  sampler->SetImage( imagePtr );
+  return Sampler( sampler.Get() );
+}
+
+Sampler::Sampler()
+{
+}
+
+Sampler::~Sampler()
+{
+}
+
+Sampler::Sampler( const Sampler& handle )
+: Handle( handle )
+{
+}
+
+Sampler Sampler::DownCast( BaseHandle handle )
+{
+  return Sampler( dynamic_cast<Dali::Internal::Sampler*>(handle.GetObjectPtr()));
+}
+
+Sampler& Sampler::operator=( const Sampler& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+void Sampler::SetUniformName( const std::string& name )
+{
+  GetImplementation(*this).SetTextureUnitUniformName( name );
+}
+
+void Sampler::SetImage( Image& image )
+{
+  Internal::ImagePtr imagePtr = &GetImplementation( image );
+  GetImplementation(*this).SetImage( imagePtr );
+}
+
+Image Sampler::GetImage() const
+{
+  Internal::ImagePtr imagePtr( GetImplementation(*this).GetImage() );
+  return Dali::Image( imagePtr.Get() );
+}
+
+void Sampler::SetFilterMode( FilterMode minFilter, FilterMode magFilter )
+{
+  GetImplementation(*this).SetFilterMode( minFilter, magFilter );
+}
+
+void Sampler::SetWrapMode( WrapMode uWrap, WrapMode vWrap )
+{
+  GetImplementation(*this).SetWrapMode( uWrap, vWrap );
+}
+
+void Sampler::SetAffectsTransparency( bool affectsTransparency )
+{
+  GetImplementation(*this).SetAffectsTransparency( affectsTransparency );
+}
+
+Sampler::Sampler(Internal::Sampler* pointer)
+: Handle( pointer )
+{
+}
+
+} //namespace Dali
diff --git a/dali/devel-api/rendering/sampler.h b/dali/devel-api/rendering/sampler.h
new file mode 100644 (file)
index 0000000..b5d53d7
--- /dev/null
@@ -0,0 +1,187 @@
+#ifndef DALI_SAMPLER_H
+#define DALI_SAMPLER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef> // std::size_t
+#include <string> // std::string
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/images/image.h> // Dali::Image
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Sampler;
+}
+
+/**
+ * @brief Sampler is a handle to an object that can be used to provide an image to a material.
+ */
+class DALI_IMPORT_API Sampler : public Handle
+{
+public:
+
+  /**
+   * @brief Texture filter mode.
+   */
+  enum FilterMode
+  {
+    NONE,     ///< Use GL system defaults (minification NEAREST_MIPMAP_LINEAR, magnification LINEAR)
+    DEFAULT,  ///< Use dali defaults (minification LINEAR, magnification LINEAR)
+    NEAREST,  ///< Filter nearest
+    LINEAR    ///< Filter linear
+  };
+
+  /**
+   * @brief Texture wrap mode.
+   */
+  enum WrapMode
+  {
+    CLAMP_TO_EDGE,    ///< The texture coordinates get clamped to the range [0, 1]
+    REPEAT,           ///< Only the fractional part of the texture coordinates is used
+    MIRRORED_REPEAT,  ///< If the integer part of the texture coordinate is odd then it uses
+                      ///< the fractional part, if it's even it uses 1 - the fractional part
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the Sampler class.
+   */
+  struct Property
+  {
+    enum
+    {
+      MINIFICATION_FILTER = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "minification-filter",  type STRING
+      MAGNIGICATION_FILTER,                                       ///< name "magnification-filter", type STRING
+      U_WRAP,                                                     ///< name "u-wrap",               type STRING
+      V_WRAP,                                                     ///< name "v-wrap",               type STRING
+      AFFECTS_TRANSPARENCY,                                       ///< name "affects-transparency", type BOOLEAN
+    };
+  };
+
+  /**
+   * @brief Creates a new Sampler object
+   *
+   * @param[in] image Image used by this sampler
+   * @param[in] uniformName String with the name of the uniform
+   */
+  static Sampler New( Image& image, const std::string& uniformName );
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  Sampler();
+
+  /**
+   * @brief Destructor
+   */
+  ~Sampler();
+
+  /**
+   * @brief Copy constructor, creates a new handle to the same object
+   *
+   * @param[in] handle Handle to an object
+   */
+  Sampler( const Sampler& handle );
+
+  /**
+   * @brief Downcast to a sampler handle.
+   *
+   * If not the returned handle is left uninitialized.
+   * @param[in] handle to An object
+   * @return handle or an uninitialized handle
+   */
+  static Sampler DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  Sampler& operator=( const Sampler& handle );
+
+  /**
+   * @brief Sets the name of the shader uniform that will use this sampler
+   *
+   * @param[in] name String with the name of the uniform
+   */
+  void SetUniformName( const std::string& name );
+
+  /**
+   * @brief Set the image used by this sampler
+   *
+   * @param[in] image Image used by this sampler
+   */
+  void SetImage( Image& image );
+
+  /**
+   * @brief Retrieve the image used by this sampler
+   *
+   * If no image is assigned, an empty handle is returned
+   * @return The image.
+   */
+  Image GetImage() const;
+
+  /**
+   * @brief Set the filter modes for this sampler
+   *
+   * Calling this function sets the properties MINIFICATION_FILTER
+   * and MAGNIFICATION_FILTER
+   *
+   * @param[in] minFilter The minification filter that will be used
+   * @param[in] magFilter The magnification filter that will be used
+   */
+  void SetFilterMode( FilterMode minFilter, FilterMode magFilter );
+
+  /**
+   * @brief Set the wrap modes for this sampler
+   *
+   * Calling this function sets the properties U_WRAP and V_WRAP
+   *
+   * param[in] uWrap Wrap mode for u coordinates
+   * param[in] vWrap Wrap mode for v coordinates
+   */
+  void SetWrapMode( WrapMode uWrap, WrapMode vWrap );
+
+  /**
+   * @brief Set if this sampler should be considered for opacity hinting
+   *
+   * Calling this function sets the property AFFECTS_TRANSPARENCY
+   *
+   * param[in] affectsTransparency Specifies if this sampler should be considered for opacity hinting
+   */
+  void SetAffectsTransparency( bool affectsTransparency );
+
+public:
+  /**
+   * @brief The constructor
+   *
+   * @param [in] pointer A pointer to a newly allocated Sampler
+   */
+  explicit DALI_INTERNAL Sampler( Internal::Sampler* pointer );
+};
+
+} //namespace Dali
+
+#endif // DALI_SAMPLER_H
diff --git a/dali/devel-api/rendering/shader.cpp b/dali/devel-api/rendering/shader.cpp
new file mode 100644 (file)
index 0000000..6be2e63
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/rendering/shader.h>  // Dali::Shader
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/rendering/shader-impl.h>  // Dali::Internal::Shader
+
+namespace Dali
+{
+
+Shader Shader::New( const std::string& vertexShader,
+                    const std::string& fragmentShader,
+                    ShaderHints hints )
+{
+  Internal::ShaderPtr renderer = Internal::Shader::New( vertexShader, fragmentShader, hints );
+  return Shader( renderer.Get() );
+}
+
+Shader::Shader()
+{
+}
+
+Shader::~Shader()
+{
+}
+
+Shader::Shader( const Shader& handle )
+: Handle( handle )
+{
+}
+
+Shader Shader::DownCast( BaseHandle handle )
+{
+  return Shader( dynamic_cast<Dali::Internal::Shader*>(handle.GetObjectPtr()));
+}
+
+Shader& Shader::operator=( const Shader& handle )
+{
+  BaseHandle::operator=( handle );
+  return *this;
+}
+
+Shader::Shader( Internal::Shader* pointer )
+: Handle( pointer )
+{
+}
+
+} // namespace Dali
diff --git a/dali/devel-api/rendering/shader.h b/dali/devel-api/rendering/shader.h
new file mode 100644 (file)
index 0000000..05d01f3
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef DALI_SHADER_H
+#define DALI_SHADER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string> // std::string
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h> // Dali::Handle
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+
+/**
+ * @brief DALI_COMPOSE_SHADER macro provides a convenient way to write shader source code.
+ *
+ * We normally use double quotation marks to write a string such as "Hello World".
+ * However many symbols are needed to add multiple lines of string.
+ * We don't need to write quotation marks using this macro at every line.
+ *
+ * [An example of double quotation marks usage]
+ * <pre>
+ * const string FRAGMENT_SHADER_SOURCE = \
+ * "  void main()\n"
+ * "  {\n"
+ * "    gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n"
+ * "  }\n";
+ * </pre><br/>
+ * [An example of DALI_COMPOSE_SHADER usage]
+ * <pre>
+ * const string VERTEX_SHADER_SOURCE = DALI_COMPOSE_SHADER (
+ *   void main()
+ *   {
+ *     gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
+ *     vTexCoord = aTexCoord;
+ *   }
+ * );
+ * </pre>
+ */
+#define DALI_COMPOSE_SHADER(STR) #STR
+
+namespace Dali
+{
+
+namespace Internal DALI_INTERNAL
+{
+class Shader;
+}
+
+/**
+ * @brief Shaders allows custom vertex and color transformations in the GPU
+ */
+class DALI_IMPORT_API Shader : public Handle
+{
+public:
+  /**
+   * @brief Hints for rendering/subdividing geometry.
+   */
+  enum ShaderHints
+  {
+    HINT_NONE                     = 0x00, ///< no hints
+    HINT_REQUIRES_SELF_DEPTH_TEST = 0x01, ///< Expects depth testing enabled
+    HINT_OUTPUT_IS_TRANSPARENT    = 0x02, ///< Might generate transparent alpha from opaque inputs
+    HINT_OUTPUT_IS_OPAQUE         = 0x04, ///< Outputs opaque colors even if the inputs are transparent
+    HINT_MODIFIES_GEOMETRY        = 0x08, ///< Might change position of vertices,
+                                          ///< this option disables any culling optimizations
+  };
+
+  /**
+   * @brief An enumeration of properties belonging to the Shader class.
+   */
+  struct Property
+  {
+    enum
+    {
+      PROGRAM = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "program",      type MAP; {"vertex-prefix":"","fragment-prefix":"","vertex":"","fragment":""}
+      SHADER_HINTS,                                   ///< name "shader-hints", type INTEGER; (bitfield) values from enum Shader::Hints
+    };
+  };
+
+  /**
+   * @brief Create Shader.
+   *
+   * @param vertexShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param fragmentShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param hints GeometryHints to define the geometry of the rendered object
+   * @return A handle to a shader effect
+   */
+  static Shader New( const std::string& vertexShader,
+                     const std::string& fragmentShader,
+                     ShaderHints hints = ShaderHints(HINT_NONE) );
+
+  /**
+   * @brief Default constructor, creates an empty handle
+   */
+  Shader();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   */
+  ~Shader();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @param handle A handle to a Shader object
+   */
+  Shader( const Shader& handle );
+
+  /**
+   * @brief Downcast to a shader handle.
+   *
+   * If not a shader the returned shader handle is left uninitialized.
+   * @param[in] handle to an object
+   * @return shader handle or an uninitialized handle
+   */
+  static Shader DownCast( BaseHandle handle );
+
+  /**
+   * @brief Assignment operator, changes this handle to point at the same object
+   *
+   * @param[in] handle Handle to an object
+   * @return Reference to the assigned object
+   */
+  Shader& operator=( const Shader& handle );
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   * @param [in] effect A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL Shader( Internal::Shader* effect );
+};
+
+} // namespace Dali
+
+#endif // DALI_SHADER_H
diff --git a/dali/devel-api/scripting/scripting.cpp b/dali/devel-api/scripting/scripting.cpp
new file mode 100644 (file)
index 0000000..98483c5
--- /dev/null
@@ -0,0 +1,681 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/devel-api/scripting/scripting.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/internal/common/image-attributes.h>
+#include <dali/internal/event/images/resource-image-impl.h>
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+
+namespace Dali
+{
+
+namespace Scripting
+{
+
+namespace
+{
+
+// Tables used here for converting strings to the enumerations and vice versa
+struct AnchorValue
+{
+  const char* name;
+  const Vector3 value;
+};
+const AnchorValue ANCHOR_CONSTANT_TABLE[] =
+{
+  { "TOP_LEFT",               ParentOrigin::TOP_LEFT               },
+  { "TOP_CENTER",             ParentOrigin::TOP_CENTER             },
+  { "TOP_RIGHT",              ParentOrigin::TOP_RIGHT              },
+  { "CENTER_LEFT",            ParentOrigin::CENTER_LEFT            },
+  { "CENTER",                 ParentOrigin::CENTER                 },
+  { "CENTER_RIGHT",           ParentOrigin::CENTER_RIGHT           },
+  { "BOTTOM_LEFT",            ParentOrigin::BOTTOM_LEFT            },
+  { "BOTTOM_CENTER",          ParentOrigin::BOTTOM_CENTER          },
+  { "BOTTOM_RIGHT",           ParentOrigin::BOTTOM_RIGHT           },
+};
+const unsigned int ANCHOR_CONSTANT_TABLE_COUNT = sizeof( ANCHOR_CONSTANT_TABLE ) / sizeof( ANCHOR_CONSTANT_TABLE[0] );
+
+const StringEnum COLOR_MODE_TABLE[] =
+{
+  { "USE_OWN_COLOR",                    USE_OWN_COLOR                    },
+  { "USE_PARENT_COLOR",                 USE_PARENT_COLOR                 },
+  { "USE_OWN_MULTIPLY_PARENT_COLOR",    USE_OWN_MULTIPLY_PARENT_COLOR    },
+  { "USE_OWN_MULTIPLY_PARENT_ALPHA",    USE_OWN_MULTIPLY_PARENT_ALPHA    },
+};
+const unsigned int COLOR_MODE_TABLE_COUNT = sizeof( COLOR_MODE_TABLE ) / sizeof( COLOR_MODE_TABLE[0] );
+
+const StringEnum POSITION_INHERITANCE_MODE_TABLE[] =
+{
+  { "INHERIT_PARENT_POSITION",                    INHERIT_PARENT_POSITION                    },
+  { "USE_PARENT_POSITION",                        USE_PARENT_POSITION                        },
+  { "USE_PARENT_POSITION_PLUS_LOCAL_POSITION",    USE_PARENT_POSITION_PLUS_LOCAL_POSITION    },
+  { "DONT_INHERIT_POSITION",                      DONT_INHERIT_POSITION                      },
+};
+const unsigned int POSITION_INHERITANCE_MODE_TABLE_COUNT = sizeof( POSITION_INHERITANCE_MODE_TABLE ) / sizeof( POSITION_INHERITANCE_MODE_TABLE[0] );
+
+const StringEnum DRAW_MODE_TABLE[] =
+{
+  { "NORMAL",     DrawMode::NORMAL     },
+  { "OVERLAY_2D", DrawMode::OVERLAY_2D },
+  { "STENCIL",    DrawMode::STENCIL    },
+};
+const unsigned int DRAW_MODE_TABLE_COUNT = sizeof( DRAW_MODE_TABLE ) / sizeof( DRAW_MODE_TABLE[0] );
+
+const StringEnum IMAGE_LOAD_POLICY_TABLE[] =
+{
+  { "IMMEDIATE", ResourceImage::IMMEDIATE },
+  { "ON_DEMAND", ResourceImage::ON_DEMAND },
+};
+const unsigned int IMAGE_LOAD_POLICY_TABLE_COUNT = sizeof( IMAGE_LOAD_POLICY_TABLE ) / sizeof( IMAGE_LOAD_POLICY_TABLE[0] );
+
+const StringEnum IMAGE_RELEASE_POLICY_TABLE[] =
+{
+  { "UNUSED", Image::UNUSED },
+  { "NEVER",  Image::NEVER  },
+};
+const unsigned int IMAGE_RELEASE_POLICY_TABLE_COUNT = sizeof( IMAGE_RELEASE_POLICY_TABLE ) / sizeof( IMAGE_RELEASE_POLICY_TABLE[0] );
+
+const StringEnum PIXEL_FORMAT_TABLE[] =
+{
+  { "A8",                                           Pixel::A8                                           },
+  { "L8",                                           Pixel::L8                                           },
+  { "LA88",                                         Pixel::LA88                                         },
+  { "RGB565",                                       Pixel::RGB565                                       },
+  { "BGR565",                                       Pixel::BGR565                                       },
+  { "RGBA4444",                                     Pixel::RGBA4444                                     },
+  { "BGRA4444",                                     Pixel::BGRA4444                                     },
+  { "RGBA5551",                                     Pixel::RGBA5551                                     },
+  { "BGRA5551",                                     Pixel::BGRA5551                                     },
+  { "RGB888",                                       Pixel::RGB888                                       },
+  { "RGB8888",                                      Pixel::RGB8888                                      },
+  { "BGR8888",                                      Pixel::BGR8888                                      },
+  { "RGBA8888",                                     Pixel::RGBA8888                                     },
+  { "BGRA8888",                                     Pixel::BGRA8888                                     },
+  { "COMPRESSED_R11_EAC",                           Pixel::COMPRESSED_R11_EAC                           },
+  { "COMPRESSED_SIGNED_R11_EAC",                    Pixel::COMPRESSED_SIGNED_R11_EAC                    },
+  { "COMPRESSED_SIGNED_RG11_EAC",                   Pixel::COMPRESSED_SIGNED_RG11_EAC                   },
+  { "COMPRESSED_RG11_EAC",                          Pixel::COMPRESSED_RG11_EAC                          },
+  { "COMPRESSED_RGB8_ETC2",                         Pixel::COMPRESSED_RGB8_ETC2                         },
+  { "COMPRESSED_SRGB8_ETC2",                        Pixel::COMPRESSED_SRGB8_ETC2                        },
+  { "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2",     Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2     },
+  { "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2",    Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2    },
+  { "COMPRESSED_RGBA8_ETC2_EAC",                    Pixel::COMPRESSED_RGBA8_ETC2_EAC                    },
+  { "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC",             Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC             },
+  { "COMPRESSED_RGB8_ETC1",                         Pixel::COMPRESSED_RGB8_ETC1                         },
+  { "COMPRESSED_RGB_PVRTC_4BPPV1",                  Pixel::COMPRESSED_RGB_PVRTC_4BPPV1                  },
+};
+const unsigned int PIXEL_FORMAT_TABLE_COUNT = sizeof( PIXEL_FORMAT_TABLE ) / sizeof( PIXEL_FORMAT_TABLE[0] );
+
+const StringEnum IMAGE_FITTING_MODE_TABLE[] =
+{
+  { "SHRINK_TO_FIT", FittingMode::SHRINK_TO_FIT },
+  { "SCALE_TO_FILL", FittingMode::SCALE_TO_FILL },
+  { "FIT_WIDTH",     FittingMode::FIT_WIDTH    },
+  { "FIT_HEIGHT",    FittingMode::FIT_HEIGHT   },
+};
+const unsigned int IMAGE_FITTING_MODE_TABLE_COUNT = sizeof( IMAGE_FITTING_MODE_TABLE ) / sizeof( IMAGE_FITTING_MODE_TABLE[0] );
+
+const StringEnum IMAGE_SAMPLING_MODE_TABLE[] =
+{
+  { "BOX",              SamplingMode::BOX            },
+  { "NEAREST",          SamplingMode::NEAREST        },
+  { "LINEAR",           SamplingMode::LINEAR         },
+  { "BOX_THEN_NEAREST", SamplingMode::BOX_THEN_NEAREST },
+  { "BOX_THEN_LINEAR",  SamplingMode::BOX_THEN_LINEAR  },
+  { "NO_FILTER",        SamplingMode::NO_FILTER       },
+  { "DONT_CARE",        SamplingMode::DONT_CARE       },
+};
+const unsigned int IMAGE_SAMPLING_MODE_TABLE_COUNT = sizeof( IMAGE_SAMPLING_MODE_TABLE ) / sizeof( IMAGE_SAMPLING_MODE_TABLE[0] );
+
+const char* ImageTypeName[] = { "ResourceImage", "FrameBufferImage", "BufferImage" };
+enum ImageType                { RESOURCE_IMAGE,  FRAME_BUFFER_IMAGE, BUFFER_IMAGE };
+const unsigned int imageTypeCount = sizeof( ImageTypeName ) / sizeof( const char* );
+
+bool CompareEnums( const char * a, const char * b )
+{
+  while( ( *a != '\0' ) && ( *b != '\0' ) )
+  {
+    char ca = *a;
+    char cb = *b;
+
+    if( ( ( ca == '-' ) || ( ca == '_') ) &&
+        ( ( cb == '-' ) || ( cb == '_') ) )
+    {
+      ++a;
+      ++b;
+      continue;
+    }
+
+    if( ( 'A' <= ca ) && ( ca <= 'Z') )
+    {
+      ca = ca + ( 'a' - 'A' );
+    }
+
+    if( ( 'A' <= cb ) && ( cb <= 'Z') )
+    {
+      cb = cb + ( 'a' - 'A' );
+    }
+
+    if( ca != cb )
+    {
+      return false;
+    }
+
+    ++a;
+    ++b;
+  }
+
+  if( ( *a == '\0' ) && ( *b == '\0' ) )
+  {
+    return true;
+  }
+
+  return false;
+}
+
+} // unnamed namespace
+
+unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount )
+{
+  unsigned int index = 0;
+  bool found = false;
+  for ( unsigned int i = 0; i < tableCount; ++i, ++index )
+  {
+    if( CompareEnums( value, table->string ) )
+    {
+      found = true;
+      break;
+    }
+    ++table;
+  }
+  if ( !found )
+  {
+    DALI_LOG_ERROR( "Unknown enumeration string %s\n", value );
+  }
+  return index;
+}
+
+ColorMode GetColorMode( const std::string& value )
+{
+  // return default on error
+  ColorMode mode( USE_OWN_MULTIPLY_PARENT_ALPHA );
+  GetEnumeration< ColorMode >( value.c_str(), COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT, mode );
+  return mode;
+}
+
+
+std::string GetColorMode( ColorMode value )
+{
+  const char* name = GetEnumerationName< ColorMode >( value, COLOR_MODE_TABLE, COLOR_MODE_TABLE_COUNT );
+  if( name )
+  {
+    return std::string( name );
+  }
+  return std::string();
+}
+
+PositionInheritanceMode GetPositionInheritanceMode( const std::string& value )
+{
+  // return default on error
+  PositionInheritanceMode mode( INHERIT_PARENT_POSITION );
+  GetEnumeration< PositionInheritanceMode >( value.c_str(), POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT, mode );
+  return mode;
+}
+
+
+std::string GetPositionInheritanceMode( PositionInheritanceMode value )
+{
+  const char* name = GetEnumerationName< PositionInheritanceMode >( value, POSITION_INHERITANCE_MODE_TABLE, POSITION_INHERITANCE_MODE_TABLE_COUNT );
+  if( name )
+  {
+    return std::string( name );
+  }
+  return std::string();
+}
+
+
+DrawMode::Type GetDrawMode( const std::string& value )
+{
+  // return default on error
+  DrawMode::Type mode( DrawMode::NORMAL );
+  GetEnumeration< DrawMode::Type >( value.c_str(), DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT, mode );
+  return mode;
+}
+
+
+std::string GetDrawMode( DrawMode::Type value )
+{
+  const char* name = GetEnumerationName< DrawMode::Type >( value, DRAW_MODE_TABLE, DRAW_MODE_TABLE_COUNT );
+  if( name )
+  {
+    return std::string( name );
+  }
+  return std::string();
+}
+
+
+Vector3 GetAnchorConstant( const std::string& value )
+{
+  for( unsigned int i = 0; i < ANCHOR_CONSTANT_TABLE_COUNT; ++i )
+  {
+    if( CompareEnums( value.c_str(), ANCHOR_CONSTANT_TABLE[ i ].name ) )
+    {
+      return ANCHOR_CONSTANT_TABLE[ i ].value;
+    }
+  }
+  return Vector3();
+}
+
+
+Image NewImage( const Property::Value& property )
+{
+  Image ret;
+
+  std::string filename;
+  ResourceImage::LoadPolicy loadPolicy = Dali::Internal::IMAGE_LOAD_POLICY_DEFAULT;
+  Image::ReleasePolicy releasePolicy   = Dali::Internal::IMAGE_RELEASE_POLICY_DEFAULT;
+  Internal::ImageAttributes attributes = Internal::ImageAttributes::New();
+
+  const Property::Map* map = property.GetMap();
+  ImageType imageType = RESOURCE_IMAGE; // default to resource image
+  if( map )
+  {
+    // first check the type as it determines, which other parameters are needed
+    const Property::Value* value = map->Find( "type" );
+    if( value )
+    {
+      std::string type;
+      value->Get( type );
+      for( unsigned int i = 0; i < imageTypeCount; ++i )
+      {
+        if( 0 == type.compare( ImageTypeName[ i ] ) )
+        {
+          imageType = static_cast<ImageType>( i );
+          break;
+        }
+      }
+    }
+
+    // filename is only needed for resource images
+    if( RESOURCE_IMAGE == imageType )
+    {
+      const Property::Value* value = map->Find( "filename" );
+      if( value )
+      {
+        value->Get( filename );
+      }
+      // if empty file, no need to go further
+      if( filename.size() == 0 )
+      {
+        DALI_LOG_ERROR( "No filename\n" );
+        return Image();
+      }
+    }
+
+    value = map->Find( "load-policy" );
+    if( value )
+    {
+      std::string policy;
+      value->Get( policy );
+      // keep default value on error
+      GetEnumeration< ResourceImage::LoadPolicy >( policy.c_str(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT, loadPolicy );
+    }
+
+    value = map->Find( "release-policy" );
+    if( value )
+    {
+      std::string policy;
+      value->Get( policy );
+      // keep default value on error
+      GetEnumeration< Image::ReleasePolicy >( policy.c_str(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT, releasePolicy );
+    }
+
+    // Width and height can be set individually. Dali derives the unspecified
+    // dimension from the aspect ratio of the raw image.
+    int width = 0, height = 0;
+
+    value = map->Find( "width" );
+    if( value )
+    {
+      // handle floats and integer the same for json script
+      if( value->GetType() == Property::FLOAT )
+      {
+        width = static_cast<unsigned int>( value->Get<float>() );
+      }
+      else
+      {
+        value->Get( width );
+      }
+    }
+    value = map->Find( "height" );
+    if( value )
+    {
+      if( value->GetType() == Property::FLOAT )
+      {
+        height = static_cast<int>( value->Get<float>() );
+      }
+      else
+      {
+        value->Get( height );
+      }
+    }
+    attributes.SetSize( width, height );
+
+    Pixel::Format pixelFormat = Pixel::RGBA8888;
+    value = map->Find( "pixel-format" );
+    if( value )
+    {
+      std::string format;
+      value->Get( format );
+      GetEnumeration< Pixel::Format >( format.c_str(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT, pixelFormat );
+    }
+
+    value = map->Find( "fitting-mode" );
+    if( value )
+    {
+      std::string fitting;
+      value->Get( fitting );
+      FittingMode::Type mode;
+      if( GetEnumeration< FittingMode::Type >( fitting.c_str(), IMAGE_FITTING_MODE_TABLE, IMAGE_FITTING_MODE_TABLE_COUNT, mode ) )
+      {
+        attributes.SetScalingMode( mode );
+      }
+    }
+
+    value = map->Find( "sampling-mode" );
+    if( value )
+    {
+      std::string sampling;
+      value->Get( sampling );
+      SamplingMode::Type mode;
+      if( GetEnumeration< SamplingMode::Type >( sampling.c_str(), IMAGE_SAMPLING_MODE_TABLE, IMAGE_SAMPLING_MODE_TABLE_COUNT, mode ) )
+      {
+        attributes.SetFilterMode( mode );
+      }
+    }
+
+    value = map->Find( "orientation" );
+    if( value )
+    {
+      bool b = value->Get<bool>();
+      attributes.SetOrientationCorrection( b );
+    }
+
+    switch( imageType )
+    {
+      case RESOURCE_IMAGE :
+      {
+        ret = ResourceImage::New( filename, loadPolicy, releasePolicy,
+                                  ImageDimensions( attributes.GetSize().x, attributes.GetSize().y ),
+                                  attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
+        break;
+      }
+      case BUFFER_IMAGE :
+      {
+        ret = BufferImage::New( attributes.GetWidth(),
+                                attributes.GetHeight(),
+                                pixelFormat,
+                                releasePolicy );
+        break;
+      }
+      case FRAME_BUFFER_IMAGE :
+      {
+        ret = FrameBufferImage::New( attributes.GetWidth(),
+                                     attributes.GetHeight(),
+                                     pixelFormat,
+                                     releasePolicy );
+        break;
+      }
+    }
+  }
+
+  return ret;
+
+} // Image NewImage( Property::Value map )
+
+
+ShaderEffect NewShaderEffect( const Property::Value& property )
+{
+  Internal::ShaderEffectPtr ret;
+
+  const Property::Map* map = property.GetMap();
+  if( map )
+  {
+    ret = Internal::ShaderEffect::New( Dali::ShaderEffect::HINT_NONE ); // hint can be reset if in map
+
+    const Property::Value* value = map->Find( "program" );
+    if( value )
+    {
+      Property::Index index = ret->GetPropertyIndex( "program" );
+      ret->SetProperty( index, *value );
+    }
+
+    for( unsigned int i = 0; i < map->Count(); ++i )
+    {
+      const std::string& key = map->GetKey( i );
+      if( key != "program" )
+      {
+        Property::Index index = ret->GetPropertyIndex( key );
+
+        const Property::Value& value = map->GetValue( i );
+        if( Property::INVALID_INDEX != index )
+        {
+          ret->SetProperty( index, value );
+        }
+        else
+        {
+          // if its not a property then register it as a uniform (making a custom property)
+          if( value.GetType() == Property::INTEGER )
+          {
+            // valid uniforms are floats, vec3's etc so we recast if the user accidentally
+            // set as integer. Note the map could have come from json script.
+            Property::Value asFloat( static_cast<float>( value.Get<int>() ) );
+            ret->SetUniform( key, asFloat, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
+          }
+          else
+          {
+            ret->SetUniform( key, value, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
+          }
+        }
+      }
+    }
+  }
+
+  return Dali::ShaderEffect(ret.Get());
+}
+
+
+Actor NewActor( const Property::Map& map )
+{
+  BaseHandle handle;
+
+  // First find type and create Actor
+  Property::Value* typeValue = map.Find( "type" );
+  if ( typeValue )
+  {
+    TypeInfo type = TypeRegistry::Get().GetTypeInfo( typeValue->Get< std::string >() );
+    if ( type )
+    {
+      handle = type.CreateInstance();
+    }
+  }
+
+  if ( !handle )
+  {
+    DALI_LOG_ERROR( "Actor type not provided\n" );
+    return Actor();
+  }
+
+  Actor actor( Actor::DownCast( handle ) );
+
+  if ( actor )
+  {
+    // Now set the properties, or create children
+    for ( unsigned int i = 0, mapCount = map.Count(); i < mapCount; ++i )
+    {
+      const StringValuePair& pair( map.GetPair( i ) );
+      const std::string& key( pair.first );
+      if ( key == "type" )
+      {
+        continue;
+      }
+
+      const Property::Value& value( pair.second );
+
+      if ( key == "actors" )
+      {
+        // Create children
+        Property::Array actorArray = value.Get< Property::Array >();
+        for ( Property::Array::SizeType i = 0; i < actorArray.Size(); ++i)
+        {
+          actor.Add( NewActor( actorArray[i].Get< Property::Map >() ) );
+        }
+      }
+      else if( key ==  "parent-origin" )
+      {
+        // Parent Origin can be a string constant as well as a Vector3
+
+        const Property::Type type( value.GetType() );
+        if ( type == Property::VECTOR3 )
+        {
+          actor.SetParentOrigin( value.Get< Vector3 >() );
+        }
+        else if( type == Property::STRING )
+        {
+          actor.SetParentOrigin( GetAnchorConstant( value.Get< std::string >() ) );
+        }
+      }
+      else if( key ==  "anchor-point" )
+      {
+        // Anchor Point can be a string constant as well as a Vector3
+
+        const Property::Type type( value.GetType() );
+        if ( type == Property::VECTOR3 )
+        {
+          actor.SetAnchorPoint( value.Get< Vector3 >() );
+        }
+        else if( type == Property::STRING )
+        {
+          actor.SetAnchorPoint( GetAnchorConstant( value.Get< std::string >() ) );
+        }
+      }
+      else
+      {
+        Property::Index index( actor.GetPropertyIndex( key ) );
+
+        if ( index != Property::INVALID_INDEX )
+        {
+          actor.SetProperty( index, value );
+        }
+      }
+    }
+  }
+
+  return actor;
+}
+
+void CreatePropertyMap( Actor actor, Property::Map& map )
+{
+  map.Clear();
+
+  if ( actor )
+  {
+    map[ "type" ] = actor.GetTypeName();
+
+    // Default properties
+    Property::IndexContainer indices;
+    actor.GetPropertyIndices( indices );
+    const Property::IndexContainer::ConstIterator endIter = indices.End();
+
+    for ( Property::IndexContainer::Iterator iter = indices.Begin(); iter != endIter; ++iter )
+    {
+      map[ actor.GetPropertyName( *iter ) ] = actor.GetProperty( *iter );
+    }
+
+    // Children
+    unsigned int childCount( actor.GetChildCount() );
+    if ( childCount )
+    {
+      Property::Array childArray;
+      for ( unsigned int child = 0; child < childCount; ++child )
+      {
+        Property::Map childMap;
+        CreatePropertyMap( actor.GetChildAt( child ), childMap );
+        childArray.PushBack( childMap );
+      }
+      map[ "actors" ] = childArray;
+    }
+  }
+}
+
+void CreatePropertyMap( Image image, Property::Map& map )
+{
+  map.Clear();
+
+  if ( image )
+  {
+    std::string imageType( "ResourceImage" );
+
+    // Get Type - cannot use TypeRegistry as Image is not an Object and thus, not registered
+    BufferImage bufferImage = BufferImage::DownCast( image );
+    if ( bufferImage )
+    {
+      imageType = "BufferImage";
+      map[ "pixel-format" ] = GetEnumerationName< Pixel::Format >( bufferImage.GetPixelFormat(), PIXEL_FORMAT_TABLE, PIXEL_FORMAT_TABLE_COUNT );
+    }
+    else if ( FrameBufferImage::DownCast( image ) )
+    {
+      imageType = "FrameBufferImage";
+    }
+
+    map[ "type" ] = imageType;
+    map[ "release-policy" ] = GetEnumerationName< Image::ReleasePolicy >( image.GetReleasePolicy(), IMAGE_RELEASE_POLICY_TABLE, IMAGE_RELEASE_POLICY_TABLE_COUNT );
+
+    ResourceImage resourceImage = ResourceImage::DownCast( image );
+    if( resourceImage )
+    {
+      map[ "filename" ] = resourceImage.GetUrl();
+      map[ "load-policy" ] = GetEnumerationName< ResourceImage::LoadPolicy >( resourceImage.GetLoadPolicy(), IMAGE_LOAD_POLICY_TABLE, IMAGE_LOAD_POLICY_TABLE_COUNT );
+    }
+
+    int width( image.GetWidth() );
+    int height( image.GetHeight() );
+
+    if ( width && height )
+    {
+      map[ "width" ] = width;
+      map[ "height" ] = height;
+    }
+  }
+}
+
+} // namespace scripting
+
+} // namespace Dali
+
+
+
+
diff --git a/dali/devel-api/scripting/scripting.h b/dali/devel-api/scripting/scripting.h
new file mode 100644 (file)
index 0000000..40787de
--- /dev/null
@@ -0,0 +1,292 @@
+#ifndef __DALI_SCRIPTING_H__
+#define __DALI_SCRIPTING_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/actors/draw-mode.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/property-value.h>
+
+namespace Dali
+{
+
+class Actor;
+
+/**
+ * @brief Utilities for scripting support.
+ */
+namespace Scripting
+{
+
+/**
+ * @brief Template structure which stores an enumeration and its string equivalent.
+ */
+struct StringEnum
+{
+  const char* string; ///< The string representation
+  const int value;    ///< The enumeration value wrapped in int
+};
+
+/**
+ * @brief Find the given enum index from the table
+ *
+ * @param[in]  value       The string equivalent (case-insensitive).
+ * @param[in]  table       A pointer to an array with the enumeration to string equivalents.
+ * @param[in]  tableCount  Number of items in the array.
+ * @return The index of the enumeration. If enumeration is not found, logs an error and returns tableCount.
+ */
+DALI_IMPORT_API unsigned int FindEnumIndex( const char* value, const StringEnum* table, unsigned int tableCount );
+
+/**
+ * @brief Chooses the appropriate enumeration for the provided string from the given table.
+ *
+ * @param[in]  value       The string equivalent (case-insensitive).
+ * @param[in]  table       A pointer to an array with the enumeration to string equivalents.
+ * @param[in]  tableCount  Number of items in the array.
+ * @param[out] result      The enum value
+ *
+ * @return True if the value was found from the table
+ */
+template< typename T >
+bool GetEnumeration( const char* value, const StringEnum* table, unsigned int tableCount, T& result )
+{
+  bool retVal( false );
+  if( table )
+  {
+    unsigned int index = FindEnumIndex( value, table, tableCount );
+    // check to avoid crash, not asserting on purpose, error is logged instead
+    if( index < tableCount )
+    {
+      result = static_cast<T>( table[ index ].value );
+      retVal = true;
+    }
+  }
+  return retVal;
+}
+
+/**
+ * @brief Chooses the appropriate string for the provided enumeration from the given table.
+ *
+ * @param[in]  value       The enumeration.
+ * @param[in]  table       A pointer to an array with the enumeration to string equivalents.
+ * @param[in]  tableCount  Number of items in the array.
+ *
+ * @return The equivalent enumeration for the given string. Will return NULL if the value does not exist
+ *
+ * @note The caller is NOT responsible for cleaning up the returned pointer as it is statically allocated.
+ */
+template< typename T >
+const char* GetEnumerationName( T value, const StringEnum* table, unsigned int tableCount )
+{
+  if( table )
+  {
+    for ( unsigned int i = 0; i < tableCount; ++i )
+    {
+      if ( value == T(table[ i ].value) )
+      {
+        return table[ i ].string;
+      }
+    }
+  }
+  return NULL;
+}
+
+/**
+ * @brief Chooses the appropriate string for the provided enumeration from the given table.
+ * This is an optimised version that handles enumerations that start at 0 and are linear only.
+ *
+ * @param[in]  value       The enumeration.
+ * @param[in]  table       A pointer to an array with the enumeration to string equivalents.
+ * @param[in]  tableCount  Number of items in the array.
+ *
+ * @return The equivalent enumeration for the given string. Will return NULL if the value does not exist
+ *
+ * @note The caller is NOT responsible for cleaning up the returned pointer as it is statically allocated.
+ */
+template< typename T >
+const char * GetLinearEnumerationName( T value, const StringEnum* table, unsigned int tableCount )
+{
+  if ( table && ( value > 0 || value <= (int)tableCount ) )
+  {
+    return table[value].string;
+  }
+  return NULL;
+}
+
+/**
+ * @brief Takes a string and returns the appropriate color mode.
+ *
+ * @param[in] value The input string
+ * @return The corresponding color-mode.
+ */
+DALI_IMPORT_API ColorMode GetColorMode( const std::string& value );
+
+/**
+ * @brief Takes a color mode and returns the appropriate string equivalent.
+ *
+ * @param[in] value The color mode
+ * @return The corresponding string.
+ */
+DALI_IMPORT_API std::string GetColorMode( ColorMode value );
+
+/**
+ * @brief Takes a string and returns the appropriate position inheritance mode.
+ *
+ * @param[in] value The input string
+ * @return The corresponding position-inheritance-mode.
+ */
+DALI_IMPORT_API PositionInheritanceMode GetPositionInheritanceMode( const std::string& value );
+
+/**
+ * @brief Takes a position inheritance mode and returns the string equivalent.
+ *
+ * @param[in] value The position-inheritance-mode.
+ * @return The corresponding string.
+ */
+DALI_IMPORT_API std::string GetPositionInheritanceMode( PositionInheritanceMode value );
+
+/**
+ * @brief Takes a string and returns the appropriate draw mode.
+ *
+ * @param[in] value The input string
+ * @return The corresponding draw-mode.
+ */
+DALI_IMPORT_API DrawMode::Type GetDrawMode( const std::string& value );
+
+/**
+ * @brief Takes a draw-mode and returns the string equivalent.
+ *
+ * @param[in] value The draw-mode.
+ * @return The corresponding string.
+ */
+DALI_IMPORT_API std::string GetDrawMode( DrawMode::Type value );
+
+/**
+ * @brief Takes a string and returns the appropriate anchor-point or parent-origin constant.
+ *
+ * @param[in] value The input string
+ * @return The corresponding anchor-point or parent-origin constant.
+ */
+DALI_IMPORT_API Vector3 GetAnchorConstant( const std::string& value );
+
+/**
+ * @brief Creates object with data from the property value map.
+ *
+ * @param[in] property The property value map with the following valid fields:
+ * @code
+ * "filename":       type std::string
+ * "load-policy"     type std::string (enum)
+ * "release-policy"  type std::string (enum)
+ * "width"           type float
+ * "height"          type float
+ * "pixel-format"    type std::string (enum)
+ * "fitting-mode"    type std::string (enum)
+ * "sampling-mode"   type std::string (enum)
+ * "orientation"     type bool
+ * "type"            type std::string (FrameBufferImage|BufferImage|ResourceImage(default))
+ * @endcode
+ * Some fields are optional and some only pertain to a specific type.
+ *
+ * @return a pointer to a newly created object.
+ */
+DALI_IMPORT_API Image NewImage( const Property::Value& property );
+
+/**
+ * @brief Creates object with data from the property value map.
+ *
+ * @param[in] property The property value map with the following valid fields:
+ * @code
+ * // a program can be specified as string or a filename.
+ * // some fields may be ignored depending on the geometry-type
+ * "program":        type Map
+ * {
+ *   "vertex":                   type std::string
+ *   "fragment":                 type std::string
+ *   "vertex-prefix":            type std::string
+ *   "fragment-prefix":          type std::string
+ *   "text-vertex":              type std::string
+ *   "text-fragment":            type std::string
+ *   "vertex-filename":          type std::string
+ *   "fragment-filename":        type std::string
+ *   "vertex-prefix-filename":   type std::string
+ *   "fragment-prefix-filename": type std::string
+ *   "text-vertex-filename":     type std::string
+ *   "text-fragment-filename":   type std::string
+ *   "geometry-type":            type std::string (enum)
+ *   "geometry-hints":           type std::string (enum)
+ * }
+ * // uniforms must be specified to be registered
+ * "uUniform1":       type float,
+ * "uUniform2":       type float, etc
+ * @endcode
+ *
+ * @return a pointer to a newly created object.
+ */
+DALI_IMPORT_API ShaderEffect NewShaderEffect( const Property::Value& property );
+
+/**
+ * @brief Creates an actor with the date from the property value map.
+ *
+ * @param[in] map The property value map with the properties (and hierarchy) of the actor required
+ *                 For example:
+ * @code
+ * {
+ *   "type": "ImageActor",
+ *   "image":
+ *   {
+ *     "filename":"my-image-path.png"
+ *   },
+ *   "actors":
+ *   [
+ *     {
+ *       "type":"Actor",
+ *       "position":[0,0,0]
+ *     }
+ *   ]
+ * }
+ * @endcode
+ *
+ * @return Handle to the newly created actor.
+ */
+DALI_IMPORT_API Actor NewActor( const Property::Map& map );
+
+/**
+ * @brief Creates a Property::Map from the actor provided.
+ *
+ * @param[in] actor The base-actor from which a Property::Map should be created
+ * @param[out] map This map is cleared and a property map of actor and its children is filled in
+ */
+DALI_IMPORT_API void CreatePropertyMap( Actor actor, Property::Map& map );
+
+/**
+ * @brief Creates a Property::Map from the image provided.
+ *
+ * @param[in] image The image from which a Property::Map should be created
+ * @param[out] map This map is cleared and a property map of the image is filled in
+ */
+DALI_IMPORT_API void CreatePropertyMap( Image image, Property::Map& map );
+
+}
+
+} // namespace Dali
+
+#endif // __DALI_SCRIPTING_H__
diff --git a/dali/integration-api/bitmap.cpp b/dali/integration-api/bitmap.cpp
new file mode 100644 (file)
index 0000000..bfff2d5
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/bitmap.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/images/bitmap-packed-pixel.h>
+#include <dali/internal/event/images/bitmap-compressed.h>
+#include <dali/internal/event/images/bitmap-external.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+using namespace Dali::Pixel;
+
+void ConvertToGlFormat( Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat )
+{
+  // Compressed textures have no pixelDataType, so init to an invalid value:
+  pixelDataType  = -1;
+
+  switch( pixelformat )
+  {
+    case A8:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_ALPHA;
+      break;
+    }
+
+    case L8:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_LUMINANCE;
+      break;
+    }
+
+    case LA88:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_LUMINANCE_ALPHA;
+      break;
+    }
+
+    case RGB565:
+    {
+      pixelDataType = GL_UNSIGNED_SHORT_5_6_5;
+      internalFormat= GL_RGB;
+      break;
+    }
+
+    case BGR565:
+    {
+      DALI_LOG_ERROR("Pixel format BGR565 is not supported by GLES.\n");
+      pixelDataType  = GL_UNSIGNED_SHORT_5_6_5;
+#ifdef _ARCH_ARM_
+      internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
+#else
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+#endif
+      break;
+    }
+
+    case RGBA4444:
+    {
+      pixelDataType = GL_UNSIGNED_SHORT_4_4_4_4;
+      internalFormat= GL_RGBA;
+      break;
+    }
+
+    case BGRA4444:
+    {
+      DALI_LOG_ERROR("Pixel format BGRA4444 is not supported by GLES.\n");
+      pixelDataType  = GL_UNSIGNED_SHORT_4_4_4_4;
+#ifdef _ARCH_ARM_
+      internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
+#else
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+#endif
+      break;
+    }
+
+    case RGBA5551:
+    {
+      pixelDataType = GL_UNSIGNED_SHORT_5_5_5_1;
+      internalFormat= GL_RGBA;
+      break;
+    }
+
+    case BGRA5551:
+    {
+      DALI_LOG_ERROR("Pixel format BGRA5551 is not supported by GLES.\n");
+      pixelDataType  = GL_UNSIGNED_SHORT_5_5_5_1;
+#ifdef _ARCH_ARM_
+      internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
+#else
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+#endif
+      break;
+    }
+
+    case RGB888:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_RGB;
+      break;
+    }
+
+    case RGB8888:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+      break;
+    }
+
+    case BGR8888:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+#ifdef GL_BGRA_EXT
+      internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
+#else
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+#endif
+    break;
+    }
+
+    case RGBA8888:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+      internalFormat= GL_RGBA;
+      break;
+    }
+
+    case BGRA8888:
+    {
+      pixelDataType = GL_UNSIGNED_BYTE;
+#ifdef GL_BGRA_EXT
+      internalFormat= GL_BGRA_EXT; // alpha is reserved but not used
+#else
+      internalFormat= GL_RGBA;     // alpha is reserved but not used
+#endif
+      break;
+    }
+
+    // GLES 3.0 standard compressed formats:
+    case COMPRESSED_R11_EAC:
+    {
+      DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_R11_EAC.\n");
+      internalFormat = 0x9270; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_SIGNED_R11_EAC:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_R11_EAC.\n" );
+      internalFormat = 0x9271; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      ;
+      break;
+    }
+    case COMPRESSED_RG11_EAC:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RG11_EAC.\n" );
+      internalFormat = 0x9272; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_SIGNED_RG11_EAC:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SIGNED_RG11_EAC.\n" );
+      internalFormat = 0x9273; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_RGB8_ETC2:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_ETC2.\n" );
+      internalFormat = 0x9274; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_SRGB8_ETC2:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ETC2.\n" );
+      internalFormat = 0x9275; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
+      internalFormat = 0x9276; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2.\n" );
+      internalFormat = 0x9277; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_RGBA8_ETC2_EAC:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_RGBA8_ETC2_EAC.\n" );
+      internalFormat = 0x9278; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using GLES 3.0 standard compressed pixel format COMPRESSED_SRGB8_ALPHA8_ETC2_EAC.\n" );
+      internalFormat = 0x9279; ///! < Hardcoded until we move to GLES 3.0 or greater.
+      break;
+    }
+
+    // GLES 2 extension compressed formats:
+    case COMPRESSED_RGB8_ETC1:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB8_ETC1.\n" );
+      internalFormat = 0x8D64; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
+      break;
+    }
+    case COMPRESSED_RGB_PVRTC_4BPPV1:
+    {
+      DALI_LOG_INFO( Debug::Filter::gImage, Debug::Verbose, "Using non-standard GLES 2.0 extension compressed pixel format COMPRESSED_RGB_PVRTC_4BPPV1.\n" );
+      internalFormat = 0x8C00; ///! < Hardcoded so we can test before we move to GLES 3.0 or greater.
+      break;
+    }
+  }
+}
+
+Bitmap* Bitmap::New( const Profile profile = BITMAP_2D_PACKED_PIXELS,
+                     ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_DISCARD )
+{
+  DALI_ASSERT_DEBUG(profile == BITMAP_2D_PACKED_PIXELS || profile == BITMAP_COMPRESSED);
+
+  switch( profile )
+  {
+    /** A 2D array of pixels where each pixel is a whole number of bytes
+     * and each scanline of the backing memory buffer may have additional
+     * bytes off the right edge if requested, and there may be additional
+     * scanlines past the bottom of the image in the buffer if requested.*/
+    case BITMAP_2D_PACKED_PIXELS:
+    {
+      Bitmap * const bitmap = new Dali::Internal::BitmapPackedPixel( discardable );
+      return bitmap;
+    }
+
+    /** The data for the bitmap is buffered in an opaque form.*/
+    case BITMAP_COMPRESSED:
+    {
+      return new Dali::Internal::BitmapCompressed( discardable );
+    }
+  }
+  return 0;
+}
+
+
+Bitmap::Bitmap( ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf)
+: mImageWidth(0),
+  mImageHeight(0),
+  mPixelFormat(Pixel::RGBA8888),
+  mHasAlphaChannel(true),
+  mAlphaChannelUsed(true),
+  mData(pixBuf),
+  mDiscardable(discardable)
+{
+}
+
+void Bitmap::DiscardBuffer()
+{
+  if( mDiscardable == ResourcePolicy::OWNED_DISCARD )
+  {
+    DeletePixelBuffer();
+  }
+}
+
+Bitmap::~Bitmap()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  // If owned
+  if( mDiscardable == ResourcePolicy::OWNED_DISCARD ||
+      mDiscardable == ResourcePolicy::OWNED_RETAIN )
+  {
+    DeletePixelBuffer();
+  }
+}
+
+/**
+ * */
+void Bitmap::DeletePixelBuffer()
+{
+  if( !mData )
+  {
+    return;
+  }
+  free ( mData );
+  mData = NULL;
+}
+
+
+void Bitmap::Initialize( Pixel::Format pixelFormat,
+                          unsigned int width,
+                          unsigned int height)
+{
+  DALI_ASSERT_DEBUG(width * height < (32 * 1024) * (32 * 1024) && "The total area of the bitmap is too great.\n");
+  mImageWidth   = width;
+  mImageHeight  = height;
+  mPixelFormat  = pixelFormat;
+
+  mHasAlphaChannel = Pixel::HasAlpha(pixelFormat);
+}
+
+} //namespace Integration
+
+} //namespace Dali
diff --git a/dali/integration-api/bitmap.h b/dali/integration-api/bitmap.h
new file mode 100644 (file)
index 0000000..6319ae1
--- /dev/null
@@ -0,0 +1,348 @@
+#ifndef __DALI_INTEGRATION_BITMAP_H__
+#define __DALI_INTEGRATION_BITMAP_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/resource-policies.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * Returns GL data type and internal format for specified pixel format
+ * @param[in]  pixelformat    pixel format (eg. Pixel::RGBA32)
+ * @param[out] pixelDataType  pixel data type (eg. GL_UNSIGNED_BYTE)
+ * @param[out] internalFormat pixel internal format (eg. GL_RGBA)
+ */
+DALI_IMPORT_API void ConvertToGlFormat(Pixel::Format pixelformat, unsigned& pixelDataType, unsigned& internalFormat);
+
+class Bitmap;
+typedef IntrusivePtr<Bitmap>    BitmapPtr;
+typedef unsigned char                 PixelBuffer;  ///< Pixel data buffers are composed of these
+
+/**
+ * Bitmap class.
+ * An abstract container for image data.
+ * \sa{BitmapPackedPixel BitmapCompressed BitmapExternal} for concrete
+ * subclasses.
+ */
+class DALI_IMPORT_API Bitmap : public Dali::RefObject
+{
+protected:
+
+  /**
+   * Constructor
+   * Use the static function Bitmap::New() to create instances.
+   * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
+   * @param[in] pixBuf External buffer of pixel data or null.
+   */
+  Bitmap( ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_RETAIN, Dali::Integration::PixelBuffer* pixBuf = 0 );
+
+  /**
+   * Initializes internal class members
+   * @param[in] pixelFormat   pixel format
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   */
+  void Initialize(Pixel::Format pixelFormat,
+                           unsigned int width,
+                           unsigned int height);
+
+
+public:
+  /** Defines the characteristics of the Bitmap returned from the factory
+   *  function. */
+  enum Profile
+  {
+    /** A 2D array of pixels where each pixel is a whole number of bytes
+     * and each scanline of the backing memory buffer may have additional
+     * bytes off the right edge if requested, and there may be additional
+     * scanlines past the bottom of the image in the buffer if requested.*/
+    BITMAP_2D_PACKED_PIXELS,
+    /** The data for the bitmap is buffered in an opaque form.*/
+    BITMAP_COMPRESSED
+  };
+
+  /**
+   * Create a new instance of a Bitmap with the required profile.
+   * @return Pointer to created Bitmap subclass. Clients should immediately
+   * wrap this in a reference-counting smart pointer or store it in a similarly
+   * automatic owning collection.
+   * @param[in] profile Defines required features of the bitmap (\sa Profile).
+   * @param[in] discardable OWNED_DISCARD means that the data is owned by bitmap,
+   * and may released away after uploading to GPU.
+   * OWNED_RETAIN means that the data is owned and must be kept in CPU memory
+   * e.g. for an image that cannot be reloaded from disk.
+   * NOT_OWNED means that the data is managed by an external component and is
+   * guaranteed to remain dereferenceable at least as long as the Bitmap remains alive.
+   */
+  static Bitmap* New( Profile profile, ResourcePolicy::Discardable discardable );
+
+  /** \name GeneralFeatures
+   * Features that are generic between profiles. */
+  /**@{*/
+
+  /**
+   * Get the width of the image
+   * @return The width of the image
+   */
+  unsigned int GetImageWidth() const
+  {
+    return mImageWidth;
+  }
+
+  /**
+   * Get the height of the image
+   * @return The height of the image
+   */
+  unsigned int GetImageHeight() const
+  {
+    return mImageHeight;
+  }
+
+  /**
+   * Get the pixel format
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const
+  {
+    return mPixelFormat;
+  }
+
+  /**
+   * Get the pixel buffer if it's present.
+   * @return The buffer if present, or NULL if there is no pixel buffer.
+   * You can modify its contents.
+   * @sa ReserveBuffer GetBufferSize
+   */
+  virtual PixelBuffer* GetBuffer()
+  {
+    return mData;
+  }
+
+  /**
+   * Get the pixel buffer size in bytes
+   * @return The buffer size in bytes.
+   * @sa ReserveBuffer GetBuffer
+   */
+  virtual size_t GetBufferSize() const = 0;
+
+  /**
+   * Queries if the bitmap has an alpha channel
+   * @return true if there is an alpha channel
+   */
+  bool HasAlphaChannel() const
+  {
+    return mHasAlphaChannel;
+  }
+
+  /**
+   * Queries if the bitmap has any transparent data
+   * @return true if the bitmap has alpha data
+   */
+  bool IsFullyOpaque() const
+  {
+    // check pixel format for alpha channel
+    return !(HasAlphaChannel() && mAlphaChannelUsed);
+  }
+
+  /**@}*/ ///< End of generic features
+
+
+  /** \name PackedPixelsProfile
+   * Features that are active only if the Bitmap was created with a
+   * BITMAP_2D_PACKED_PIXELS profile. */
+  /**@{*/
+
+  class PackedPixelsProfile
+  {
+  public:
+
+    /**
+     * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer is deleted.
+     * Dali has ownership of the buffer, but its contents can be modified.
+     * Bitmap stores given size information about the image.
+     * @pre bufferWidth, bufferHeight have to be power of two
+     * @param[in] pixelFormat   pixel format
+     * @param[in] width         Image width in pixels
+     * @param[in] height        Image height in pixels
+     * @param[in] bufferWidth   Buffer width (stride) in pixels
+     * @param[in] bufferHeight  Buffer height in pixels
+     * @return pixel buffer pointer
+     */
+    virtual PixelBuffer* ReserveBuffer(Pixel::Format pixelFormat,
+                                       unsigned int width,
+                                       unsigned int height,
+                                       unsigned int bufferWidth = 0,
+                                       unsigned int bufferHeight = 0) = 0;
+
+    /**
+     * Assign a pixel buffer. Any previously allocated pixel buffer is deleted.
+     * Dali has ownership of the buffer, but it iss allowable to modify its
+     * contents after it is assigned, but before it is used.
+     * Bitmap stores the provided size information about the image.
+     *
+     * The buffer must have been allocated with the C++ array new operator, not
+     * with malloc or as a local or static object. The precise form is as follows:
+     *
+     *    PixelBuffer * buffer = new PixelBuffer[bufSize];
+     *
+     * @pre bufferWidth, bufferHeight have to be power of two
+     * @param[in] pixelFormat   pixel format
+     * @param[in] buffer        the pixel buffer
+     * @param[in] bufferSize    size of the pixel buffer
+     * @param[in] width         Image width in pixels
+     * @param[in] height        Image height in pixels
+     * @param[in] bufferWidth   Buffer width (stride) in pixels
+     * @param[in] bufferHeight  Buffer height in pixels
+     */
+    virtual void AssignBuffer(Pixel::Format pixelFormat,
+                              PixelBuffer* buffer,
+                              std::size_t bufferSize,
+                              unsigned int width,
+                              unsigned int height,
+                              unsigned int bufferWidth = 0,
+                              unsigned int bufferHeight = 0) = 0;
+    /**
+     * Get the width of the buffer (stride)
+     * @return The width of the buffer in pixels
+     */
+    virtual unsigned int GetBufferWidth() const = 0;
+
+    /**
+     * Get the height of the buffer
+     * @return The height of the buffer in pixels
+     */
+    virtual unsigned int GetBufferHeight() const = 0;
+
+    /**
+     * Get the pixel buffer stride.
+     * @return The buffer stride (in bytes) if this is bitmap of non-compressed
+     * packed pixels for which a stride is meaningful or 0 otherwise.
+     */
+    virtual unsigned int GetBufferStride() const = 0;
+
+    /**
+     * Check the bitmap data and test whether it has any transparent pixels.
+     * This property can then be tested for with IsFullyOpaque().
+     */
+    virtual void TestForTransparency() = 0;
+  };
+
+  /**
+   * Get interface to features that are active only if the Bitmap was created
+   * with a BITMAP_2D_PACKED_PIXELS profile. */
+  virtual const PackedPixelsProfile* GetPackedPixelsProfile() const { return 0; }
+  /**
+   * Get interface to features that are active only if the Bitmap was created
+   * with a BITMAP_2D_PACKED_PIXELS profile. */
+  virtual PackedPixelsProfile* GetPackedPixelsProfile() { return 0; }
+
+  /**@}*/ ///< End of packed pixel features.
+
+
+  /** \name CompressedProfile
+   * Features that only apply to opaque/compressed formats. */
+  /**@{*/
+
+  class CompressedProfile
+  {
+  public:
+    /**
+     * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer
+     * is deleted.
+     * Dali has ownership of the buffer, and contents are opaque and immutable.
+     * Bitmap stores given size information about the image which the client is assumed
+     * to have retrieved from out-of-band image metadata.
+     * @param[in] pixelFormat   pixel format
+     * @param[in] width         Image width in pixels
+     * @param[in] height        Image height in pixels
+     * @param[in] bufferSize    Buffer size in bytes
+     * @return pixel buffer pointer
+     */
+    virtual PixelBuffer* ReserveBufferOfSize( Pixel::Format pixelFormat,
+                                       const unsigned width,
+                                       const unsigned height,
+                                       const size_t numBytes ) = 0;
+  };
+
+  virtual const CompressedProfile* GetCompressedProfile() const { return 0; }
+  virtual CompressedProfile* GetCompressedProfile() { return 0; }
+  /**@}*/
+
+
+  /**
+   * Inform the bitmap that its pixel buffer is no longer required and can be
+   * deleted to free up memory if the bitmap owns the buffer.
+   */
+  void DiscardBuffer();
+
+  /**
+   * Check if the pixel buffer can be discarded
+   * @return true if the pixel buffer can be discarded
+   */
+  bool IsDiscardable() const
+  {
+    return mDiscardable == ResourcePolicy::OWNED_DISCARD;
+  }
+
+  /**
+   * Delete the pixel buffer data
+   */
+  void DeletePixelBuffer();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Bitmap();
+
+protected:
+
+  unsigned int  mImageWidth;          ///< Image width in pixels
+  unsigned int  mImageHeight;         ///< Image height in pixels
+  Pixel::Format mPixelFormat;         ///< Pixel format
+  bool          mHasAlphaChannel;   ///< Whether the image has an alpha channel
+  bool          mAlphaChannelUsed;  ///< Whether the alpha channel is used in case the image owns one.
+  PixelBuffer*  mData;            ///< Raw pixel data
+
+private:
+
+  ResourcePolicy::Discardable mDiscardable; ///< Should delete the buffer when discard buffer is called.
+
+  Bitmap(const Bitmap& other);  ///< defined private to prevent use
+  Bitmap& operator = (const Bitmap& other); ///< defined private to prevent use
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_BITMAP_H__
diff --git a/dali/integration-api/context-notifier.h b/dali/integration-api/context-notifier.h
new file mode 100644 (file)
index 0000000..348f292
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__
+#define __DALI_INTEGRATION_CONTEXT_NOTIFIER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Dali
+{
+namespace Integration
+{
+
+/**
+ * Interface to inform dali core of context loss and regain
+ */
+class ContextNotifierInterface
+{
+public:
+  /**
+   * Notify that the GL context has been lost, e.g. during ReplaceSurface
+   * or Pause.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  virtual void NotifyContextLost() = 0;
+
+  /**
+   * Notify that the GL context has been re-created, e.g. after ReplaceSurface
+   * or Context loss.
+   *
+   * In the case of ReplaceSurface, both ContextDestroyed() and ContextCreated() will have
+   * been called on the render thread before this is called on the event thread.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  virtual void NotifyContextRegained() = 0;
+};
+
+} // namespace Integration
+} // namespace Dali
+
+
+#endif // __DALI_INTEGRATION_CONTEXT_NOTIFICATION_H__
diff --git a/dali/integration-api/core.cpp b/dali/integration-api/core.cpp
new file mode 100644 (file)
index 0000000..2648940
--- /dev/null
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/core.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/events/event.h>
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/internal/common/core-impl.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+Core* Core::New(RenderController& renderController, PlatformAbstraction& platformAbstraction,
+                GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction, GestureManager& gestureManager, ResourcePolicy::DataRetention policy )
+{
+  Core* instance = new Core;
+  instance->mImpl = new Internal::Core( renderController, platformAbstraction, glAbstraction, glSyncAbstraction, gestureManager, policy );
+
+  return instance;
+}
+
+Core::~Core()
+{
+  delete mImpl;
+}
+
+ContextNotifierInterface* Core::GetContextNotifier()
+{
+  return mImpl->GetContextNotifier();
+}
+
+// @todo Rename to ResetGlContext
+void Core::ContextCreated()
+{
+  mImpl->ContextCreated();
+}
+
+// @todo Replace with StopRendering that prevents RenderManager from rendering
+// until we get ResetGLContext again, change ContextCreated to reset gpu buffer cache,
+// gl texture id's
+void Core::ContextDestroyed()
+{
+  mImpl->ContextDestroyed();
+}
+
+void Core::RecoverFromContextLoss()
+{
+  mImpl->RecoverFromContextLoss();
+}
+
+void Core::SurfaceResized(unsigned int width, unsigned int height)
+{
+  mImpl->SurfaceResized(width, height);
+}
+
+void Core::SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical)
+{
+  mImpl->SetDpi(dpiHorizontal, dpiVertical);
+}
+
+void Core::Suspend()
+{
+  mImpl->Suspend();
+}
+
+void Core::Resume()
+{
+  mImpl->Resume();
+}
+
+void Core::SceneCreated()
+{
+  mImpl->SceneCreated();
+}
+
+void Core::QueueEvent(const Event& event)
+{
+  mImpl->QueueEvent(event);
+}
+
+void Core::ProcessEvents()
+{
+  mImpl->ProcessEvents();
+}
+
+void Core::UpdateTouchData(const TouchData& touch)
+{
+  mImpl->UpdateTouchData(touch);
+}
+
+unsigned int Core::GetMaximumUpdateCount() const
+{
+  return mImpl->GetMaximumUpdateCount();
+}
+
+void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, UpdateStatus& status )
+{
+  mImpl->Update( elapsedSeconds, lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds, status );
+}
+
+void Core::Render( RenderStatus& status )
+{
+  mImpl->Render( status );
+}
+
+SystemOverlay& Core::GetSystemOverlay()
+{
+  return mImpl->GetSystemOverlay();
+}
+
+void Core::SetViewMode( ViewMode viewMode )
+{
+  mImpl->SetViewMode( viewMode );
+}
+
+ViewMode Core::GetViewMode() const
+{
+  return mImpl->GetViewMode();
+}
+
+void Core::SetStereoBase( float stereoBase )
+{
+  mImpl->SetStereoBase( stereoBase );
+}
+
+float Core::GetStereoBase() const
+{
+  return mImpl->GetStereoBase();
+}
+
+void Core::SetPixmapYInverted( bool yInverted )
+{
+  mImpl->SetPixmapYInverted( yInverted );
+}
+
+Core::Core()
+: mImpl( NULL )
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/core.h b/dali/integration-api/core.h
new file mode 100644 (file)
index 0000000..018e3e9
--- /dev/null
@@ -0,0 +1,437 @@
+#ifndef __DALI_INTEGRATION_CORE_H__
+#define __DALI_INTEGRATION_CORE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/view-mode.h>
+#include <dali/integration-api/context-notifier.h>
+#include <dali/integration-api/resource-policies.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class Core;
+}
+
+namespace Integration
+{
+
+class Core;
+class GestureManager;
+class GlAbstraction;
+class GlSyncAbstraction;
+class PlatformAbstraction;
+class RenderController;
+class SystemOverlay;
+struct Event;
+struct TouchData;
+
+
+/**
+ * The reasons why further updates are required.
+ */
+namespace KeepUpdating
+{
+enum Reasons
+{
+  NOT_REQUESTED           = 0,    ///< Zero means that no further updates are required
+  STAGE_KEEP_RENDERING    = 1<<1, ///<  - Stage::KeepRendering() is being used
+  ANIMATIONS_RUNNING      = 1<<2, ///< - Animations are ongoing
+  LOADING_RESOURCES       = 1<<3, ///< - Resources are being loaded
+  MONITORING_PERFORMANCE  = 1<<4, ///< - The --enable-performance-monitor option is being used
+  RENDER_TASK_SYNC        = 1<<5  ///< - A render task is waiting for render sync
+};
+}
+
+/**
+ * The status of the Core::Update operation.
+ */
+class UpdateStatus
+{
+public:
+
+  /**
+   * Constructor
+   */
+  UpdateStatus()
+  : keepUpdating(false),
+    needsNotification(false),
+    secondsFromLastFrame( 0.0f )
+  {
+  }
+
+public:
+
+  /**
+   * Query whether the Core has further frames to update & render e.g. when animations are ongoing.
+   * @return A bitmask of KeepUpdating values
+   */
+  unsigned int KeepUpdating() { return keepUpdating; }
+
+  /**
+   * Query whether the Core requires an Notification event.
+   * This should be sent through the same mechanism (e.g. event loop) as input events.
+   * @return True if an Notification event should be sent.
+   */
+  bool NeedsNotification() { return needsNotification; }
+
+  /**
+   * This method is provided so that FPS can be easily calculated with a release version
+   * of Core.
+   * @return the seconds from last frame as float
+   */
+  float SecondsFromLastFrame() { return secondsFromLastFrame; }
+
+public:
+
+  unsigned int keepUpdating; ///< A bitmask of KeepUpdating values
+  bool needsNotification;
+  float secondsFromLastFrame;
+};
+
+/**
+ * The status of the Core::Render operation.
+ */
+class RenderStatus
+{
+public:
+
+  /**
+   * Constructor
+   */
+  RenderStatus()
+  : needsUpdate(false),
+    hasRendered(false)
+  {
+  }
+
+  /**
+   * Set whether update needs to run following a render.
+   * This might be because render has sent messages to update, or it has
+   * some textures to upload over several frames.
+   */
+  void SetNeedsUpdate(bool updateRequired) { needsUpdate = updateRequired; }
+
+  /**
+   * Query the update status following rendering of a frame.
+   * @return true if update should run.
+   */
+  bool NeedsUpdate() { return needsUpdate; }
+
+  /**
+   * Set whether there were new render instructions.
+   */
+  void SetHasRendered(bool rendered) { hasRendered = rendered; }
+
+  /**
+   * Query whether there were new render instructions.
+   * @return true if there were render instructions
+   */
+  bool HasRendered() { return hasRendered; }
+
+private:
+
+  bool needsUpdate;
+  bool hasRendered;
+};
+
+/**
+ * Integration::Core is used for integration with the native windowing system.
+ * The following integration tasks must be completed:
+ *
+ * 1) Handle GL context creation, and notify the Core when this occurs.
+ *
+ * 2) Provide suspend/resume behaviour (see below for more details).
+ *
+ * 3) Run an event loop, for passing events to the Core e.g. multi-touch input events.
+ * Notification events should be sent after a frame is updated (see UpdateStatus).
+ *
+ * 4) Run a rendering loop, instructing the Core to render each frame.
+ * A separate rendering thread is recommended; see multi-threading options below.
+ *
+ * 5) Provide an implementation of the PlatformAbstraction interface, used to access platform specific services.
+ *
+ * 6) Provide an implementation of the GlAbstraction interface, used to access OpenGL services.
+ *
+ * 7) Provide an implementation of the GestureManager interface, used to register gestures provided by the platform.
+ *
+ * Suspend/Resume behaviour:
+ *
+ * The Core has no knowledge of the application lifecycle, but can be suspended.
+ * In the suspended state, input events will not be processed, and animations will not progress any further.
+ * The Core can still render in the suspended state; the same frame will be produced each time.
+ *
+ * Multi-threading notes:
+ *
+ * The Dali API methods are not reentrant.  If you access the API from multiple threads simultaneously, then the results
+ * are undefined. This means that your application might segfault, or behave unpredictably.
+ *
+ * Rendering strategies:
+ *
+ * 1) Single-threaded. Call every Core method from the same thread. Event handling and rendering will occur in the same thread.
+ * This is not recommended, since processing input (slowly) can affect the smooth flow of animations.
+ *
+ * 2) Multi-threaded. The Core update & render operations can be processed in separate threads.
+ * See the method descriptions in Core to see which thread they should be called from.
+ * This is the recommended option, so that input processing will not affect the smoothness of animations.
+ * Note that the rendering thread must be halted, before destroying the GL context.
+ */
+class DALI_IMPORT_API Core
+{
+public:
+
+  /**
+   * Create a new Core.
+   * This object is used for integration with the native windowing system.
+   * @param[in] renderController The interface to an object which controls rendering.
+   * @param[in] platformAbstraction The interface providing platform specific services.
+   * @param[in] glAbstraction The interface providing OpenGL services.
+   * @param[in] glSyncAbstraction The interface providing OpenGL sync objects.
+   * @param[in] gestureManager The interface providing gesture manager services.
+   * @param[in] policy The data retention policy. This depends on application setting
+   * and platform support. Dali should honour this policy when deciding to discard
+   * intermediate resource data.
+   * @return A newly allocated Core.
+   */
+  static Core* New(RenderController& renderController,
+                   PlatformAbstraction& platformAbstraction,
+                   GlAbstraction& glAbstraction,
+                   GlSyncAbstraction& glSyncAbstraction,
+                   GestureManager& gestureManager,
+                   ResourcePolicy::DataRetention policy);
+
+  /**
+   * Non-virtual destructor. Core is not intended as a base class.
+   */
+  ~Core();
+
+  // GL Context Lifecycle
+
+  /**
+   * Get the object that will notify the application/toolkit when context is lost/regained
+   */
+  ContextNotifierInterface* GetContextNotifier();
+
+  /**
+   * Notify the Core that the GL context has been created.
+   * The context must be created before the Core can render.
+   * Multi-threading note: this method should be called from the rendering thread only
+   * @post The Core is aware of the GL context.
+   */
+  void ContextCreated();
+
+  /**
+   * Notify the Core that that GL context is about to be destroyed.
+   * The Core will free any previously allocated GL resources.
+   * Multi-threading note: this method should be called from the rendering thread only
+   * @post The Core is unaware of any GL context.
+   */
+  void ContextDestroyed();
+
+  /**
+   * Notify the Core that the GL context has been re-created, e.g. after ReplaceSurface
+   * or Context loss.
+   *
+   * In the case of ReplaceSurface, both ContextToBeDestroyed() and ContextCreated() will have
+   * been called on the render thread before this is called on the event thread.
+   *
+   * Multi-threading note: this method should be called from the main thread
+   */
+  void RecoverFromContextLoss();
+
+  /**
+   * Notify the Core that the GL surface has been resized.
+   * This should be done at least once i.e. after the first call to ContextCreated().
+   * The Core will use the surface size for camera calculations, and to set the GL viewport.
+   * Multi-threading note: this method should be called from the main thread
+   * @param[in] width The new surface width.
+   * @param[in] height The new surface height.
+   */
+  void SurfaceResized(unsigned int width, unsigned int height);
+
+  // Core setters
+
+  /**
+   * Notify the Core about the display's DPI values.
+   * This should be done after the display is initialized and a Core instance is created.
+   * The Core will use the DPI values for font rendering.
+   * Multi-threading note: this method should be called from the main thread
+   * @param[in] dpiHorizontal Horizontal DPI value.
+   * @param[in] dpiVertical   Vertical DPI value.
+   */
+  void SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical);
+
+  // Core Lifecycle
+
+  /**
+   * Put Core into the suspended state.
+   * Any ongoing event processing will be cancelled, for example multi-touch sequences.
+   * The core expects the system has suspended us. Animation time will continue during the suspended
+   * state.
+   * Multi-threading note: this method should be called from the main thread
+   * @post The Core is in the suspended state.
+   */
+  void Suspend();
+
+  /**
+   * Resume the Core from the suspended state.
+   * At the first update, the elapsed time passed to the animations will be equal to the time spent
+   * suspended.
+   * Multi-threading note: this method should be called from the main thread
+   * @post The Core is not in the suspended state.
+   */
+  void Resume();
+
+  /**
+   * Notify Core that the scene has been created.
+   */
+  void SceneCreated();
+
+  /**
+   * Queue an event with Core.
+   * Pre-processing of events may be beneficial e.g. a series of motion events could be throttled, so that only the last event is queued.
+   * Multi-threading note: this method should be called from the main thread.
+   * @param[in] event The new event.
+   */
+  void QueueEvent(const Event& event);
+
+  /**
+   * Process the events queued with QueueEvent().
+   * Multi-threading note: this method should be called from the main thread.
+   * @pre ProcessEvents should not be called during ProcessEvents.
+   */
+  void ProcessEvents();
+
+  /**
+   * Update external raw touch data in core.
+   * The core will use the touch data to generate Dali Touch/Gesture events for applications to use
+   * in the update thread.
+   * @param[in] touch The raw touch data.
+   * @note This can be called from either the event thread OR a dedicated touch thread.
+   */
+  void UpdateTouchData(const TouchData& touch);
+
+  /**
+   * The Core::Update() method prepares a frame for rendering. This method determines how many frames
+   * may be prepared, ahead of the rendering.
+   * For example if the maximum update count is 2, then Core::Update() for frame N+1 may be processed
+   * whilst frame N is being rendered. However the Core::Update() for frame N+2 may not be called, until
+   * the Core::Render() method for frame N has returned.
+   * @return The maximum update count (>= 1).
+   */
+  unsigned int GetMaximumUpdateCount() const;
+
+  /**
+   * Update the scene for the next frame. This method must be called before each frame is rendered.
+   * Multi-threading notes: this method should be called from a dedicated update-thread.
+   * The update for frame N+1 may be processed whilst frame N is being rendered.
+   * However the update-thread must wait until frame N has been rendered, before processing frame N+2.
+   * After this method returns, messages may be queued internally for the main thread.
+   * In order to process these messages, a notification is sent via the main thread's event loop.
+   * @param[in] elapsedSeconds Number of seconds since the last call
+   * @param[in] lastVSyncTimeMilliseconds The last vsync time in milliseconds
+   * @param[in] nextVSyncTimeMilliseconds The time of the next predicted VSync in milliseconds
+   * @param[out] status showing whether further updates are required. This also shows
+   * whether a Notification event should be sent, regardless of whether the multi-threading is used.
+   */
+  void Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, UpdateStatus& status );
+
+  /**
+   * Render the next frame. This method should be preceded by a call up Update.
+   * Multi-threading note: this method should be called from a dedicated rendering thread.
+   * @pre The GL context must have been created, and made current.
+   * @param[out] status showing whether update is required to run.
+   */
+  void Render( RenderStatus& status );
+
+  // System-level overlay
+
+  /**
+   * Use the SystemOverlay to draw content for system-level indicators, dialogs etc.
+   * @return The SystemOverlay.
+   */
+  SystemOverlay& GetSystemOverlay();
+
+  /**
+   * Set the stereoscopic 3D view mode
+   * @param[in] viewMode The new view mode
+   */
+  void SetViewMode( ViewMode viewMode );
+
+  /**
+   * Get the current view mode
+   * @return The current view mode
+   * @see SetViewMode.
+   */
+  ViewMode GetViewMode() const;
+
+  /**
+   * Set the stereo base (eye seperation) for stereoscopic 3D
+   * @param[in] stereoBase The stereo base (eye seperation) for stereoscopic 3D (mm)
+   */
+  void SetStereoBase( float stereoBase );
+
+  /**
+   * Get the stereo base (eye seperation) for stereoscopic 3D
+   * @return The stereo base (eye seperation) for stereoscopic 3D (mm)
+   */
+  float GetStereoBase() const;
+
+  // Pixmap
+
+  /**
+   * Set true if an pixmap image is y-inverted
+   */
+  void SetPixmapYInverted( bool yInverted );
+
+private:
+
+  /**
+   * Private constructor; see also Core::New()
+   */
+  Core();
+
+  /**
+   * Undefined copy-constructor.
+   * This avoids accidental calls to a default copy-constructor.
+   * @param[in] core A reference to the object to copy.
+   */
+  Core(const Core& core);
+
+  /**
+   * Undefined assignment operator.
+   * This avoids accidental calls to a default assignment operator.
+   * @param[in] rhs A reference to the object to copy.
+   */
+  Core& operator=(const Core& rhs);
+
+private:
+
+  Internal::Core* mImpl;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_CORE_H__
diff --git a/dali/integration-api/debug.cpp b/dali/integration-api/debug.cpp
new file mode 100644 (file)
index 0000000..dd62a17
--- /dev/null
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/debug.h>
+
+// EXTERNAL INCLUDES
+#include <cstdio>
+#include <cstdarg>
+#include <cstring>
+#include <cstdlib>
+#include <sstream>
+#include <iomanip>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+
+namespace Dali
+{
+
+namespace // unnamed namespace
+{
+
+/**
+ * Generic function to print out any 2-Dimensional array
+ * @param[in] data pointer to the source data stored as float[rows][cols]
+ * @param[in] rows number of rows in 2D array
+ * @param[in] cols number of columns in 2D array
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the 2D array
+ */
+std::string Array2DToString(const float *data, unsigned int rows, unsigned int cols, size_t precision, size_t indent)
+{
+  std::ostringstream oss;
+
+  std::ios_base::fmtflags mask = oss.flags();
+  mask &= ~std::ios_base::scientific;
+  mask |=  std::ios_base::fixed;
+
+  for(unsigned int rowIdx = 0; rowIdx < rows; rowIdx++)
+  {
+    oss  << std::setw(indent) << std::setfill(' ') << ' ' << "[ ";
+    oss  << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(mask);
+
+    for(unsigned int colIdx = 0; colIdx < cols; colIdx++)
+    {
+      oss << std::setw(precision + 6) << (*data++) << ' ';
+    }
+
+    oss << ']' << std::endl;
+  }
+
+  return oss.str();
+}
+
+}
+
+namespace Integration
+{
+
+namespace Log
+{
+
+__thread LogFunction gthreadLocalLogFunction = NULL;
+
+/* Forward declarations */
+std::string FormatToString(const char *format, ...);
+std::string ArgListToString(const char *format, va_list args);
+
+void LogMessage(DebugPriority priority, const char* format, ...)
+{
+  if ( !gthreadLocalLogFunction )
+  {
+    return;
+  }
+
+  va_list arg;
+  va_start(arg, format);
+  std::string message = ArgListToString(format, arg);
+  va_end(arg);
+
+  gthreadLocalLogFunction(priority,message);
+}
+
+void InstallLogFunction(const LogFunction& logFunction)
+{
+  // TLS stores a pointer to an object.
+  // It needs to be allocated on the heap, because TLS will destroy it when the thread exits.
+
+  gthreadLocalLogFunction = logFunction;
+}
+
+void UninstallLogFunction()
+{
+  gthreadLocalLogFunction = NULL;
+}
+
+#ifdef DEBUG_ENABLED
+
+/*Change false to true if trace is needed but don't commit to codeline*/
+Filter* Filter::gRender     = Filter::New(Debug::Concise, false, "LOG_RENDER");
+Filter* Filter::gResource   = Filter::New(Debug::Concise, false, "LOG_RESOURCE");
+Filter* Filter::gGLResource = Filter::New(Debug::Concise, false, "LOG_GL_RESOURCE");
+Filter* Filter::gObject     = NULL;
+Filter* Filter::gImage      = Filter::New(Debug::Concise, false, "LOG_IMAGE");
+Filter* Filter::gModel      = Filter::New(Debug::Concise, false, "LOG_MODEL");
+Filter* Filter::gNode       = NULL;
+Filter* Filter::gElement    = NULL;
+Filter* Filter::gActor      = Filter::New(Debug::Concise, false, "LOG_ACTOR");
+Filter* Filter::gShader     = Filter::New(Debug::Concise, false, "LOG_SHADER");
+
+Filter::FilterList* Filter::GetActiveFilters()
+{
+  static Filter::FilterList* activeFilters = new FilterList;
+  return activeFilters;
+}
+
+Filter* Filter::New( LogLevel level, bool trace, const char * environmentVariableName )
+{
+  char * environmentVariableValue = getenv( environmentVariableName );
+  if ( environmentVariableValue )
+  {
+    unsigned int envLevel(0);
+    char envTraceString(0);
+    sscanf( environmentVariableValue, "%u,%c", &envLevel, &envTraceString );
+
+    if ( envLevel > Verbose )
+    {
+      envLevel = Verbose;
+    }
+    level = LogLevel( envLevel );
+
+    // Just use 'f' and 't' as it's faster than doing full string comparisons
+    if ( envTraceString == 't' )
+    {
+      trace = true;
+    }
+    else if ( envTraceString == 'f' )
+    {
+      trace = false;
+    }
+  }
+
+  Filter* filter = new Filter(level, trace);
+  filter->mNesting++;
+  GetActiveFilters()->push_back(filter);
+  return filter;
+}
+
+/**
+ * Enable trace on all filters.
+ */
+void Filter::EnableGlobalTrace()
+{
+  for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
+  {
+    (*iter)->EnableTrace();
+  }
+}
+
+/**
+ * Disable trace on all filters.
+ */
+void Filter::DisableGlobalTrace()
+{
+  for(FilterIter iter = GetActiveFilters()->begin(); iter != GetActiveFilters()->end(); iter++)
+  {
+    (*iter)->DisableTrace();
+  }
+}
+
+
+void Filter::Log(LogLevel level, const char* format, ...)
+{
+  if(level <= mLoggingLevel)
+  {
+    va_list arg;
+    va_start(arg, format);
+
+    char *buffer = NULL;
+    int numChars = asprintf(&buffer, "%-*c %s", mNesting, ':', format);
+    if(numChars >= 0) // No error
+    {
+      std::string message = ArgListToString(buffer, arg);
+      LogMessage(DebugInfo, message.c_str());
+      free(buffer);
+    }
+    va_end(arg);
+  }
+}
+
+
+TraceObj::TraceObj(Filter* filter, const char*format, ...) : mFilter(filter)
+{
+  if(mFilter && mFilter->IsTraceEnabled())
+  {
+    va_list arg;
+    va_start(arg, format);
+    mMessage = ArgListToString(format, arg);
+    va_end(arg);
+
+    LogMessage(DebugInfo, "Entr%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
+    ++mFilter->mNesting;
+  }
+}
+
+TraceObj::~TraceObj()
+{
+  if(mFilter && mFilter->IsTraceEnabled())
+  {
+    if (mFilter->mNesting)
+    {
+      --mFilter->mNesting;
+    }
+    LogMessage(DebugInfo, "Exit%-*c %s\n", mFilter->mNesting, ':', mMessage.c_str());
+  }
+}
+
+#endif // DEBUG_ENABLED
+
+
+std::string ArgListToString(const char *format, va_list args)
+{
+  std::string str; // empty string
+  if(format != NULL)
+  {
+    char* buffer = NULL;
+    int err = vasprintf(&buffer, format, args);
+    if(err >= 0) // No error
+    {
+      str = buffer;
+      free(buffer);
+    }
+  }
+  return str;
+}
+
+std::string FormatToString(const char *format, ...)
+{
+  va_list arg;
+  va_start(arg, format);
+  std::string s = ArgListToString(format, arg);
+  va_end(arg);
+  return s;
+}
+
+std::string ColorToString(const Vector4& color)
+{
+  std::ostringstream oss;
+  oss << "<R:" << color.r << " G:" << color.g << " B:" << color.b << " A:" << color.a << ">";
+  return oss.str();
+}
+
+std::string Vector4ToString(const Vector4& v, size_t precision, size_t indent)
+{
+  std::ostringstream oss;
+  oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right;
+  oss << "<X:" << std::setw(precision+4) << v.x
+      << " Y:" << std::setw(precision+4) << v.y
+      << " Z:" << std::setw(precision+4) << v.z
+      << " W:" << std::setw(precision+4) << v.w << ">";
+  return oss.str();
+}
+
+std::string Vector3ToString(const Vector3& v, size_t precision, size_t indent)
+{
+  std::ostringstream oss;
+  oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right << std::setiosflags(std::ios_base::fixed);
+  oss << "<X:" << std::setw(precision+4) << v.x
+      << " Y:" << std::setw(precision+4) << v.y
+      << " Z:" << std::setw(precision+4) << v.z << ">";
+  return oss.str();
+}
+
+std::string QuaternionToString(const Quaternion& q, size_t precision, size_t indent)
+{
+  std::ostringstream oss;
+
+  Vector3 axis;
+  Radian angle;
+  q.ToAxisAngle(axis, angle);
+
+  oss << std::setw(indent+3) << std::setfill(' ') << std::setprecision(precision) << std::right;
+  oss << "<A:" << std::setw(precision+4) << Degree( angle ).degree << ", " << Vector3ToString(axis, precision, 0) << ">";
+
+  return oss.str();
+}
+
+std::string Matrix3ToString(const Matrix3& m, size_t precision, size_t indent)
+{
+  return Array2DToString(m.AsFloat(), 3, 3, precision, indent);
+}
+
+std::string MatrixToString(const Matrix& m, size_t precision, size_t indent)
+{
+  return Array2DToString(m.AsFloat(), 4, 4, precision, indent);
+}
+
+} // namespace Log
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/debug.h b/dali/integration-api/debug.h
new file mode 100644 (file)
index 0000000..8b17e38
--- /dev/null
@@ -0,0 +1,489 @@
+#ifndef __DALI_INTEGRATION_DEBUG_H__
+#define __DALI_INTEGRATION_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <sstream>
+#include <list>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+// Using Debug namespace alias shortens the log usage significantly
+namespace Dali{namespace Integration{namespace Log{}}}
+namespace Debug = Dali::Integration::Log;
+
+namespace Dali
+{
+
+struct Vector2;
+struct Vector3;
+struct Vector4;
+class Matrix3;
+class Matrix;
+class Quaternion;
+
+namespace Integration
+{
+namespace Log
+{
+
+enum DebugPriority
+{
+  DebugInfo,
+  DebugWarning,
+  DebugError
+};
+
+/**
+ * Used by logging macros to log a message along with function/class name
+ * @param level debug level
+ * @param format string format
+ */
+DALI_IMPORT_API void LogMessage(enum DebugPriority level,const char *format, ...);
+
+/**
+ * typedef for the logging function.
+ */
+typedef void (*LogFunction)(DebugPriority priority, std::string& message);
+
+/**
+ * A log function has to be installed for every thread that wants to use logging.
+ * This should be done by the adaptor.
+ * The log function can be different for each thread.
+ * @param logFunction the log function to install
+ * @param logOpts the log options to save in thread
+ */
+DALI_IMPORT_API void InstallLogFunction(const LogFunction& logFunction);
+
+/**
+ * A log function has to be uninstalled for every thread that wants to use logging.
+ * The log function can be different for each thread.
+ */
+DALI_IMPORT_API void UninstallLogFunction();
+
+/********************************************************************************
+ *                            Error/Warning  macros.                            *
+ ********************************************************************************/
+
+/**
+ * Provides unfiltered logging for global error level messages
+ */
+#define DALI_LOG_ERROR(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError,   "%s " format, __PRETTY_FUNCTION__, ## args)
+
+#define DALI_LOG_ERROR_NOFN(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, format, ## args)
+
+/**
+ * Provides unfiltered logging for fps monitor
+ */
+#define DALI_LOG_FPS(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
+
+/**
+ * Provides unfiltered logging for update status
+ */
+#define DALI_LOG_UPDATE_STATUS(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
+
+/**
+ * Provides unfiltered logging for render information
+ */
+#define DALI_LOG_RENDER_INFO(format, args...)     Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugInfo, format, ## args)
+
+#ifdef DEBUG_ENABLED
+
+/**
+ * Provides unfiltered logging for global warning level messages
+ */
+#define DALI_LOG_WARNING(format, args...)   Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugWarning, "%s " format, __PRETTY_FUNCTION__, ## args)
+
+
+#else // DEBUG_ENABLED
+
+// Don't warn on release build
+#define DALI_LOG_WARNING(format, args...)
+
+#endif
+
+/********************************************************************************
+ *                                    Filter                                    *
+ ********************************************************************************/
+
+#ifdef DEBUG_ENABLED
+
+/**
+ * Enumeration of logging levels.
+ * Used by the filters to provide multiple log levels.
+ * In general, the higher the value, the more debug is available for that filter.
+ */
+enum LogLevel
+{
+  NoLogging   = 0,
+  Concise     = 1,
+  General     = 2,
+  Verbose     = 3
+};
+
+
+/**
+ * The Filter object is used by the DALI_LOG_INFO macro and others to determine if the logging
+ * should take place, and routes the logging via the platform abstraction's LogMessage.
+ *
+ * It provides a logging level. If this is set to zero, then DALI_LOG_INFO won't log anything.
+ * It provides the ability to turn tracing on or off.
+ *
+ */
+class DALI_IMPORT_API Filter
+{
+public:
+  typedef std::list<Filter*>           FilterList;
+  typedef std::list<Filter*>::iterator FilterIter;
+
+public:
+
+  /**
+   * Test if the filter is enabled for the given logging level
+   * @param[in] level - the level to test.
+   * @return true if this level of logging is enabled.
+   */
+  bool IsEnabledFor(LogLevel level) { return level != Debug::NoLogging && level <= mLoggingLevel;}
+
+  /**
+   * Test if trace is enabled for this filter.
+   * @return true if trace is enabled;
+   */
+  bool IsTraceEnabled() { return mTraceEnabled; }
+
+  /**
+   * Enable tracing on this filter.
+   */
+  void EnableTrace() { mTraceEnabled = true; }
+
+  /**
+   * Disable tracing on this filter.
+   */
+  void DisableTrace() { mTraceEnabled = false; }
+
+  /**
+   * Set the log level for this filter. Setting to a higher value than Debug::General also
+   * enables General;
+   */
+  void SetLogLevel(LogLevel level) { mLoggingLevel = level; }
+
+  /**
+   * Perform the logging for this filter.
+   */
+  void Log(LogLevel level, const char* format, ...);
+
+  /**
+   * Create a new filter whose debug level and trace can be modified through the use of an
+   * environment variable.
+   *
+   * @param[in] level The default log level
+   * @param[in] trace The default trace level. If true, function tracing is on.
+   * @param[in] environmentVariableName The environment variable name used in order to change the
+   *                                    log level or trace.
+   *
+   * @info To modify logg level/trace at runtime, you can should define your filter as shown below:
+   *
+   * @code
+   * Debug::Filter* filter = Debug::Filter::New( Debug::NoLogging, false, "FILTER_ENV" );
+   * @endcode
+   *
+   * And to use it when running an executable:
+   * @code
+   * FILTER_ENV=3 dali-demo        // LogLevel Verbose,   Trace using default
+   * FILTER_ENV=1,true dali-demo   // LogLevel Concise,   Trace ON
+   * FILTER_ENV=2,false dali-demo  // LogLevel General,   Trace OFF
+   * FILTER_ENV=0,true dali-demo   // LogLevel NoLogging, Trace ON
+   * @endcode
+   */
+  static Filter* New(LogLevel level, bool trace, const char * environmentVariableName );
+
+  /**
+   * Enable trace on all filters.
+   */
+  void EnableGlobalTrace();
+
+  /**
+   * Disable trace on all filters.
+   */
+  void DisableGlobalTrace();
+
+private:
+
+  /**
+   * Constructor.
+   * @param[in] level - the highest log level.
+   * @param[in] trace - whether this filter allows tracing.
+   */
+  Filter(LogLevel level, bool trace) : mLoggingLevel(level), mTraceEnabled(trace), mNesting(0) {}
+
+  static FilterList* GetActiveFilters();
+
+public:
+  // High level filters. If these filters are too broad for your current requirement, then
+  // you can add a filter to your own class or source file. If you do, use Filter::New()
+  // to tell this class about it.
+
+  static Filter *gRender;
+  static Filter *gResource;
+  static Filter *gGLResource;
+  static Filter *gObject;
+  static Filter *gImage;
+  static Filter *gModel;
+  static Filter *gNode;
+  static Filter *gElement;
+  static Filter *gActor;
+  static Filter *gShader;
+
+private:
+  LogLevel mLoggingLevel;
+  bool     mTraceEnabled;
+public:
+  int      mNesting;
+
+};
+
+
+#define  DALI_LOG_FILTER_SET_LEVEL(filter, level) filter->SetLogLevel(level)
+#define  DALI_LOG_FILTER_ENABLE_TRACE(filter)     filter->EnableTrace()
+#define  DALI_LOG_FILTER_DISABLE_TRACE(filter)    filter->DisableTrace()
+
+#else
+
+#define  DALI_LOG_FILTER_SET_LEVEL(filter, level)
+#define  DALI_LOG_FILTER_ENABLE_TRACE(filter)
+#define  DALI_LOG_FILTER_DISABLE_TRACE(filter)
+
+#endif
+
+/********************************************************************************
+ *                            General Logging macros                            *
+ ********************************************************************************/
+
+#ifdef DEBUG_ENABLED
+
+#define DALI_LOG_INFO(filter, level, format, args...)                        \
+  if(filter && filter->IsEnabledFor(level)) { filter->Log(level, format,  ## args); }
+
+#else // DEBUG_ENABLED
+
+#define DALI_LOG_INFO(filter, level, format, args...)
+
+#endif // DEBUG_ENABLED
+
+
+/********************************************************************************
+ *                                  Trace Macros                                *
+ ********************************************************************************/
+
+/*
+ * These macros allow the instrumentation of methods. These translate into calls
+ * to LogMessage(DebugInfo).
+ */
+
+#ifdef DEBUG_ENABLED
+
+class DALI_IMPORT_API TraceObj
+{
+public:
+  TraceObj(Filter* filter, const char* fmt, ...);
+  ~TraceObj();
+
+public:
+  std::string mMessage;
+  Filter* mFilter;
+};
+
+
+#define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...)                 \
+  Dali::Integration::Log::TraceObj debugTraceObj(filter, "%s: " format, __PRETTY_FUNCTION__, ## args)
+
+#define DALI_LOG_TRACE_METHOD(filter)                                      \
+  Dali::Integration::Log::TraceObj debugTraceObj(filter, __PRETTY_FUNCTION__)
+
+
+#else // DEBUG_ENABLED
+
+#define DALI_LOG_TRACE_METHOD_FMT(filter, format, args...)
+#define DALI_LOG_TRACE_METHOD(filter)
+
+
+#endif
+
+/********************************************************************************
+ *                              Extra object debug                              *
+ ********************************************************************************/
+
+#ifdef DEBUG_ENABLED
+
+/**
+ * Warning, this macro changes the current scope, so should usually be put at the
+ * end of the class definition.
+ *
+ * Suggest that the value is usually set to the object's name.
+ * Warning - this will increase the size of the object for a debug build.
+ */
+#define DALI_LOG_OBJECT_STRING_DECLARATION \
+public: \
+  std::string mDebugString;
+
+/**
+ * Print all the actor tree names
+ **/
+#define DALI_LOG_ACTOR_TREE( node ) { \
+  std::stringstream branch; \
+  Node* tempNode = node; \
+  while( tempNode ) { \
+    branch << "<" << tempNode->mDebugString << ">::"; \
+    tempNode = tempNode->GetParent(); \
+  } \
+  DALI_LOG_ERROR_NOFN("Actor tree: %s\n", branch.str().c_str()); \
+}
+
+/**
+ * Allows one object to set another object's debug string
+ */
+#define DALI_LOG_SET_OBJECT_STRING(object, string) (object->mDebugString = string)
+
+/**
+ * Allows one object to set another object's std::string easily
+ */
+#define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...) (object->mDebugString = FormatToString(fmt, ## args))
+
+/**
+ * Allows one object to get another object's debug string
+ */
+#define DALI_LOG_GET_OBJECT_STRING(object) (object->mDebugString)
+
+/**
+ * Get the C string (for use in formatted logging)
+ */
+#define DALI_LOG_GET_OBJECT_C_STR(object) (object->mDebugString.c_str())
+
+/**
+ * Filtered logging of the object's debug string
+ */
+#define DALI_LOG_OBJECT(filter, object)  DALI_LOG_INFO(filter, Debug::General, object->mDebugString)
+
+
+#else // DEBUG_ENABLED
+
+#define DALI_LOG_OBJECT_STRING_DECLARATION
+#define DALI_LOG_ACTOR_TREE(node)
+#define DALI_LOG_SET_OBJECT_STRING(object, string)
+#define DALI_LOG_FMT_OBJECT_STRING(object, fmt, args...)
+#define DALI_LOG_GET_OBJECT_STRING(object)
+#define DALI_LOG_GET_OBJECT_C_STR(object) ""
+#define DALI_LOG_OBJECT(filter, object)
+
+#endif
+
+/********************************************************************************
+ *                                Helper writers                                *
+ ********************************************************************************/
+
+/**
+ * Helper method to translate a color to a string.
+ * @param[in] color - the color to translate
+ * @return string - the text representation of the color.
+ */
+DALI_IMPORT_API std::string ColorToString(const Vector4& color);
+
+/**
+ * Helper method to translate a vector4 to a string.
+ * @param[in] v - the vector
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the vector.
+ */
+DALI_IMPORT_API std::string Vector4ToString(const Vector4& v, size_t precision=3, size_t indent=0);
+
+/**
+ * Helper method to translate a vector4 to a string.
+ * @param[in] v - the vector
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the vector.
+ */
+DALI_IMPORT_API std::string Vector3ToString(const Vector3& v, size_t precision=3, size_t indent=0);
+
+/**
+ * Helper method to translate a quaternion to a string.
+ * @param[in] q the quaternion
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the quaternion.
+ */
+DALI_IMPORT_API std::string QuaternionToString(const Quaternion& q, size_t precision=3, size_t indent=0);
+
+/**
+ * Helper method to translate a 3x3 matrix to a string.
+ * @param[in] m - the matrix
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the vector.
+ */
+DALI_IMPORT_API std::string Matrix3ToString(const Matrix3& m, size_t precision=3, size_t indent=0);
+
+/**
+ * Helper method to translate a 4x4 matrix to a string.
+ * @param[in] m - the matrix
+ * @param[in] precision - the precision to write the float data.
+ * @param[in] indent - the indent level to use.
+ * @return string - the text representation of the vector.
+ */
+DALI_IMPORT_API std::string MatrixToString(const Matrix& m, size_t precision=3, size_t indent=0);
+
+#ifdef DEBUG_ENABLED
+
+
+/**
+ * Filtered write of a matrix
+ */
+#define DALI_LOG_MATRIX(filter, matrix)  DALI_LOG_INFO(filter, Debug::General, MatrixToString(matrix))
+
+/**
+ * Filtered write of a vector
+ */
+#define DALI_LOG_VECTOR4(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector4ToString(vector))
+
+/**
+ * Filtered write of a vector
+ */
+#define DALI_LOG_VECTOR3(filter, vector) DALI_LOG_INFO(filter, Debug::General, Vector3ToString(vector))
+
+/**
+ * Filtered write of a color
+ */
+#define DALI_LOG_COLOR(filter, color)    DALI_LOG_INFO(filter, Debug::General, ColorToString(color))
+
+#else
+
+#define DALI_LOG_MATRIX(filter, matrix)
+#define DALI_LOG_VECTOR4(filter,vector)
+#define DALI_LOG_VECTOR3(filter,vector)
+#define DALI_LOG_COLOR(filter, color)
+
+#endif
+
+}}} // Dali/Integration/Debug namespaces
+
+
+#endif // __DALI_INTEGRATION_DEBUG_H__
diff --git a/dali/integration-api/events/event.cpp b/dali/integration-api/events/event.cpp
new file mode 100644 (file)
index 0000000..381de18
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/event.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+Event::~Event()
+{
+}
+
+Event::Event(Type eventType)
+: type(eventType)
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/event.h b/dali/integration-api/events/event.h
new file mode 100644 (file)
index 0000000..66bd92d
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef __DALI_INTEGRATION_EVENT_H__
+#define __DALI_INTEGRATION_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * Base structure for events passed to Dali::Integration::Core::QueueEvent()
+ * An instance of this class cannot be created.
+ */
+struct Event
+{
+  // Destruction
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Event();
+
+  // Enumerations
+
+  enum Type
+  {
+    Touch,         ///< A touch event, when the user interacts with the screen.
+    Key,           ///< A key pressed event, from the virtual or external keyboard.
+    Gesture,       ///< A Gesture event has been detected.
+    Wheel,         ///< A wheel event, when the wheel is being rolled from an external mouse.
+    Hover          ///< A hover event, when the user hovers above the screen.
+  };
+
+  // Data
+
+  /**
+   * The event type.
+   */
+  Type type;
+
+protected: // Constructors only to be used by derived structures.
+
+  /**
+   * This constructor is only used by derived classes.
+   * @param[in] eventType The type of event.
+   */
+  Event(Type eventType);
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_EVENT_H__
diff --git a/dali/integration-api/events/gesture-event.cpp b/dali/integration-api/events/gesture-event.cpp
new file mode 100644 (file)
index 0000000..e3c2c50
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/gesture-event.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+GestureEvent::~GestureEvent()
+{
+}
+
+GestureEvent::GestureEvent(Gesture::Type gesture, Gesture::State gestureState)
+: Event(Gesture),
+  gestureType(gesture),
+  state(gestureState),
+  time(0)
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/gesture-event.h b/dali/integration-api/events/gesture-event.h
new file mode 100644 (file)
index 0000000..8924474
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __DALI_INTEGRATION_GESTURE_EVENT_H__
+#define __DALI_INTEGRATION_GESTURE_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/integration-api/events/event.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * This is the abstract base structure for any gestures that the adaptor detects and wishes to send
+ * to the Core.
+ */
+struct GestureEvent : public Event
+{
+  // Destruction
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~GestureEvent();
+
+  // Data
+
+  /**
+   * Gesture Type.
+   */
+  Gesture::Type gestureType;
+
+  /**
+   * The state of the gesture.
+   */
+  Gesture::State state;
+
+  /**
+   * The time the gesture took place.
+   */
+  unsigned int time;
+
+protected:  // Constructors only to be used by derived structures.
+
+  /**
+   * This constructor is only used by derived classes.
+   * @param[in] gesture       The type of gesture event.
+   * @param[in] gestureState  The state of the gesture event.
+   */
+  GestureEvent(Gesture::Type gesture, Gesture::State gestureState);
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_GESTURE_EVENT_H__
diff --git a/dali/integration-api/events/gesture-requests.h b/dali/integration-api/events/gesture-requests.h
new file mode 100644 (file)
index 0000000..21b4490
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef __DALI_INTEGRATION_GESTURE_REQUESTS_H__
+#define __DALI_INTEGRATION_GESTURE_REQUESTS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * This structure specifies the gesture type required (or no longer required) by Core.
+ */
+struct GestureRequest
+{
+  // Creation & Destruction
+
+  /**
+   * Default Constructor
+   * @param[in]  typeRequired  The gesture type required
+   */
+  GestureRequest(Gesture::Type typeRequired) : type(typeRequired)
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~GestureRequest()
+  {
+  }
+
+  // Data Members
+
+  Gesture::Type type; ///< The type of gesture required.
+};
+
+/**
+ * This is used by Core when a pan gesture is required.
+ */
+struct PanGestureRequest : public GestureRequest
+{
+  // Creation & Destruction
+
+  /**
+   * Default Constructor
+   */
+  PanGestureRequest()
+  : GestureRequest(Gesture::Pan),
+    minTouches(1),
+    maxTouches(1)
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PanGestureRequest()
+  {
+  }
+
+  // Data Members
+
+  unsigned int minTouches; ///< The minimum number of touch points required for a pan gesture.
+  unsigned int maxTouches; ///< The maximum number of touch points required for a pan gesture.
+};
+
+/**
+ * This is used by Core when a pinch gesture is required.
+ */
+struct PinchGestureRequest : public GestureRequest
+{
+  // Creation & Destruction
+
+  /**
+   * Default Constructor
+   */
+  PinchGestureRequest()
+  : GestureRequest(Gesture::Pinch)
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PinchGestureRequest()
+  {
+  }
+};
+
+/**
+ * This is used by Core when a tap gesture is required.
+ */
+struct TapGestureRequest : public GestureRequest
+{
+  // Creation & Destruction
+
+  /**
+   * Default Constructor
+   */
+  TapGestureRequest()
+  : GestureRequest(Gesture::Tap),
+    minTaps(1),
+    maxTaps(1),
+    minTouches(1),
+    maxTouches(1)
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~TapGestureRequest()
+  {
+  }
+
+  // Data Members
+
+  unsigned int minTaps;    ///< The minimum number of taps required.
+  unsigned int maxTaps;    ///< The maximum number of taps required.
+  unsigned int minTouches; ///< The minimum number of touch points required for our tap gesture.
+  unsigned int maxTouches; ///< The maximum number of touch points required for our tap gesture.
+};
+
+/**
+ * This is used by Core when a long press gesture is required.
+ */
+struct LongPressGestureRequest : public GestureRequest
+{
+  // Creation & Destruction
+
+  /**
+   * Default Constructor
+   */
+  LongPressGestureRequest()
+  : GestureRequest(Gesture::LongPress),
+    minTouches(1),
+    maxTouches(1)
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~LongPressGestureRequest()
+  {
+  }
+
+  // Data Members
+
+  unsigned int minTouches; ///< The minimum number of touch points required for a long press gesture.
+  unsigned int maxTouches; ///< The maximum number of touch points required for a long press gesture.
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_GESTURE_REQUESTS_H__
diff --git a/dali/integration-api/events/hover-event-integ.cpp b/dali/integration-api/events/hover-event-integ.cpp
new file mode 100644 (file)
index 0000000..4b846a8
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/hover-event-integ.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+HoverEvent::HoverEvent()
+: MultiPointEvent( Hover )
+{
+}
+
+HoverEvent::HoverEvent( unsigned long time )
+: MultiPointEvent( Hover, time )
+{
+}
+
+HoverEvent::~HoverEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/hover-event-integ.h b/dali/integration-api/events/hover-event-integ.h
new file mode 100644 (file)
index 0000000..7d7bffd
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __DALI_INTEGRATION_HOVER_EVENT_H__
+#define __DALI_INTEGRATION_HOVER_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/hover-event.h>
+#include <dali/integration-api/events/multi-point-event-integ.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this structure should be used by the adaptor to send a hover event to Dali core.
+ *
+ * This class can contain one or many touch points. It also contains the time at which the
+ * event occurred.
+ */
+struct HoverEvent : public MultiPointEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   */
+  HoverEvent();
+
+  /**
+   * Constructor
+   * @param[in]  time  The time the event occurred.
+   */
+  HoverEvent(unsigned long time);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~HoverEvent();
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_HOVER_EVENT_H__
diff --git a/dali/integration-api/events/key-event-integ.cpp b/dali/integration-api/events/key-event-integ.cpp
new file mode 100644 (file)
index 0000000..80dc7cc
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/key-event-integ.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+KeyEvent::KeyEvent()
+: Event(Key),
+  keyName(),
+  keyString(),
+  keyCode(-1),
+  keyModifier(0),
+  time(0),
+  state(KeyEvent::Down)
+{
+}
+
+KeyEvent::KeyEvent(const std::string& keyName, const std::string& keyString, int keyCode, int keyModifier, unsigned long timeStamp, const State& keyState)
+: Event(Key),
+  keyName(keyName),
+  keyString(keyString),
+  keyCode(keyCode),
+  keyModifier(keyModifier),
+  time(timeStamp),
+  state(keyState)
+{
+}
+
+KeyEvent::~KeyEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/key-event-integ.h b/dali/integration-api/events/key-event-integ.h
new file mode 100644 (file)
index 0000000..26762ed
--- /dev/null
@@ -0,0 +1,115 @@
+#ifndef __DALI_INTEGRATION_KEY_EVENT_H__
+#define __DALI_INTEGRATION_KEY_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/event.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this class should be used by the adaptor to send a key event to
+ * the Dali core.
+ *
+ */
+struct KeyEvent : public Event
+{
+  // Enumerations
+  // Specifies the state of the key event.
+  enum State
+  {
+    Down,        /**< Key down */
+    Up,          /**< Key up */
+
+    Last
+  };
+
+  /**
+   * Default Constructor
+   */
+  KeyEvent();
+
+  /**
+   * Constructor
+   * @param[in]  keyName       The name of the key pressed or command from the IMF, if later then the some following parameters will be needed.
+   * @param[in]  keyString     A string of input characters or key pressed
+   * @param[in]  keyCode       The unique key code for the key pressed.
+   * @param[in]  keyModifier   The key modifier for special keys like shift and alt
+   * @param[in]  timeStamp The time (in ms) that the key event occurred.
+   * @param[in]  keyState The state of the key event.
+   */
+  KeyEvent(const std::string& keyName,
+           const std::string& keyString,
+           int keyCode,
+           int keyModifier,
+           unsigned long timeStamp,
+           const State& keyState);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~KeyEvent();
+
+  // Data
+
+  /**
+   *@copydoc Dali::KeyEvent::keyPressedName
+   */
+  std::string keyName;
+
+  /**
+   *@copydoc Dali::KeyEvent::keyPressed
+   */
+  std::string keyString;
+
+  /**
+   * @copydoc Dali::KeyEvent::keyCode
+   */
+  int  keyCode;
+
+  /**
+   *@copydoc Dali::KeyEvent::keyModifier
+   */
+  int  keyModifier;
+
+  /**
+   *@copydoc Dali::KeyEvent::time
+   */
+  unsigned long time;
+
+  /**
+   * State of the key event.
+   * @see State
+   */
+  State state;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_KEY_EVENT_H__
diff --git a/dali/integration-api/events/long-press-gesture-event.cpp b/dali/integration-api/events/long-press-gesture-event.cpp
new file mode 100644 (file)
index 0000000..878276b
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "long-press-gesture-event.h"
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+LongPressGestureEvent::LongPressGestureEvent( Gesture::State state )
+: GestureEvent( Gesture::LongPress, state ),
+  numberOfTouches(1)
+{
+}
+
+LongPressGestureEvent::~LongPressGestureEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/long-press-gesture-event.h b/dali/integration-api/events/long-press-gesture-event.h
new file mode 100644 (file)
index 0000000..828896f
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__
+#define __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * If the adaptor detects a long press gesture, then it should create an instance of this structure and
+ * send it to the Core.
+ *
+ * This gesture can be in four states:
+ * - Possible:  When the user first puts their finger down - Core needs to hit test the down point.
+ * - Started:   When the long-press gesture is actually detected.
+ * - Finished:  When the user finally lifts all touches.
+ * - Cancelled: If, after a down event, no long press is detected, or a system interruption.
+ */
+struct LongPressGestureEvent : public GestureEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   * @param[in]  state  Started, when we detect a long press.
+   *                    Finished, when all touches are finished.
+   */
+  LongPressGestureEvent( Gesture::State state );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~LongPressGestureEvent();
+
+  // Data
+
+  /**
+   * @copydoc Dali::LongPressGesture::numberOfTouches
+   */
+  unsigned int numberOfTouches;
+
+  /**
+   * This is the point, in screen coordinates, where the long press occurred.
+   * If a multi-touch tap, then this should be the centroid of all the touch points.
+   */
+  Vector2 point;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_LONG_PRESS_GESTURE_H__
diff --git a/dali/integration-api/events/multi-point-event-integ.cpp b/dali/integration-api/events/multi-point-event-integ.cpp
new file mode 100644 (file)
index 0000000..9320a45
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/multi-point-event-integ.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+MultiPointEvent::MultiPointEvent( Type eventType )
+: Event( eventType ),
+  time( 0 )
+{
+}
+
+MultiPointEvent::MultiPointEvent( Type eventType, unsigned long time )
+: Event( eventType ),
+  time( time )
+{
+}
+
+MultiPointEvent::~MultiPointEvent()
+{
+}
+
+void MultiPointEvent::AddPoint(const TouchPoint& point)
+{
+  points.push_back(point);
+}
+
+TouchPoint& MultiPointEvent::GetPoint(unsigned int point)
+{
+  DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds");
+  return points[point];
+}
+
+const TouchPoint& MultiPointEvent::GetPoint(unsigned int point) const
+{
+  DALI_ASSERT_ALWAYS(point < points.size() && "MultiPointEvent: Point index out of bounds");
+  return points[point];
+}
+
+unsigned int MultiPointEvent::GetPointCount() const
+{
+  return points.size();
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/multi-point-event-integ.h b/dali/integration-api/events/multi-point-event-integ.h
new file mode 100644 (file)
index 0000000..b5dd601
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
+#define __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/integration-api/events/event.h>
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this structure should be used by the adaptor to send a multi-point event to Dali core.
+ *
+ * This class can contain one or multiple touch points. It also contains the time at which the
+ * event occurred.
+ */
+struct MultiPointEvent : public Event
+{
+  // Construction & Destruction
+
+public:
+  /**
+   * Virtual destructor
+   */
+  virtual ~MultiPointEvent();
+
+protected:
+  /**
+   * Default Constructor
+   */
+  MultiPointEvent(Type eventType);
+
+  /**
+   * Constructor
+   * @param[in]  time  The time the event occurred.
+   */
+  MultiPointEvent(Type eventType, unsigned long time);
+
+public:
+  // Data
+
+  /**
+   * @copydoc Dali::MultiPointEvent::points
+   */
+  std::vector<TouchPoint> points;
+
+  /**
+   * @copydoc Dali::MultiPointEvent::time
+   */
+  unsigned long time;
+
+  // Convenience Methods
+
+  /**
+   * Adds a point to the MultiPointEvent.
+   * @param[in]  point  The point to add.
+   */
+  void AddPoint(const TouchPoint& point);
+
+  /**
+   * @copydoc Dali::MultiPointEvent::GetPoint()
+   */
+  TouchPoint& GetPoint(unsigned int point);
+
+  /**
+   * @copydoc Dali::MultiPointEvent::GetPoint()
+   */
+  const TouchPoint& GetPoint(unsigned int point) const;
+
+  /**
+   * @copydoc Dali::MultiPointEvent::GetPointCount() const
+   */
+  unsigned int GetPointCount() const;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_MULTI_POINT_EVENT_H__
diff --git a/dali/integration-api/events/pan-gesture-event.cpp b/dali/integration-api/events/pan-gesture-event.cpp
new file mode 100644 (file)
index 0000000..712a448
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/pan-gesture-event.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+
+PanGestureEvent::PanGestureEvent(Gesture::State state)
+: GestureEvent(Gesture::Pan, state),
+  timeDelta(0),
+  numberOfTouches(1)
+{
+}
+
+PanGestureEvent::~PanGestureEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/pan-gesture-event.h b/dali/integration-api/events/pan-gesture-event.h
new file mode 100644 (file)
index 0000000..401cf43
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__
+#define __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * If the adaptor detects a pan gesture, then it should create an instance of this structure and
+ * send it to the Core.
+ *
+ * A Pan Gesture event should be in one of five states:
+ * - Possible:   When the user first puts their finger down - Core needs to hit test the down point.
+ * - Started:    If a pan is detected.
+ * - Continuing: If after a pan is detected, it continues.
+ * - Finished:   If after a pan, the user lifts their finger(s).
+ * - Cancelled:  If, after a down event, no pan is detected or a system interruption.
+ *
+ * A Started state will be ignored if a Possible state does not precede it.
+ * Likewise, a Continuing or Finished state will be ignored if a Started state does not precede it.
+ */
+struct PanGestureEvent: public GestureEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   * @param[in]  state  The state of the gesture
+   */
+  PanGestureEvent(Gesture::State state);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PanGestureEvent();
+
+  // Data
+
+  /**
+   * The previous touch position of the primary touch point in screen coordinates.
+   */
+  Vector2 previousPosition;
+
+  /**
+   * This current touch position of the primary touch point in screen coordinates.
+   */
+  Vector2 currentPosition;
+
+  /**
+   * The time difference between the previous and latest touch motion events (in ms).
+   */
+  unsigned long timeDelta;
+
+  /**
+   * The total number of fingers touching the screen in a pan gesture.
+   */
+  unsigned int numberOfTouches;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_PAN_GESTURE_EVENT_H__
diff --git a/dali/integration-api/events/pinch-gesture-event.cpp b/dali/integration-api/events/pinch-gesture-event.cpp
new file mode 100644 (file)
index 0000000..6129d41
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/pinch-gesture-event.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+PinchGestureEvent::PinchGestureEvent(Gesture::State state)
+: GestureEvent(Gesture::Pinch, state),
+  scale(0.0f),
+  speed(0.0f),
+  centerPoint()
+{
+}
+
+PinchGestureEvent::~PinchGestureEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/pinch-gesture-event.h b/dali/integration-api/events/pinch-gesture-event.h
new file mode 100644 (file)
index 0000000..e05cd01
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__
+#define __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * If the adaptor detects a pinch gesture, then it should create an instance of this structure and
+ * send it to the Core.
+ *
+ * A Pinch Gesture event should be in one of four states:
+ * - Started:    If a pinch is detected.
+ * - Continuing: If after a pinch is detected, it continues.
+ * - Finished:   If after a pinch, the user lifts their finger(s).
+ * - Cancelled:  If there is a system interruption.
+ */
+struct PinchGestureEvent : public GestureEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   * @param[in]  state  The state of the gesture
+   */
+  PinchGestureEvent(Gesture::State state);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PinchGestureEvent();
+
+  // Data
+
+  /**
+   * @copydoc Dali::PinchGesture::scale
+   */
+  float scale;
+
+  /**
+   * @copydoc Dali::PinchGesture::speed
+   */
+  float speed;
+
+  /**
+   * The center point between the two touch points of the last touch event in the series of touch motion
+   * event producing this gesture.
+   */
+  Vector2 centerPoint;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_PINCH_GESTURE_EVENT_H__
diff --git a/dali/integration-api/events/tap-gesture-event.cpp b/dali/integration-api/events/tap-gesture-event.cpp
new file mode 100644 (file)
index 0000000..09a1caa
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/tap-gesture-event.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+TapGestureEvent::TapGestureEvent( Gesture::State state )
+: GestureEvent(Gesture::Tap, state),
+  numberOfTaps(1),
+  numberOfTouches(1)
+{
+}
+
+TapGestureEvent::~TapGestureEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/tap-gesture-event.h b/dali/integration-api/events/tap-gesture-event.h
new file mode 100644 (file)
index 0000000..b70fc94
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __DALI_INTEGRATION_TAP_GESTURE_H__
+#define __DALI_INTEGRATION_TAP_GESTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * If the adaptor detects a tap gesture, then it should create an instance of this structure and
+ * send it to the Core.
+ *
+ * A Tap Gesture event should be in one of three states:
+ * - Possible:  When the user first puts their finger down - Core needs to hit test the down point so
+ *              that a tap (down and up quickly) is also on the same actor.
+ * - Started:   If a tap is detected (No Finished state is expected).
+ * - Cancelled: If, after a down event, no tap is detected, or a system interruption.
+ *
+ * A Started state will be ignored if a Possible state does not precede it.
+ */
+struct TapGestureEvent : public GestureEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   * @param[in]  state  Possible, denotes down press;
+   *                    Started, of a tap occurs; and
+   *                    Cancelled, when tap does not occur.
+   */
+  TapGestureEvent( Gesture::State state );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~TapGestureEvent();
+
+  // Data
+
+  /**
+   * @copydoc Dali::TapGesture::numberOfTaps
+   */
+  unsigned int numberOfTaps;
+
+  /**
+   * @copydoc Dali::TapGesture::numberOfTouches
+   */
+  unsigned int numberOfTouches;
+
+  /**
+   * This is the point, in screen coordinates, where the tap occurred.
+   * If a multi-touch tap, then this should be the centroid of all the touch points.
+   */
+  Vector2 point;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_TAP_GESTURE_H__
diff --git a/dali/integration-api/events/touch-data.h b/dali/integration-api/events/touch-data.h
new file mode 100644 (file)
index 0000000..c19dc34
--- /dev/null
@@ -0,0 +1,105 @@
+#ifndef __DALI_INTEGRATION_TOUCH_DATA_H__
+#define __DALI_INTEGRATION_TOUCH_DATA_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+struct TouchData;
+
+typedef std::vector<TouchData> TouchDataContainer;
+typedef TouchDataContainer::iterator TouchDataIter;
+
+/**
+ * TouchData structure
+ * represents the raw touch information from touch-screen for
+ * a single touch event e.g.
+ *
+ * "First finger touching down at pixel 123,456 on the screen (relative
+ * to top left corner of phone in portrait mode). at timestamp 125ms (from a reference
+ * timestamp e.g. phone boot being 0secs)."
+ * TouchData(Down, 125, 0, 123, 456)
+ *
+ * "Above finger moving to pixel 133,457, at timestamp 150ms"
+ * TouchData(Motion, 150, 0, 133, 457)
+ *
+ * "Additional finger touching down at pixel 50, 75, at timestamp 175ms"
+ * TouchData(Down, 175, 1, 50, 75)
+ *
+ * "First finger removing at pixel 143, 458, at timestamp 200ms"
+ * TouchData(Up, 200, 0, 143, 458)
+ *
+ * "Additional finger removing at pixel 51, 77, at timestamp 225ms"
+ * TouchData(Up, 225, 1, 51, 77)
+ *
+ * Note: Multiple incidents of touch data can be present at the same timestamp.
+ */
+struct TouchData
+{
+
+  /**
+   * The Touch Type for this data.
+   */
+  enum TouchType
+  {
+    Down,     // Touch started
+    Up,       // Touch ended
+    Motion    // Touch is continuing
+  };
+
+  TouchData()
+  : type(Motion),
+    timestamp(0u),
+    index(0u),
+    x(0),
+    y(0)
+  {
+
+  }
+
+  TouchData(TouchType type,
+            unsigned int timestamp,
+            unsigned int index,
+            int x,
+            int y)
+  : type(type),
+    timestamp(timestamp),
+    index(index),
+    x(x),
+    y(y)
+  {
+  }
+
+  TouchType type;
+  unsigned int timestamp;
+  unsigned int index;
+  int x;
+  int y;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_TOUCH_DATA_H__
diff --git a/dali/integration-api/events/touch-event-combiner.cpp b/dali/integration-api/events/touch-event-combiner.cpp
new file mode 100644 (file)
index 0000000..b864e43
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/touch-event-combiner.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+namespace
+{
+const unsigned long DEFAULT_MINIMUM_MOTION_TIME( 1u );
+const Vector2 DEFAULT_MINIMUM_MOTION_DISTANCE( 1.0f, 1.0f );
+} // unnamed namespace
+
+struct TouchEventCombiner::PointInfo
+{
+  // Construction
+
+  /**
+   * Constructor
+   * @param[in]  touchPoint  The point to add.
+   * @param[in]  pointTime   The time of the point event.
+   */
+  PointInfo( const TouchPoint& touchPoint, unsigned long pointTime )
+  : point( touchPoint ),
+    time( pointTime )
+  {
+  }
+
+  // Data
+
+  TouchPoint point;   ///< The point.
+  unsigned long time; ///< The time the point event took place.
+};
+
+TouchEventCombiner::TouchEventCombiner()
+: mMinMotionTime( DEFAULT_MINIMUM_MOTION_TIME ),
+  mMinMotionDistance( DEFAULT_MINIMUM_MOTION_DISTANCE )
+{
+}
+
+TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance )
+: mMinMotionTime( minMotionTime ),
+  mMinMotionDistance( minMotionXDistance, minMotionYDistance )
+{
+  DALI_ASSERT_ALWAYS( minMotionXDistance >= 0.0f && minMotionYDistance >= 0.0f && "Negative values not allowed\n" );
+}
+
+TouchEventCombiner::TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance )
+: mMinMotionTime( minMotionTime ),
+  mMinMotionDistance( minMotionDistance )
+{
+  DALI_ASSERT_ALWAYS( minMotionDistance.x >= 0.0f && minMotionDistance.y >= 0.0f && "Negative values not allowed\n" );
+}
+
+TouchEventCombiner::~TouchEventCombiner()
+{
+}
+
+TouchEventCombiner::EventDispatchType TouchEventCombiner::GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent )
+{
+  TouchEventCombiner::EventDispatchType dispatchEvent( TouchEventCombiner::DispatchNone );
+
+  switch ( point.state )
+  {
+    case TouchPoint::Started:
+    {
+      touchEvent.time = time;
+      bool addToContainer( true );
+
+      // Iterate through already stored touch points and add to TouchEvent
+      for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
+      {
+        if ( iter->point.deviceId != point.deviceId )
+        {
+          iter->point.state = TouchPoint::Stationary;
+        }
+        else
+        {
+          // System has sent us two down points for the same point ID, update our stored data to latest.
+          // We do not want to emit another down event for this Point Device ID.
+
+          addToContainer = false;
+          iter->point = point;
+          iter->time = time;
+        }
+        touchEvent.AddPoint( iter->point );
+      }
+
+      // Add new touch point to the list and to the TouchEvent
+      if (addToContainer)
+      {
+        mPressedPoints.push_back( PointInfo( point, time ) );
+        touchEvent.AddPoint( point );
+        dispatchEvent = TouchEventCombiner::DispatchTouch; // Only dispatch touch event if just added to container
+
+        // Check whether hover event was dispatched previously
+        if ( !mHoveredPoints.empty() )
+        {
+          hoverEvent.time = time;
+
+          PointInfoContainer::iterator match( mHoveredPoints.end() );
+          for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+          {
+            if ( point.deviceId == iter->point.deviceId )
+            {
+              match = iter;
+              // Add new point to the HoverEvent
+              iter->point.state = TouchPoint::Finished;
+              hoverEvent.AddPoint( iter->point );
+            }
+            else
+            {
+              iter->point.state = TouchPoint::Stationary;
+              hoverEvent.AddPoint( iter->point );
+            }
+          }
+
+          if ( match != mHoveredPoints.end() )
+          {
+            mHoveredPoints.erase( match );
+            dispatchEvent = TouchEventCombiner::DispatchBoth; // We should only dispatch hover events if the point was actually hovered in this window
+          }
+        }
+      }
+
+      break;
+    }
+
+    case TouchPoint::Finished:
+    {
+      touchEvent.time = time;
+
+      // Find pressed touch point in local list (while also adding the stored points to the touchEvent)
+      PointInfoContainer::iterator match( mPressedPoints.end() );
+      for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
+      {
+        if ( point.deviceId == iter->point.deviceId )
+        {
+          match = iter;
+
+          // Add new point to the TouchEvent
+          touchEvent.AddPoint( point );
+        }
+        else
+        {
+          iter->point.state = TouchPoint::Stationary;
+          touchEvent.AddPoint( iter->point );
+        }
+      }
+
+      if ( match != mPressedPoints.end() )
+      {
+        mPressedPoints.erase( match );
+        dispatchEvent = TouchEventCombiner::DispatchTouch; // We should only dispatch touch events if the point was actually pressed in this window
+
+        // Iterate through already stored touch points for HoverEvent and delete them
+        for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+        {
+          if ( iter->point.deviceId == point.deviceId )
+          {
+            iter = mHoveredPoints.erase( iter );
+          }
+        }
+      }
+      break;
+    }
+
+    case TouchPoint::Motion:
+    {
+      bool fromNewDeviceId = false;
+
+      if ( !mPressedPoints.empty() )
+      {
+        touchEvent.time = time;
+
+        bool ignore = false;
+        PointInfoContainer::iterator match = mPressedPoints.end();
+        for ( PointInfoContainer::iterator iter = mPressedPoints.begin(), endIter = mPressedPoints.end(); iter != endIter; ++iter )
+        {
+          if ( point.deviceId == iter->point.deviceId )
+          {
+            unsigned long timeDiff( time - iter->time );
+
+            if ( timeDiff < mMinMotionTime )
+            {
+              // Motion event sent too soon after previous event so ignore
+              ignore = true;
+              break;
+            }
+
+            if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
+                 ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
+            {
+              // Not enough positional change from last event so ignore
+              ignore = true;
+              break;
+            }
+
+            match = iter;
+
+            // Add new touch point to the TouchEvent
+            touchEvent.AddPoint( point );
+          }
+          else
+          {
+            iter->point.state = TouchPoint::Stationary;
+            touchEvent.AddPoint( iter->point );
+          }
+        }
+
+        if ( match != mPressedPoints.end() )
+        {
+          PointInfo matchedPoint( point, time );
+          std::swap( *match, matchedPoint );
+
+          dispatchEvent = TouchEventCombiner::DispatchTouch; // Dispatch touch event
+        }
+        else if(!ignore)
+        {
+          fromNewDeviceId = true;
+        }
+      }
+
+      // Dispatch hover event if no previous down event received or the motion event comes from a new device ID
+      if(mPressedPoints.empty() || fromNewDeviceId)
+      {
+        hoverEvent.time = time;
+
+        // Iterate through already stored touch points and add to HoverEvent
+        bool ignore = false;
+        PointInfoContainer::iterator match = mHoveredPoints.end();
+        for ( PointInfoContainer::iterator iter = mHoveredPoints.begin(), endIter = mHoveredPoints.end(); iter != endIter; ++iter )
+        {
+          if ( iter->point.deviceId == point.deviceId )
+          {
+            unsigned long timeDiff( time - iter->time );
+
+            if ( timeDiff < mMinMotionTime )
+            {
+              // Motion event sent too soon after previous event so ignore
+              ignore = true;
+              break;
+            }
+
+            if ( ( abs( point.screen.x - iter->point.screen.x ) < mMinMotionDistance.x ) &&
+                 ( abs( point.screen.y - iter->point.screen.y ) < mMinMotionDistance.y ) )
+            {
+              // Not enough positional change from last event so ignore
+              ignore = true;
+              break;
+            }
+
+            match = iter;
+
+            // Add new touch point to the HoverEvent
+            hoverEvent.AddPoint( point );
+          }
+          else
+          {
+            iter->point.state = TouchPoint::Stationary;
+            hoverEvent.AddPoint( iter->point );
+          }
+        }
+
+        // Add new hover point to the list and to the HoverEvent
+        if ( !ignore ) // Only dispatch hover event when it should not be ignored
+        {
+          if( match == mHoveredPoints.end() )
+          {
+            TouchPoint hoverPoint(point);
+            hoverPoint.state = TouchPoint::Started; // The first hover event received
+            mHoveredPoints.push_back( PointInfo( hoverPoint, time ) );
+            hoverEvent.AddPoint( hoverPoint );
+          }
+          else
+          {
+            PointInfo matchedPoint( point, time );
+            std::swap( *match, matchedPoint );
+          }
+
+          if(dispatchEvent == TouchEventCombiner::DispatchTouch)
+          {
+            dispatchEvent = TouchEventCombiner::DispatchBoth;
+          }
+          else
+          {
+            dispatchEvent = TouchEventCombiner::DispatchHover;
+          }
+        }
+      }
+      break;
+    }
+
+    case TouchPoint::Interrupted:
+    {
+      Reset();
+
+      // We should still tell core about the interruption.
+      touchEvent.AddPoint( point );
+      hoverEvent.AddPoint( point );
+      dispatchEvent = TouchEventCombiner::DispatchBoth;
+      break;
+    }
+
+    default:
+      break;
+  }
+
+  return dispatchEvent;
+}
+
+void TouchEventCombiner::SetMinimumMotionTimeThreshold( unsigned long minTime )
+{
+  mMinMotionTime = minTime;
+}
+
+void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minDistance )
+{
+  DALI_ASSERT_ALWAYS( minDistance >= 0.0f && "Negative values not allowed\n" );
+
+  mMinMotionDistance.x = mMinMotionDistance.y = minDistance;
+}
+
+void TouchEventCombiner::SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance )
+{
+  DALI_ASSERT_ALWAYS( minXDistance >= 0.0f && minYDistance >= 0.0f && "Negative values not allowed\n" );
+
+  mMinMotionDistance.x = minXDistance;
+  mMinMotionDistance.y = minYDistance;
+}
+
+void TouchEventCombiner::SetMinimumMotionDistanceThreshold( Vector2 minDistance )
+{
+  DALI_ASSERT_ALWAYS( minDistance.x >= 0.0f && minDistance.y >= 0.0f && "Negative values not allowed\n" );
+
+  mMinMotionDistance = minDistance;
+}
+
+unsigned long TouchEventCombiner::GetMinimumMotionTimeThreshold() const
+{
+  return mMinMotionTime;
+}
+
+Vector2 TouchEventCombiner::GetMinimumMotionDistanceThreshold() const
+{
+  return mMinMotionDistance;
+}
+
+void TouchEventCombiner::Reset()
+{
+  mPressedPoints.clear();
+  mHoveredPoints.clear();
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/touch-event-combiner.h b/dali/integration-api/events/touch-event-combiner.h
new file mode 100644 (file)
index 0000000..1c3b351
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__
+#define __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/events/touch-point.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+struct TouchEvent;
+struct HoverEvent;
+
+/**
+ * Dali::Integration::TouchEventCombiner is a utility class, an instance of which, should be created
+ * upon initialisation.  It accepts single Point(s) containing information about a touch area and
+ * creates a TouchEvent and/or HoverEvent combining the latest event's information with previous TouchPoint(s).
+ *
+ * The created TouchEvent and/or HoverEvent can then be sent to the Dali Core as indicated by the GetNextTouchEvent()
+ * method.
+ *
+ * The TouchEventCombiner ensures that the following rules are also adhered to:
+ * - If two Down events are accidentally received, then the second one is ignored.
+ * - Motion events are not processed if a Down event does not precede it.
+ * - Motion event throttling is carried out to satisfy the minimum distance and time delta required.
+ * - If an interrupted event is received, then any stored Point history is cleared.
+ */
+class TouchEventCombiner
+{
+public:
+
+  // Enumerations
+
+  enum EventDispatchType
+  {
+    DispatchTouch,      ///< The touch event should be dispatched.
+    DispatchHover,      ///< The hover event should be dispatched.
+    DispatchBoth,       ///< Both touch event and hover event should be dispatched.
+    DispatchNone        ///< Neither touch event nor hover event should be dispatched.
+  };
+
+  /**
+   * Default Constructor.
+   * @note The default minimum motion time is 1 ms between motion events and the default behaviour
+   *       is to throttle X and Y movement by 1.
+   */
+  TouchEventCombiner();
+
+  /**
+   * Construction with parameters.
+   * @param[in]  minMotionTime       The minimum time (in ms) that should occur between motion events.
+   * @param[in]  minMotionXDistance  The minimum distance a finger has to be moved between horizontal motion events.
+   * @param[in]  minMotionYDistance  The minimum distance a finger has to be moved between vertical motion events.
+   * @note Will assert if any of the parameters is negative.
+   */
+  TouchEventCombiner( unsigned long minMotionTime, float minMotionXDistance, float minMotionYDistance );
+
+  /**
+   * Construction with parameters.
+   * @param[in]  minMotionTime      The minimum time (in ms) that should occur between motion events.
+   * @param[in]  minMotionDistance  A Vector2 representing the minimum distance a finger has to be moved between horizontal and vertical motion events.
+   * @note Will assert if any of the parameters is negative.
+   */
+  TouchEventCombiner( unsigned long minMotionTime, Vector2 minMotionDistance );
+
+  /**
+   * Non virtual destructor
+   */
+  ~TouchEventCombiner();
+
+public:
+
+  /**
+   * Allows the caller to pass in a point which is processed and the TouchEvent and/or HoverEvent is appropriately filled with the new,
+   * and previously stored Point information.
+   *
+   * @note If the thresholds set have not been passed, then false is returned and the TouchEvent and/or HoverEvent should not be sent
+   * to Dali Core.
+   *
+   * @param[in]   point         The new Point.
+   * @param[in]   time          The time the event occurred.
+   * @param[out]  touchEvent    This is populated with the correct Point(s) and time information.
+   * @param[out]  hoverEvent    This is populated with the correct Point(s) and time information.
+   *
+   * @return true if the point is beyond the different thresholds set thus, should be sent to core, false otherwise.
+   */
+  EventDispatchType GetNextTouchEvent( const TouchPoint& point, unsigned long time, TouchEvent& touchEvent, HoverEvent& hoverEvent );
+
+  /**
+   * Sets the minimum time (in ms) that should occur between motion events.
+   * @param[in]  minTime  Minimum time between motion events.
+   */
+  void SetMinimumMotionTimeThreshold( unsigned long minTime );
+
+  /**
+   * Sets the minimum distance a finger has to be moved (both X and Y) between motion events.
+   * @param[in]  minDistance  The minimum distance between motion events.
+   * @note Will assert if parameter is negative.
+   */
+  void SetMinimumMotionDistanceThreshold( float minDistance );
+
+  /**
+   * Sets the minimum distance a finger has to be moved between motion events.
+   * @param[in]  minXDistance  The minimum X distance between motion events.
+   * @param[in]  minYDistance  The minimum Y distance between motion events.
+   * @note Use this method if the X and Y threshold required is different.
+   * @note Will assert if any of the parameters is negative.
+   */
+  void SetMinimumMotionDistanceThreshold( float minXDistance, float minYDistance );
+
+  /**
+   * Sets the minimum distance a finger has to be moved between motion events.
+   * @param[in]  minDistance  A Vector2 representing the minimum X and Y thresholds.
+   * @note Use this method if the X and Y threshold required is different.
+   * @note Will assert if any of the parameters is negative.
+   */
+  void SetMinimumMotionDistanceThreshold( Vector2 minDistance );
+
+  /**
+   * Retrieves the minimum motion time threshold.
+   * @return the minimum time threshold.
+   */
+  unsigned long GetMinimumMotionTimeThreshold() const;
+
+  /**
+   * Gets the minimum distance a finger has to be moved (both X and Y) between motion events.
+   * @return A Vector2 representing the x and y thresholds.
+   */
+  Vector2 GetMinimumMotionDistanceThreshold() const;
+
+  /**
+   * This resets any information contained by the TouchEventCombiner.
+   * This may be required if some platform event has occurred which makes it necessary to reset any
+   * TouchPoint information that the combiner may store.
+   */
+  void Reset();
+
+private:
+
+  struct PointInfo;
+  typedef std::vector< PointInfo > PointInfoContainer;
+  PointInfoContainer mPressedPoints; ///< A container of touched point and time.
+  PointInfoContainer mHoveredPoints; ///< A container of hovered point and time.
+
+  unsigned long mMinMotionTime; ///< The minimum time that should elapse before considering a new motion event.
+  Vector2 mMinMotionDistance; ///< The minimum distance in the X and Y direction before considering a new motion event.
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_TOUCH_EVENT_COMBINER_H__
diff --git a/dali/integration-api/events/touch-event-integ.cpp b/dali/integration-api/events/touch-event-integ.cpp
new file mode 100644 (file)
index 0000000..ac44731
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/touch-event-integ.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+TouchEvent::TouchEvent()
+: MultiPointEvent( Touch )
+{
+}
+
+TouchEvent::TouchEvent( unsigned long time )
+: MultiPointEvent( Touch, time )
+{
+}
+
+TouchEvent::~TouchEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/touch-event-integ.h b/dali/integration-api/events/touch-event-integ.h
new file mode 100644 (file)
index 0000000..86752aa
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __DALI_INTEGRATION_TOUCH_EVENT_H__
+#define __DALI_INTEGRATION_TOUCH_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/touch-event.h>
+#include <dali/integration-api/events/multi-point-event-integ.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this structure should be used by the adaptor to send a touch event to Dali core.
+ *
+ * This class can contain one or many touch points. It also contains the time at which the
+ * event occurred.
+ */
+struct TouchEvent : public MultiPointEvent
+{
+  // Construction & Destruction
+
+  /**
+   * Default Constructor
+   */
+  TouchEvent();
+
+  /**
+   * Constructor
+   * @param[in]  time  The time the event occurred.
+   */
+  TouchEvent(unsigned long time);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~TouchEvent();
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_TOUCH_EVENT_H__
diff --git a/dali/integration-api/events/wheel-event-integ.cpp b/dali/integration-api/events/wheel-event-integ.cpp
new file mode 100644 (file)
index 0000000..3f99995
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/events/wheel-event-integ.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+WheelEvent::WheelEvent()
+: Event( Wheel ),
+  type( MOUSE_WHEEL ),
+  direction( 0 ),
+  modifiers( 0 ),
+  point( Vector2::ZERO ),
+  z( 0 ),
+  timeStamp( 0 )
+{
+}
+
+WheelEvent::WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp )
+: Event( Wheel ),
+  type( type ),
+  direction( direction ),
+  modifiers( modifiers ),
+  point( point ),
+  z( z ),
+  timeStamp( timeStamp )
+{
+}
+
+WheelEvent::~WheelEvent()
+{
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/events/wheel-event-integ.h b/dali/integration-api/events/wheel-event-integ.h
new file mode 100644 (file)
index 0000000..5b0e0b2
--- /dev/null
@@ -0,0 +1,111 @@
+#ifndef __DALI_INTEGRATION_WHEEL_EVENT_H__
+#define __DALI_INTEGRATION_WHEEL_EVENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/event.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali DALI_IMPORT_API
+{
+
+namespace Integration
+{
+
+/**
+ * An instance of this class should be used by the adaptor to send a wheel event to
+ * the Dali core.
+ *
+ */
+struct WheelEvent : public Event
+{
+  // Enumerations
+
+  /**
+   * @brief Specifies the type of the wheel event.
+   */
+  enum Type
+  {
+    MOUSE_WHEEL,      ///< Mouse wheel event
+    CUSTOM_WHEEL      ///< Custom wheel event
+  };
+
+  /**
+   * Default Constructor
+   */
+  WheelEvent();
+
+  /**
+   * Constructor
+   * @param[in]  type       The type of the wheel event
+   * @param[in]  direction  The direction of wheel rolling (0 = default vertical wheel, 1 = horizontal wheel)
+   * @param[in]  modifiers  modifier keys pressed during the event (such as shift, alt and control)
+   * @param[in]  point      The co-ordinates of the cursor relative to the top-left of the screen.
+   * @param[in]  z          The offset of rolling (positive value means roll down, and negative value means roll up)
+   * @param[in]  timeStamp  The time the wheel is being rolled.
+   */
+  WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~WheelEvent();
+
+  // Data
+
+  /**
+   *@copydoc Dali::WheelEvent::type
+   */
+  Type type;
+
+  /**
+   *@copydoc Dali::WheelEvent::direction
+   */
+  int direction;
+
+  /**
+   *@copydoc Dali::WheelEvent::modifiers
+   */
+  unsigned int modifiers;
+
+  /**
+   *@copydoc Dali::WheelEvent::point
+   */
+  Vector2 point;
+
+  /**
+   *@copydoc Dali::WheelEvent::z
+   */
+  int z;
+
+  /**
+   *@copydoc Dali::WheelEvent::timeStamp
+   */
+  unsigned int timeStamp;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_WHEEL_EVENT_H__
diff --git a/dali/integration-api/file.list b/dali/integration-api/file.list
new file mode 100644 (file)
index 0000000..ec83f66
--- /dev/null
@@ -0,0 +1,61 @@
+# Add platform abstraction headers here
+
+platform_abstraction_src_files = \
+   $(platform_abstraction_src_dir)/bitmap.cpp \
+   $(platform_abstraction_src_dir)/core.cpp \
+   $(platform_abstraction_src_dir)/image-data.cpp \
+   $(platform_abstraction_src_dir)/debug.cpp \
+   $(platform_abstraction_src_dir)/profiling.cpp \
+   $(platform_abstraction_src_dir)/input-options.cpp \
+   $(platform_abstraction_src_dir)/system-overlay.cpp \
+   $(platform_abstraction_src_dir)/lockless-buffer.cpp \
+   $(platform_abstraction_src_dir)/events/event.cpp \
+   $(platform_abstraction_src_dir)/events/gesture-event.cpp \
+   $(platform_abstraction_src_dir)/events/hover-event-integ.cpp \
+   $(platform_abstraction_src_dir)/events/key-event-integ.cpp \
+   $(platform_abstraction_src_dir)/events/long-press-gesture-event.cpp \
+   $(platform_abstraction_src_dir)/events/wheel-event-integ.cpp \
+   $(platform_abstraction_src_dir)/events/multi-point-event-integ.cpp \
+   $(platform_abstraction_src_dir)/events/pan-gesture-event.cpp \
+   $(platform_abstraction_src_dir)/events/pinch-gesture-event.cpp \
+   $(platform_abstraction_src_dir)/events/tap-gesture-event.cpp \
+   $(platform_abstraction_src_dir)/events/touch-event-combiner.cpp \
+   $(platform_abstraction_src_dir)/events/touch-event-integ.cpp
+
+platform_abstraction_header_files = \
+   $(platform_abstraction_src_dir)/core.h \
+   $(platform_abstraction_src_dir)/context-notifier.h \
+   $(platform_abstraction_src_dir)/debug.h \
+   $(platform_abstraction_src_dir)/profiling.h \
+   $(platform_abstraction_src_dir)/input-options.h \
+   $(platform_abstraction_src_dir)/bitmap.h \
+   $(platform_abstraction_src_dir)/resource-policies.h \
+   $(platform_abstraction_src_dir)/image-data.h \
+   $(platform_abstraction_src_dir)/resource-types.h \
+   $(platform_abstraction_src_dir)/resource-request.h \
+   $(platform_abstraction_src_dir)/resource-cache.h \
+   $(platform_abstraction_src_dir)/resource-declarations.h \
+   $(platform_abstraction_src_dir)/gl-abstraction.h \
+   $(platform_abstraction_src_dir)/gl-defines.h \
+   $(platform_abstraction_src_dir)/gl-sync-abstraction.h \
+   $(platform_abstraction_src_dir)/gesture-manager.h \
+   $(platform_abstraction_src_dir)/render-controller.h \
+   $(platform_abstraction_src_dir)/platform-abstraction.h \
+   $(platform_abstraction_src_dir)/system-overlay.h \
+   $(platform_abstraction_src_dir)/lockless-buffer.h
+
+platform_abstraction_events_header_files = \
+   $(platform_abstraction_src_dir)/events/event.h \
+   $(platform_abstraction_src_dir)/events/gesture-event.h \
+   $(platform_abstraction_src_dir)/events/gesture-requests.h \
+   $(platform_abstraction_src_dir)/events/hover-event-integ.h \
+   $(platform_abstraction_src_dir)/events/key-event-integ.h \
+   $(platform_abstraction_src_dir)/events/long-press-gesture-event.h \
+   $(platform_abstraction_src_dir)/events/wheel-event-integ.h \
+   $(platform_abstraction_src_dir)/events/multi-point-event-integ.h \
+   $(platform_abstraction_src_dir)/events/pan-gesture-event.h \
+   $(platform_abstraction_src_dir)/events/pinch-gesture-event.h \
+   $(platform_abstraction_src_dir)/events/tap-gesture-event.h \
+   $(platform_abstraction_src_dir)/events/touch-data.h \
+   $(platform_abstraction_src_dir)/events/touch-event-combiner.h \
+   $(platform_abstraction_src_dir)/events/touch-event-integ.h
diff --git a/dali/integration-api/gesture-manager.h b/dali/integration-api/gesture-manager.h
new file mode 100644 (file)
index 0000000..ba32f03
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __DALI_INTEGRATION_GESTURE_MANAGER_H__
+#define __DALI_INTEGRATION_GESTURE_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/integration-api/events/gesture-requests.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * GestureManager is an abstract interface, used by Dali to register and unregister gestures provided
+ * by the adaptor. A concrete implementation must be created for each adaptor, and provided when creating
+ * the Dali::Integration::Core object.
+ */
+class DALI_IMPORT_API GestureManager
+{
+public:
+
+  /**
+   * Called by Dali to enable the adaptor to start detecting the required gesture type.
+   * @param[in]  request  The required gesture and details.
+   */
+  virtual void Register(const GestureRequest& request) = 0;
+
+  /**
+   * Called by Dali to inform the adaptor that it no longer requires a GestureEvent when the state
+   * gesture type is detected.
+   * @param[in]  request  The gesture that is no longer required.
+   */
+  virtual void Unregister(const GestureRequest& request) = 0;
+
+  /**
+   * Called by Dali to inform the adaptor that the detection parameters of a previously requested
+   * gesture have now changed.
+   * @param[in]  request  The gesture and updated details.
+   */
+  virtual void Update(const GestureRequest& request) = 0;
+
+}; // class GestureManager
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_GESTURE_MANAGER_H__
diff --git a/dali/integration-api/gl-abstraction.h b/dali/integration-api/gl-abstraction.h
new file mode 100644 (file)
index 0000000..a5d81f3
--- /dev/null
@@ -0,0 +1,381 @@
+#ifndef __DALI_INTEGRATION_GL_ABSTRACTION_H__
+#define __DALI_INTEGRATION_GL_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdint.h>
+
+/*
+ * This file is based on gl3.h, the following licence is included for conformance.
+ */
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+
+/* OpenGL ES 3.0 */
+struct __GLsync;
+
+namespace Dali
+{
+
+/**
+ * These types are equivalent to those in the GLES2 API.
+ * Dali objects should only access GL indirectly, through the Context API.
+ */
+
+/* OpenGL ES 2.0 */
+
+typedef void             GLvoid;
+typedef char             GLchar;
+typedef unsigned int     GLenum;
+typedef unsigned char    GLboolean;
+typedef unsigned int     GLbitfield;
+typedef int8_t           GLbyte;
+typedef short            GLshort;
+typedef int              GLint;
+typedef int              GLsizei;
+typedef uint8_t          GLubyte;
+typedef unsigned short   GLushort;
+typedef unsigned int     GLuint;
+typedef float            GLfloat;
+typedef float            GLclampf;
+typedef int              GLfixed;
+typedef signed long int  GLintptr;
+typedef signed long int  GLsizeiptr;
+
+/* OpenGL ES 3.0 */
+
+typedef unsigned short     GLhalf;
+typedef int64_t            GLint64;
+typedef uint64_t           GLuint64;
+typedef __GLsync* GLsync;
+
+namespace Integration
+{
+
+/**
+ * GlAbstraction is an abstract interface, used to access OpenGL services.
+ * A concrete implementation must be created for each platform, and provided when creating the
+ * Dali::Integration::Core object.
+ */
+class GlAbstraction
+{
+protected:
+
+  /**
+   * Virtual protected destructor, no deletion through this interface
+   */
+  virtual ~GlAbstraction() {}
+
+public:
+  /**
+   * Invoked by Render thread before Core::Render.
+   */
+  virtual void PreRender() = 0;
+
+  /**
+   * Invoked by Render thread after Core::Render
+   * Inform the gl implementation that the rendering in this frame has finished,
+   * and how much time was spent.
+   */
+  virtual void PostRender() = 0;
+
+  /**
+   * The number of texture units an implementation supports is implementation dependent, but must be at least 8.
+   */
+  static const unsigned int MIN_TEXTURE_UNIT_LIMIT = 8;
+
+  /* OpenGL ES 2.0 */
+
+  virtual void         ActiveTexture (GLenum texture) = 0;
+  virtual void         AttachShader (GLuint program, GLuint shader) = 0;
+  virtual void         BindAttribLocation (GLuint program, GLuint index, const char* name) = 0;
+  virtual void         BindBuffer (GLenum target, GLuint buffer) = 0;
+  virtual void         BindFramebuffer (GLenum target, GLuint framebuffer) = 0;
+  virtual void         BindRenderbuffer (GLenum target, GLuint renderbuffer) = 0;
+  virtual void         BindTexture (GLenum target, GLuint texture) = 0;
+  virtual void         BlendColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) = 0;
+  virtual void         BlendEquation ( GLenum mode ) = 0;
+  virtual void         BlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha) = 0;
+  virtual void         BlendFunc (GLenum sfactor, GLenum dfactor) = 0;
+  virtual void         BlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) = 0;
+  virtual void         BufferData (GLenum target, GLsizeiptr size, const void* data, GLenum usage) = 0;
+  virtual void         BufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void* data) = 0;
+  virtual GLenum       CheckFramebufferStatus (GLenum target) = 0;
+  virtual void         Clear (GLbitfield mask) = 0;
+  virtual void         ClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) = 0;
+  virtual void         ClearDepthf (GLclampf depth) = 0;
+  virtual void         ClearStencil (GLint s) = 0;
+  virtual void         ColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) = 0;
+  virtual void         CompileShader (GLuint shader) = 0;
+  virtual void         CompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data) = 0;
+  virtual void         CompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data) = 0;
+  virtual void         CopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) = 0;
+  virtual void         CopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+  virtual GLuint       CreateProgram (void) = 0;
+  virtual GLuint       CreateShader (GLenum type) = 0;
+  virtual void         CullFace (GLenum mode) = 0;
+  virtual void         DeleteBuffers (GLsizei n, const GLuint* buffers) = 0;
+  virtual void         DeleteFramebuffers (GLsizei n, const GLuint* framebuffers) = 0;
+  virtual void         DeleteProgram (GLuint program) = 0;
+  virtual void         DeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers) = 0;
+  virtual void         DeleteShader (GLuint shader) = 0;
+  virtual void         DeleteTextures (GLsizei n, const GLuint* textures) = 0;
+  virtual void         DepthFunc (GLenum func) = 0;
+  virtual void         DepthMask (GLboolean flag) = 0;
+  virtual void         DepthRangef (GLclampf zNear, GLclampf zFar) = 0;
+  virtual void         DetachShader (GLuint program, GLuint shader) = 0;
+  virtual void         Disable (GLenum cap) = 0;
+  virtual void         DisableVertexAttribArray (GLuint index) = 0;
+  virtual void         DrawArrays (GLenum mode, GLint first, GLsizei count) = 0;
+  virtual void         DrawElements (GLenum mode, GLsizei count, GLenum type, const void* indices) = 0;
+  virtual void         Enable (GLenum cap) = 0;
+  virtual void         EnableVertexAttribArray (GLuint index) = 0;
+  virtual void         Finish (void) = 0;
+  virtual void         Flush (void) = 0;
+  virtual void         FramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) = 0;
+  virtual void         FramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) = 0;
+  virtual void         FrontFace (GLenum mode) = 0;
+  virtual void         GenBuffers (GLsizei n, GLuint* buffers) = 0;
+  virtual void         GenerateMipmap (GLenum target) = 0;
+  virtual void         GenFramebuffers (GLsizei n, GLuint* framebuffers) = 0;
+  virtual void         GenRenderbuffers (GLsizei n, GLuint* renderbuffers) = 0;
+  virtual void         GenTextures (GLsizei n, GLuint* textures) = 0;
+  virtual void         GetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) = 0;
+  virtual void         GetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, char* name) = 0;
+  virtual void         GetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders) = 0;
+  virtual GLint        GetAttribLocation (GLuint program, const char* name) = 0;
+  virtual void         GetBooleanv (GLenum pname, GLboolean* params) = 0;
+  virtual void         GetBufferParameteriv (GLenum target, GLenum pname, GLint* params) = 0;
+  virtual GLenum       GetError (void) = 0;
+  virtual void         GetFloatv (GLenum pname, GLfloat* params) = 0;
+  virtual void         GetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params) = 0;
+  virtual void         GetIntegerv (GLenum pname, GLint* params) = 0;
+  virtual void         GetProgramiv (GLuint program, GLenum pname, GLint* params) = 0;
+  virtual void         GetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, char* infolog) = 0;
+  virtual void         GetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params) = 0;
+  virtual void         GetShaderiv (GLuint shader, GLenum pname, GLint* params) = 0;
+  virtual void         GetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog) = 0;
+  virtual void         GetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision) = 0;
+  virtual void         GetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, char* source) = 0;
+  virtual const GLubyte* GetString (GLenum name) = 0;
+  virtual void         GetTexParameterfv (GLenum target, GLenum pname, GLfloat* params) = 0;
+  virtual void         GetTexParameteriv (GLenum target, GLenum pname, GLint* params) = 0;
+  virtual void         GetUniformfv (GLuint program, GLint location, GLfloat* params) = 0;
+  virtual void         GetUniformiv (GLuint program, GLint location, GLint* params) = 0;
+  virtual GLint        GetUniformLocation (GLuint program, const char* name) = 0;
+  virtual void         GetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params) = 0;
+  virtual void         GetVertexAttribiv (GLuint index, GLenum pname, GLint* params) = 0;
+  virtual void         GetVertexAttribPointerv (GLuint index, GLenum pname, void** pointer) = 0;
+  virtual void         Hint (GLenum target, GLenum mode) = 0;
+  virtual GLboolean    IsBuffer (GLuint buffer) = 0;
+  virtual GLboolean    IsEnabled (GLenum cap) = 0;
+  virtual GLboolean    IsFramebuffer (GLuint framebuffer) = 0;
+  virtual GLboolean    IsProgram (GLuint program) = 0;
+  virtual GLboolean    IsRenderbuffer (GLuint renderbuffer) = 0;
+  virtual GLboolean    IsShader (GLuint shader) = 0;
+  virtual GLboolean    IsTexture (GLuint texture) = 0;
+  virtual void         LineWidth (GLfloat width) = 0;
+  virtual void         LinkProgram (GLuint program) = 0;
+  virtual void         PixelStorei (GLenum pname, GLint param) = 0;
+  virtual void         PolygonOffset (GLfloat factor, GLfloat units) = 0;
+  virtual void         ReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels) = 0;
+  virtual void         ReleaseShaderCompiler (void) = 0;
+  virtual void         RenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height) = 0;
+  virtual void         SampleCoverage (GLclampf value, GLboolean invert) = 0;
+  virtual void         Scissor (GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+  virtual void         ShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLsizei length) = 0;
+  virtual void         ShaderSource (GLuint shader, GLsizei count, const char** string, const GLint* length) = 0;
+  virtual void         StencilFunc (GLenum func, GLint ref, GLuint mask) = 0;
+  virtual void         StencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask) = 0;
+  virtual void         StencilMask (GLuint mask) = 0;
+  virtual void         StencilMaskSeparate (GLenum face, GLuint mask) = 0;
+  virtual void         StencilOp (GLenum fail, GLenum zfail, GLenum zpass) = 0;
+  virtual void         StencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) = 0;
+  virtual void         TexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels) = 0;
+  virtual void         TexParameterf (GLenum target, GLenum pname, GLfloat param) = 0;
+  virtual void         TexParameterfv (GLenum target, GLenum pname, const GLfloat* params) = 0;
+  virtual void         TexParameteri (GLenum target, GLenum pname, GLint param) = 0;
+  virtual void         TexParameteriv (GLenum target, GLenum pname, const GLint* params) = 0;
+  virtual void         TexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void* pixels) = 0;
+  virtual void         Uniform1f (GLint location, GLfloat x) = 0;
+  virtual void         Uniform1fv (GLint location, GLsizei count, const GLfloat* v) = 0;
+  virtual void         Uniform1i (GLint location, GLint x) = 0;
+  virtual void         Uniform1iv (GLint location, GLsizei count, const GLint* v) = 0;
+  virtual void         Uniform2f (GLint location, GLfloat x, GLfloat y) = 0;
+  virtual void         Uniform2fv (GLint location, GLsizei count, const GLfloat* v) = 0;
+  virtual void         Uniform2i (GLint location, GLint x, GLint y) = 0;
+  virtual void         Uniform2iv (GLint location, GLsizei count, const GLint* v) = 0;
+  virtual void         Uniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z) = 0;
+  virtual void         Uniform3fv (GLint location, GLsizei count, const GLfloat* v) = 0;
+  virtual void         Uniform3i (GLint location, GLint x, GLint y, GLint z) = 0;
+  virtual void         Uniform3iv (GLint location, GLsizei count, const GLint* v) = 0;
+  virtual void         Uniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = 0;
+  virtual void         Uniform4fv (GLint location, GLsizei count, const GLfloat* v) = 0;
+  virtual void         Uniform4i (GLint location, GLint x, GLint y, GLint z, GLint w) = 0;
+  virtual void         Uniform4iv (GLint location, GLsizei count, const GLint* v) = 0;
+  virtual void         UniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void         UniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void         UniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void         UseProgram (GLuint program) = 0;
+  virtual void         ValidateProgram (GLuint program) = 0;
+  virtual void         VertexAttrib1f (GLuint indx, GLfloat x) = 0;
+  virtual void         VertexAttrib1fv (GLuint indx, const GLfloat* values) = 0;
+  virtual void         VertexAttrib2f (GLuint indx, GLfloat x, GLfloat y) = 0;
+  virtual void         VertexAttrib2fv (GLuint indx, const GLfloat* values) = 0;
+  virtual void         VertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z) = 0;
+  virtual void         VertexAttrib3fv (GLuint indx, const GLfloat* values) = 0;
+  virtual void         VertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w) = 0;
+  virtual void         VertexAttrib4fv (GLuint indx, const GLfloat* values) = 0;
+  virtual void         VertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr) = 0;
+  virtual void         Viewport (GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+
+  /* OpenGL ES 3.0 */
+
+  virtual void           ReadBuffer (GLenum mode) = 0;
+  virtual void           DrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) = 0;
+  virtual void           TexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) = 0;
+  virtual void           TexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) = 0;
+  virtual void           CopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+  virtual void           CompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) = 0;
+  virtual void           CompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) = 0;
+  virtual void           GenQueries (GLsizei n, GLuint* ids) = 0;
+  virtual void           DeleteQueries (GLsizei n, const GLuint* ids) = 0;
+  virtual GLboolean      IsQuery (GLuint id) = 0;
+  virtual void           BeginQuery (GLenum target, GLuint id) = 0;
+  virtual void           EndQuery (GLenum target) = 0;
+  virtual void           GetQueryiv (GLenum target, GLenum pname, GLint* params) = 0;
+  virtual void           GetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params) = 0;
+  virtual GLboolean      UnmapBuffer (GLenum target) = 0;
+  virtual void           GetBufferPointerv (GLenum target, GLenum pname, GLvoid** params) = 0;
+  virtual void           DrawBuffers (GLsizei n, const GLenum* bufs) = 0;
+  virtual void           UniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           UniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           UniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           UniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           UniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           UniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) = 0;
+  virtual void           BlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) = 0;
+  virtual void           RenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) = 0;
+  virtual void           FramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) = 0;
+  virtual GLvoid*        MapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) = 0;
+  virtual void           FlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length) = 0;
+  virtual void           BindVertexArray (GLuint array) = 0;
+  virtual void           DeleteVertexArrays (GLsizei n, const GLuint* arrays) = 0;
+  virtual void           GenVertexArrays (GLsizei n, GLuint* arrays) = 0;
+  virtual GLboolean      IsVertexArray (GLuint array) = 0;
+  virtual void           GetIntegeri_v (GLenum target, GLuint index, GLint* data) = 0;
+  virtual void           BeginTransformFeedback (GLenum primitiveMode) = 0;
+  virtual void           EndTransformFeedback (void) = 0;
+  virtual void           BindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) = 0;
+  virtual void           BindBufferBase (GLenum target, GLuint index, GLuint buffer) = 0;
+  virtual void           TransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) = 0;
+  virtual void           GetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) = 0;
+  virtual void           VertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) = 0;
+  virtual void           GetVertexAttribIiv (GLuint index, GLenum pname, GLint* params) = 0;
+  virtual void           GetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params) = 0;
+  virtual void           VertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w) = 0;
+  virtual void           VertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) = 0;
+  virtual void           VertexAttribI4iv (GLuint index, const GLint* v) = 0;
+  virtual void           VertexAttribI4uiv (GLuint index, const GLuint* v) = 0;
+  virtual void           GetUniformuiv (GLuint program, GLint location, GLuint* params) = 0;
+  virtual GLint          GetFragDataLocation (GLuint program, const GLchar *name) = 0;
+  virtual void           Uniform1ui (GLint location, GLuint v0) = 0;
+  virtual void           Uniform2ui (GLint location, GLuint v0, GLuint v1) = 0;
+  virtual void           Uniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2) = 0;
+  virtual void           Uniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) = 0;
+  virtual void           Uniform1uiv (GLint location, GLsizei count, const GLuint* value) = 0;
+  virtual void           Uniform2uiv (GLint location, GLsizei count, const GLuint* value) = 0;
+  virtual void           Uniform3uiv (GLint location, GLsizei count, const GLuint* value) = 0;
+  virtual void           Uniform4uiv (GLint location, GLsizei count, const GLuint* value) = 0;
+  virtual void           ClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value) = 0;
+  virtual void           ClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value) = 0;
+  virtual void           ClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value) = 0;
+  virtual void           ClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
+  virtual const GLubyte* GetStringi (GLenum name, GLuint index) = 0;
+  virtual void           CopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) = 0;
+  virtual void           GetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) = 0;
+  virtual void           GetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) = 0;
+  virtual GLuint         GetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName) = 0;
+  virtual void           GetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) = 0;
+  virtual void           GetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) = 0;
+  virtual void           UniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) = 0;
+  virtual void           DrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) = 0;
+  virtual void           DrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) = 0;
+  virtual GLsync         FenceSync (GLenum condition, GLbitfield flags) = 0;
+  virtual GLboolean      IsSync (GLsync sync) = 0;
+  virtual void           DeleteSync (GLsync sync) = 0;
+  virtual GLenum         ClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout) = 0;
+  virtual void           WaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout) = 0;
+  virtual void           GetInteger64v (GLenum pname, GLint64* params) = 0;
+  virtual void           GetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) = 0;
+  virtual void           GetInteger64i_v (GLenum target, GLuint index, GLint64* data) = 0;
+  virtual void           GetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params) = 0;
+  virtual void           GenSamplers (GLsizei count, GLuint* samplers) = 0;
+  virtual void           DeleteSamplers (GLsizei count, const GLuint* samplers) = 0;
+  virtual GLboolean      IsSampler (GLuint sampler) = 0;
+  virtual void           BindSampler (GLuint unit, GLuint sampler) = 0;
+  virtual void           SamplerParameteri (GLuint sampler, GLenum pname, GLint param) = 0;
+  virtual void           SamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param) = 0;
+  virtual void           SamplerParameterf (GLuint sampler, GLenum pname, GLfloat param) = 0;
+  virtual void           SamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param) = 0;
+  virtual void           GetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params) = 0;
+  virtual void           GetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params) = 0;
+  virtual void           VertexAttribDivisor (GLuint index, GLuint divisor) = 0;
+  virtual void           BindTransformFeedback (GLenum target, GLuint id) = 0;
+  virtual void           DeleteTransformFeedbacks (GLsizei n, const GLuint* ids) = 0;
+  virtual void           GenTransformFeedbacks (GLsizei n, GLuint* ids) = 0;
+  virtual GLboolean      IsTransformFeedback (GLuint id) = 0;
+  virtual void           PauseTransformFeedback (void) = 0;
+  virtual void           ResumeTransformFeedback (void) = 0;
+  virtual void           GetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) = 0;
+  virtual void           ProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) = 0;
+  virtual void           ProgramParameteri (GLuint program, GLenum pname, GLint value) = 0;
+  virtual void           InvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments) = 0;
+  virtual void           InvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+  virtual void           TexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = 0;
+  virtual void           TexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0;
+  virtual void           GetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) = 0;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_GL_ABSTRACTION_H__
diff --git a/dali/integration-api/gl-defines.h b/dali/integration-api/gl-defines.h
new file mode 100644 (file)
index 0000000..5af7acd
--- /dev/null
@@ -0,0 +1,827 @@
+#ifndef __DALI_INTERNAL_GL_DEFINES_H__
+#define __DALI_INTERNAL_GL_DEFINES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <stdint.h>
+
+/*
+ * This file is based on gl3.h, the following licence is included for conformance.
+ */
+/*
+** Copyright (c) 2007-2012 The Khronos Group Inc.
+**
+** Permission is hereby granted, free of charge, to any person obtaining a
+** copy of this software and/or associated documentation files (the
+** "Materials"), to deal in the Materials without restriction, including
+** without limitation the rights to use, copy, modify, merge, publish,
+** distribute, sublicense, and/or sell copies of the Materials, and to
+** permit persons to whom the Materials are furnished to do so, subject to
+** the following conditions:
+**
+** The above copyright notice and this permission notice shall be included
+** in all copies or substantial portions of the Materials.
+**
+** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+*/
+
+/* OpenGL ES 2.0 */
+
+/* ClearBufferMask */
+#define GL_DEPTH_BUFFER_BIT                              0x00000100
+#define GL_STENCIL_BUFFER_BIT                            0x00000400
+#define GL_COLOR_BUFFER_BIT                              0x00004000
+
+/* Boolean */
+#define GL_FALSE                                         0
+#define GL_TRUE                                          1
+
+/* BeginMode */
+#define GL_POINTS                                        0x0000
+#define GL_LINES                                         0x0001
+#define GL_LINE_LOOP                                     0x0002
+#define GL_LINE_STRIP                                    0x0003
+#define GL_TRIANGLES                                     0x0004
+#define GL_TRIANGLE_STRIP                                0x0005
+#define GL_TRIANGLE_FAN                                  0x0006
+
+/* BlendingFactorDest */
+#define GL_ZERO                                          0
+#define GL_ONE                                           1
+#define GL_SRC_COLOR                                     0x0300
+#define GL_ONE_MINUS_SRC_COLOR                           0x0301
+#define GL_SRC_ALPHA                                     0x0302
+#define GL_ONE_MINUS_SRC_ALPHA                           0x0303
+#define GL_DST_ALPHA                                     0x0304
+#define GL_ONE_MINUS_DST_ALPHA                           0x0305
+
+/* BlendingFactorSrc */
+/*      GL_ZERO */
+/*      GL_ONE */
+#define GL_DST_COLOR                                     0x0306
+#define GL_ONE_MINUS_DST_COLOR                           0x0307
+#define GL_SRC_ALPHA_SATURATE                            0x0308
+/*      GL_SRC_ALPHA */
+/*      GL_ONE_MINUS_SRC_ALPHA */
+/*      GL_DST_ALPHA */
+/*      GL_ONE_MINUS_DST_ALPHA */
+
+/* BlendEquationSeparate */
+#define GL_FUNC_ADD                                      0x8006
+#define GL_BLEND_EQUATION                                0x8009
+#define GL_BLEND_EQUATION_RGB                            0x8009    /* same as BLEND_EQUATION */
+#define GL_BLEND_EQUATION_ALPHA                          0x883D
+
+/* BlendSubtract */
+#define GL_FUNC_SUBTRACT                                 0x800A
+#define GL_FUNC_REVERSE_SUBTRACT                         0x800B
+
+/* Separate Blend Functions */
+#define GL_BLEND_DST_RGB                                 0x80C8
+#define GL_BLEND_SRC_RGB                                 0x80C9
+#define GL_BLEND_DST_ALPHA                               0x80CA
+#define GL_BLEND_SRC_ALPHA                               0x80CB
+#define GL_CONSTANT_COLOR                                0x8001
+#define GL_ONE_MINUS_CONSTANT_COLOR                      0x8002
+#define GL_CONSTANT_ALPHA                                0x8003
+#define GL_ONE_MINUS_CONSTANT_ALPHA                      0x8004
+#define GL_BLEND_COLOR                                   0x8005
+
+/* Buffer Objects */
+#define GL_ARRAY_BUFFER                                  0x8892
+#define GL_ELEMENT_ARRAY_BUFFER                          0x8893
+#define GL_ARRAY_BUFFER_BINDING                          0x8894
+#define GL_ELEMENT_ARRAY_BUFFER_BINDING                  0x8895
+
+#define GL_STREAM_DRAW                                   0x88E0
+#define GL_STATIC_DRAW                                   0x88E4
+#define GL_DYNAMIC_DRAW                                  0x88E8
+
+#define GL_BUFFER_SIZE                                   0x8764
+#define GL_BUFFER_USAGE                                  0x8765
+
+#define GL_CURRENT_VERTEX_ATTRIB                         0x8626
+
+/* CullFaceMode */
+#define GL_FRONT                                         0x0404
+#define GL_BACK                                          0x0405
+#define GL_FRONT_AND_BACK                                0x0408
+
+/* DepthFunction */
+/*      GL_NEVER */
+/*      GL_LESS */
+/*      GL_EQUAL */
+/*      GL_LEQUAL */
+/*      GL_GREATER */
+/*      GL_NOTEQUAL */
+/*      GL_GEQUAL */
+/*      GL_ALWAYS */
+
+/* EnableCap */
+#define GL_TEXTURE_2D                                    0x0DE1
+#define GL_CULL_FACE                                     0x0B44
+#define GL_BLEND                                         0x0BE2
+#define GL_DITHER                                        0x0BD0
+#define GL_STENCIL_TEST                                  0x0B90
+#define GL_DEPTH_TEST                                    0x0B71
+#define GL_SCISSOR_TEST                                  0x0C11
+#define GL_POLYGON_OFFSET_FILL                           0x8037
+#define GL_SAMPLE_ALPHA_TO_COVERAGE                      0x809E
+#define GL_SAMPLE_COVERAGE                               0x80A0
+
+/* ErrorCode */
+#define GL_NO_ERROR                                      0
+#define GL_INVALID_ENUM                                  0x0500
+#define GL_INVALID_VALUE                                 0x0501
+#define GL_INVALID_OPERATION                             0x0502
+#define GL_OUT_OF_MEMORY                                 0x0505
+
+/* FrontFaceDirection */
+#define GL_CW                                            0x0900
+#define GL_CCW                                           0x0901
+
+/* GetPName */
+#define GL_LINE_WIDTH                                    0x0B21
+#define GL_ALIASED_POINT_SIZE_RANGE                      0x846D
+#define GL_ALIASED_LINE_WIDTH_RANGE                      0x846E
+#define GL_CULL_FACE_MODE                                0x0B45
+#define GL_FRONT_FACE                                    0x0B46
+#define GL_DEPTH_RANGE                                   0x0B70
+#define GL_DEPTH_WRITEMASK                               0x0B72
+#define GL_DEPTH_CLEAR_VALUE                             0x0B73
+#define GL_DEPTH_FUNC                                    0x0B74
+#define GL_STENCIL_CLEAR_VALUE                           0x0B91
+#define GL_STENCIL_FUNC                                  0x0B92
+#define GL_STENCIL_FAIL                                  0x0B94
+#define GL_STENCIL_PASS_DEPTH_FAIL                       0x0B95
+#define GL_STENCIL_PASS_DEPTH_PASS                       0x0B96
+#define GL_STENCIL_REF                                   0x0B97
+#define GL_STENCIL_VALUE_MASK                            0x0B93
+#define GL_STENCIL_WRITEMASK                             0x0B98
+#define GL_STENCIL_BACK_FUNC                             0x8800
+#define GL_STENCIL_BACK_FAIL                             0x8801
+#define GL_STENCIL_BACK_PASS_DEPTH_FAIL                  0x8802
+#define GL_STENCIL_BACK_PASS_DEPTH_PASS                  0x8803
+#define GL_STENCIL_BACK_REF                              0x8CA3
+#define GL_STENCIL_BACK_VALUE_MASK                       0x8CA4
+#define GL_STENCIL_BACK_WRITEMASK                        0x8CA5
+#define GL_VIEWPORT                                      0x0BA2
+#define GL_SCISSOR_BOX                                   0x0C10
+/*      GL_SCISSOR_TEST */
+#define GL_COLOR_CLEAR_VALUE                             0x0C22
+#define GL_COLOR_WRITEMASK                               0x0C23
+#define GL_UNPACK_ALIGNMENT                              0x0CF5
+#define GL_PACK_ALIGNMENT                                0x0D05
+#define GL_MAX_TEXTURE_SIZE                              0x0D33
+#define GL_MAX_VIEWPORT_DIMS                             0x0D3A
+#define GL_SUBPIXEL_BITS                                 0x0D50
+#define GL_RED_BITS                                      0x0D52
+#define GL_GREEN_BITS                                    0x0D53
+#define GL_BLUE_BITS                                     0x0D54
+#define GL_ALPHA_BITS                                    0x0D55
+#define GL_DEPTH_BITS                                    0x0D56
+#define GL_STENCIL_BITS                                  0x0D57
+#define GL_POLYGON_OFFSET_UNITS                          0x2A00
+/*      GL_POLYGON_OFFSET_FILL */
+#define GL_POLYGON_OFFSET_FACTOR                         0x8038
+#define GL_TEXTURE_BINDING_2D                            0x8069
+#define GL_SAMPLE_BUFFERS                                0x80A8
+#define GL_SAMPLES                                       0x80A9
+#define GL_SAMPLE_COVERAGE_VALUE                         0x80AA
+#define GL_SAMPLE_COVERAGE_INVERT                        0x80AB
+
+/* GetTextureParameter */
+/*      GL_TEXTURE_MAG_FILTER */
+/*      GL_TEXTURE_MIN_FILTER */
+/*      GL_TEXTURE_WRAP_S */
+/*      GL_TEXTURE_WRAP_T */
+
+#define GL_NUM_COMPRESSED_TEXTURE_FORMATS                0x86A2
+#define GL_COMPRESSED_TEXTURE_FORMATS                    0x86A3
+
+/* HintMode */
+#define GL_DONT_CARE                                     0x1100
+#define GL_FASTEST                                       0x1101
+#define GL_NICEST                                        0x1102
+
+/* HintTarget */
+#define GL_GENERATE_MIPMAP_HINT                          0x8192
+
+/* DataType */
+#define GL_BYTE                                          0x1400
+#define GL_UNSIGNED_BYTE                                 0x1401
+#define GL_SHORT                                         0x1402
+#define GL_UNSIGNED_SHORT                                0x1403
+#define GL_INT                                           0x1404
+#define GL_UNSIGNED_INT                                  0x1405
+#define GL_FLOAT                                         0x1406
+#define GL_FIXED                                         0x140C
+
+/* PixelFormat */
+#define GL_DEPTH_COMPONENT                               0x1902
+#define GL_ALPHA                                         0x1906
+#define GL_RGB                                           0x1907
+#define GL_RGBA                                          0x1908
+#define GL_LUMINANCE                                     0x1909
+#define GL_LUMINANCE_ALPHA                               0x190A
+
+/* PixelType */
+/*      GL_UNSIGNED_BYTE */
+#define GL_UNSIGNED_SHORT_4_4_4_4                        0x8033
+#define GL_UNSIGNED_SHORT_5_5_5_1                        0x8034
+#define GL_UNSIGNED_SHORT_5_6_5                          0x8363
+
+/* Shaders */
+#define GL_FRAGMENT_SHADER                               0x8B30
+#define GL_VERTEX_SHADER                                 0x8B31
+#define GL_MAX_VERTEX_ATTRIBS                            0x8869
+#define GL_MAX_VERTEX_UNIFORM_VECTORS                    0x8DFB
+#define GL_MAX_VARYING_VECTORS                           0x8DFC
+#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS              0x8B4D
+#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS                0x8B4C
+#define GL_MAX_TEXTURE_IMAGE_UNITS                       0x8872
+#define GL_MAX_FRAGMENT_UNIFORM_VECTORS                  0x8DFD
+#define GL_SHADER_TYPE                                   0x8B4F
+#define GL_DELETE_STATUS                                 0x8B80
+#define GL_LINK_STATUS                                   0x8B82
+#define GL_VALIDATE_STATUS                               0x8B83
+#define GL_ATTACHED_SHADERS                              0x8B85
+#define GL_ACTIVE_UNIFORMS                               0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH                     0x8B87
+#define GL_ACTIVE_ATTRIBUTES                             0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH                   0x8B8A
+#define GL_SHADING_LANGUAGE_VERSION                      0x8B8C
+#define GL_CURRENT_PROGRAM                               0x8B8D
+
+/* StencilFunction */
+#define GL_NEVER                                         0x0200
+#define GL_LESS                                          0x0201
+#define GL_EQUAL                                         0x0202
+#define GL_LEQUAL                                        0x0203
+#define GL_GREATER                                       0x0204
+#define GL_NOTEQUAL                                      0x0205
+#define GL_GEQUAL                                        0x0206
+#define GL_ALWAYS                                        0x0207
+
+/* StencilOp */
+/*      GL_ZERO */
+#define GL_KEEP                                          0x1E00
+#define GL_REPLACE                                       0x1E01
+#define GL_INCR                                          0x1E02
+#define GL_DECR                                          0x1E03
+#define GL_INVERT                                        0x150A
+#define GL_INCR_WRAP                                     0x8507
+#define GL_DECR_WRAP                                     0x8508
+
+/* StringName */
+#define GL_VENDOR                                        0x1F00
+#define GL_RENDERER                                      0x1F01
+#define GL_VERSION                                       0x1F02
+#define GL_EXTENSIONS                                    0x1F03
+
+/* TextureMagFilter */
+#define GL_NEAREST                                       0x2600
+#define GL_LINEAR                                        0x2601
+
+/* TextureMinFilter */
+/*      GL_NEAREST */
+/*      GL_LINEAR */
+#define GL_NEAREST_MIPMAP_NEAREST                        0x2700
+#define GL_LINEAR_MIPMAP_NEAREST                         0x2701
+#define GL_NEAREST_MIPMAP_LINEAR                         0x2702
+#define GL_LINEAR_MIPMAP_LINEAR                          0x2703
+
+/* TextureParameterName */
+#define GL_TEXTURE_MAG_FILTER                            0x2800
+#define GL_TEXTURE_MIN_FILTER                            0x2801
+#define GL_TEXTURE_WRAP_S                                0x2802
+#define GL_TEXTURE_WRAP_T                                0x2803
+
+/* TextureTarget */
+/*      GL_TEXTURE_2D */
+#define GL_TEXTURE                                       0x1702
+
+#define GL_TEXTURE_CUBE_MAP                              0x8513
+#define GL_TEXTURE_BINDING_CUBE_MAP                      0x8514
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_X                   0x8515
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X                   0x8516
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y                   0x8517
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y                   0x8518
+#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z                   0x8519
+#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z                   0x851A
+#define GL_MAX_CUBE_MAP_TEXTURE_SIZE                     0x851C
+
+/* TextureUnit */
+#define GL_TEXTURE0                                      0x84C0
+#define GL_TEXTURE1                                      0x84C1
+#define GL_TEXTURE2                                      0x84C2
+#define GL_TEXTURE3                                      0x84C3
+#define GL_TEXTURE4                                      0x84C4
+#define GL_TEXTURE5                                      0x84C5
+#define GL_TEXTURE6                                      0x84C6
+#define GL_TEXTURE7                                      0x84C7
+#define GL_TEXTURE8                                      0x84C8
+#define GL_TEXTURE9                                      0x84C9
+#define GL_TEXTURE10                                     0x84CA
+#define GL_TEXTURE11                                     0x84CB
+#define GL_TEXTURE12                                     0x84CC
+#define GL_TEXTURE13                                     0x84CD
+#define GL_TEXTURE14                                     0x84CE
+#define GL_TEXTURE15                                     0x84CF
+#define GL_TEXTURE16                                     0x84D0
+#define GL_TEXTURE17                                     0x84D1
+#define GL_TEXTURE18                                     0x84D2
+#define GL_TEXTURE19                                     0x84D3
+#define GL_TEXTURE20                                     0x84D4
+#define GL_TEXTURE21                                     0x84D5
+#define GL_TEXTURE22                                     0x84D6
+#define GL_TEXTURE23                                     0x84D7
+#define GL_TEXTURE24                                     0x84D8
+#define GL_TEXTURE25                                     0x84D9
+#define GL_TEXTURE26                                     0x84DA
+#define GL_TEXTURE27                                     0x84DB
+#define GL_TEXTURE28                                     0x84DC
+#define GL_TEXTURE29                                     0x84DD
+#define GL_TEXTURE30                                     0x84DE
+#define GL_TEXTURE31                                     0x84DF
+#define GL_ACTIVE_TEXTURE                                0x84E0
+
+/* TextureWrapMode */
+#define GL_REPEAT                                        0x2901
+#define GL_CLAMP_TO_EDGE                                 0x812F
+#define GL_MIRRORED_REPEAT                               0x8370
+
+/* Uniform Types */
+#define GL_FLOAT_VEC2                                    0x8B50
+#define GL_FLOAT_VEC3                                    0x8B51
+#define GL_FLOAT_VEC4                                    0x8B52
+#define GL_INT_VEC2                                      0x8B53
+#define GL_INT_VEC3                                      0x8B54
+#define GL_INT_VEC4                                      0x8B55
+#define GL_BOOL                                          0x8B56
+#define GL_BOOL_VEC2                                     0x8B57
+#define GL_BOOL_VEC3                                     0x8B58
+#define GL_BOOL_VEC4                                     0x8B59
+#define GL_FLOAT_MAT2                                    0x8B5A
+#define GL_FLOAT_MAT3                                    0x8B5B
+#define GL_FLOAT_MAT4                                    0x8B5C
+#define GL_SAMPLER_2D                                    0x8B5E
+#define GL_SAMPLER_CUBE                                  0x8B60
+
+/* Vertex Arrays */
+#define GL_VERTEX_ATTRIB_ARRAY_ENABLED                   0x8622
+#define GL_VERTEX_ATTRIB_ARRAY_SIZE                      0x8623
+#define GL_VERTEX_ATTRIB_ARRAY_STRIDE                    0x8624
+#define GL_VERTEX_ATTRIB_ARRAY_TYPE                      0x8625
+#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED                0x886A
+#define GL_VERTEX_ATTRIB_ARRAY_POINTER                   0x8645
+#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING            0x889F
+
+/* Read Format */
+#define GL_IMPLEMENTATION_COLOR_READ_TYPE                0x8B9A
+#define GL_IMPLEMENTATION_COLOR_READ_FORMAT              0x8B9B
+
+/* Shader Source */
+#define GL_COMPILE_STATUS                                0x8B81
+#define GL_INFO_LOG_LENGTH                               0x8B84
+#define GL_SHADER_SOURCE_LENGTH                          0x8B88
+#define GL_SHADER_COMPILER                               0x8DFA
+
+/* Shader Binary */
+#define GL_SHADER_BINARY_FORMATS                         0x8DF8
+#define GL_NUM_SHADER_BINARY_FORMATS                     0x8DF9
+
+/* Shader Precision-Specified Types */
+#define GL_LOW_FLOAT                                     0x8DF0
+#define GL_MEDIUM_FLOAT                                  0x8DF1
+#define GL_HIGH_FLOAT                                    0x8DF2
+#define GL_LOW_INT                                       0x8DF3
+#define GL_MEDIUM_INT                                    0x8DF4
+#define GL_HIGH_INT                                      0x8DF5
+
+/* Framebuffer Object. */
+#define GL_FRAMEBUFFER                                   0x8D40
+#define GL_RENDERBUFFER                                  0x8D41
+
+#define GL_RGBA4                                         0x8056
+#define GL_RGB5_A1                                       0x8057
+#define GL_RGB565                                        0x8D62
+#define GL_DEPTH_COMPONENT16                             0x81A5
+#define GL_STENCIL_INDEX8                                0x8D48
+
+#define GL_RENDERBUFFER_WIDTH                            0x8D42
+#define GL_RENDERBUFFER_HEIGHT                           0x8D43
+#define GL_RENDERBUFFER_INTERNAL_FORMAT                  0x8D44
+#define GL_RENDERBUFFER_RED_SIZE                         0x8D50
+#define GL_RENDERBUFFER_GREEN_SIZE                       0x8D51
+#define GL_RENDERBUFFER_BLUE_SIZE                        0x8D52
+#define GL_RENDERBUFFER_ALPHA_SIZE                       0x8D53
+#define GL_RENDERBUFFER_DEPTH_SIZE                       0x8D54
+#define GL_RENDERBUFFER_STENCIL_SIZE                     0x8D55
+
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE            0x8CD0
+#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME            0x8CD1
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL          0x8CD2
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE  0x8CD3
+
+#define GL_COLOR_ATTACHMENT0                             0x8CE0
+#define GL_DEPTH_ATTACHMENT                              0x8D00
+#define GL_STENCIL_ATTACHMENT                            0x8D20
+
+#define GL_NONE                                          0
+
+#define GL_FRAMEBUFFER_COMPLETE                          0x8CD5
+#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT             0x8CD6
+#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT     0x8CD7
+#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS             0x8CD9
+#define GL_FRAMEBUFFER_UNSUPPORTED                       0x8CDD
+
+#define GL_FRAMEBUFFER_BINDING                           0x8CA6
+#define GL_RENDERBUFFER_BINDING                          0x8CA7
+#define GL_MAX_RENDERBUFFER_SIZE                         0x84E8
+
+#define GL_INVALID_FRAMEBUFFER_OPERATION                 0x0506
+
+/* OpenGL ES 3.0 */
+
+#define GL_READ_BUFFER                                   0x0C02
+#define GL_UNPACK_ROW_LENGTH                             0x0CF2
+#define GL_UNPACK_SKIP_ROWS                              0x0CF3
+#define GL_UNPACK_SKIP_PIXELS                            0x0CF4
+#define GL_PACK_ROW_LENGTH                               0x0D02
+#define GL_PACK_SKIP_ROWS                                0x0D03
+#define GL_PACK_SKIP_PIXELS                              0x0D04
+#define GL_COLOR                                         0x1800
+#define GL_DEPTH                                         0x1801
+#define GL_STENCIL                                       0x1802
+#define GL_RED                                           0x1903
+#define GL_RGB8                                          0x8051
+#define GL_RGBA8                                         0x8058
+#define GL_RGB10_A2                                      0x8059
+#define GL_TEXTURE_BINDING_3D                            0x806A
+#define GL_PACK_SKIP_IMAGES                              0x806B
+#define GL_PACK_IMAGE_HEIGHT                             0x806C
+#define GL_UNPACK_SKIP_IMAGES                            0x806D
+#define GL_UNPACK_IMAGE_HEIGHT                           0x806E
+#define GL_TEXTURE_3D                                    0x806F
+#define GL_TEXTURE_WRAP_R                                0x8072
+#define GL_MAX_3D_TEXTURE_SIZE                           0x8073
+#define GL_UNSIGNED_INT_2_10_10_10_REV                   0x8368
+#define GL_MAX_ELEMENTS_VERTICES                         0x80E8
+#define GL_MAX_ELEMENTS_INDICES                          0x80E9
+#define GL_TEXTURE_MIN_LOD                               0x813A
+#define GL_TEXTURE_MAX_LOD                               0x813B
+#define GL_TEXTURE_BASE_LEVEL                            0x813C
+#define GL_TEXTURE_MAX_LEVEL                             0x813D
+#define GL_MIN                                           0x8007
+#define GL_MAX                                           0x8008
+#define GL_DEPTH_COMPONENT24                             0x81A6
+#define GL_MAX_TEXTURE_LOD_BIAS                          0x84FD
+#define GL_TEXTURE_COMPARE_MODE                          0x884C
+#define GL_TEXTURE_COMPARE_FUNC                          0x884D
+#define GL_CURRENT_QUERY                                 0x8865
+#define GL_QUERY_RESULT                                  0x8866
+#define GL_QUERY_RESULT_AVAILABLE                        0x8867
+#define GL_BUFFER_MAPPED                                 0x88BC
+#define GL_BUFFER_MAP_POINTER                            0x88BD
+#define GL_STREAM_READ                                   0x88E1
+#define GL_STREAM_COPY                                   0x88E2
+#define GL_STATIC_READ                                   0x88E5
+#define GL_STATIC_COPY                                   0x88E6
+#define GL_DYNAMIC_READ                                  0x88E9
+#define GL_DYNAMIC_COPY                                  0x88EA
+#define GL_MAX_DRAW_BUFFERS                              0x8824
+#define GL_DRAW_BUFFER0                                  0x8825
+#define GL_DRAW_BUFFER1                                  0x8826
+#define GL_DRAW_BUFFER2                                  0x8827
+#define GL_DRAW_BUFFER3                                  0x8828
+#define GL_DRAW_BUFFER4                                  0x8829
+#define GL_DRAW_BUFFER5                                  0x882A
+#define GL_DRAW_BUFFER6                                  0x882B
+#define GL_DRAW_BUFFER7                                  0x882C
+#define GL_DRAW_BUFFER8                                  0x882D
+#define GL_DRAW_BUFFER9                                  0x882E
+#define GL_DRAW_BUFFER10                                 0x882F
+#define GL_DRAW_BUFFER11                                 0x8830
+#define GL_DRAW_BUFFER12                                 0x8831
+#define GL_DRAW_BUFFER13                                 0x8832
+#define GL_DRAW_BUFFER14                                 0x8833
+#define GL_DRAW_BUFFER15                                 0x8834
+#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS               0x8B49
+#define GL_MAX_VERTEX_UNIFORM_COMPONENTS                 0x8B4A
+#define GL_SAMPLER_3D                                    0x8B5F
+#define GL_SAMPLER_2D_SHADOW                             0x8B62
+#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT               0x8B8B
+#define GL_PIXEL_PACK_BUFFER                             0x88EB
+#define GL_PIXEL_UNPACK_BUFFER                           0x88EC
+#define GL_PIXEL_PACK_BUFFER_BINDING                     0x88ED
+#define GL_PIXEL_UNPACK_BUFFER_BINDING                   0x88EF
+#define GL_FLOAT_MAT2x3                                  0x8B65
+#define GL_FLOAT_MAT2x4                                  0x8B66
+#define GL_FLOAT_MAT3x2                                  0x8B67
+#define GL_FLOAT_MAT3x4                                  0x8B68
+#define GL_FLOAT_MAT4x2                                  0x8B69
+#define GL_FLOAT_MAT4x3                                  0x8B6A
+#define GL_SRGB                                          0x8C40
+#define GL_SRGB8                                         0x8C41
+#define GL_SRGB8_ALPHA8                                  0x8C43
+#define GL_COMPARE_REF_TO_TEXTURE                        0x884E
+#define GL_MAJOR_VERSION                                 0x821B
+#define GL_MINOR_VERSION                                 0x821C
+#define GL_NUM_EXTENSIONS                                0x821D
+#define GL_RGBA32F                                       0x8814
+#define GL_RGB32F                                        0x8815
+#define GL_RGBA16F                                       0x881A
+#define GL_RGB16F                                        0x881B
+#define GL_VERTEX_ATTRIB_ARRAY_INTEGER                   0x88FD
+#define GL_MAX_ARRAY_TEXTURE_LAYERS                      0x88FF
+#define GL_MIN_PROGRAM_TEXEL_OFFSET                      0x8904
+#define GL_MAX_PROGRAM_TEXEL_OFFSET                      0x8905
+#define GL_MAX_VARYING_COMPONENTS                        0x8B4B
+#define GL_TEXTURE_2D_ARRAY                              0x8C1A
+#define GL_TEXTURE_BINDING_2D_ARRAY                      0x8C1D
+#define GL_R11F_G11F_B10F                                0x8C3A
+#define GL_UNSIGNED_INT_10F_11F_11F_REV                  0x8C3B
+#define GL_RGB9_E5                                       0x8C3D
+#define GL_UNSIGNED_INT_5_9_9_9_REV                      0x8C3E
+#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH         0x8C76
+#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE                0x8C7F
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS    0x8C80
+#define GL_TRANSFORM_FEEDBACK_VARYINGS                   0x8C83
+#define GL_TRANSFORM_FEEDBACK_BUFFER_START               0x8C84
+#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE                0x8C85
+#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN         0x8C88
+#define GL_RASTERIZER_DISCARD                            0x8C89
+#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
+#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS       0x8C8B
+#define GL_INTERLEAVED_ATTRIBS                           0x8C8C
+#define GL_SEPARATE_ATTRIBS                              0x8C8D
+#define GL_TRANSFORM_FEEDBACK_BUFFER                     0x8C8E
+#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING             0x8C8F
+#define GL_RGBA32UI                                      0x8D70
+#define GL_RGB32UI                                       0x8D71
+#define GL_RGBA16UI                                      0x8D76
+#define GL_RGB16UI                                       0x8D77
+#define GL_RGBA8UI                                       0x8D7C
+#define GL_RGB8UI                                        0x8D7D
+#define GL_RGBA32I                                       0x8D82
+#define GL_RGB32I                                        0x8D83
+#define GL_RGBA16I                                       0x8D88
+#define GL_RGB16I                                        0x8D89
+#define GL_RGBA8I                                        0x8D8E
+#define GL_RGB8I                                         0x8D8F
+#define GL_RED_INTEGER                                   0x8D94
+#define GL_RGB_INTEGER                                   0x8D98
+#define GL_RGBA_INTEGER                                  0x8D99
+#define GL_SAMPLER_2D_ARRAY                              0x8DC1
+#define GL_SAMPLER_2D_ARRAY_SHADOW                       0x8DC4
+#define GL_SAMPLER_CUBE_SHADOW                           0x8DC5
+#define GL_UNSIGNED_INT_VEC2                             0x8DC6
+#define GL_UNSIGNED_INT_VEC3                             0x8DC7
+#define GL_UNSIGNED_INT_VEC4                             0x8DC8
+#define GL_INT_SAMPLER_2D                                0x8DCA
+#define GL_INT_SAMPLER_3D                                0x8DCB
+#define GL_INT_SAMPLER_CUBE                              0x8DCC
+#define GL_INT_SAMPLER_2D_ARRAY                          0x8DCF
+#define GL_UNSIGNED_INT_SAMPLER_2D                       0x8DD2
+#define GL_UNSIGNED_INT_SAMPLER_3D                       0x8DD3
+#define GL_UNSIGNED_INT_SAMPLER_CUBE                     0x8DD4
+#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY                 0x8DD7
+#define GL_BUFFER_ACCESS_FLAGS                           0x911F
+#define GL_BUFFER_MAP_LENGTH                             0x9120
+#define GL_BUFFER_MAP_OFFSET                             0x9121
+#define GL_DEPTH_COMPONENT32F                            0x8CAC
+#define GL_DEPTH32F_STENCIL8                             0x8CAD
+#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV                0x8DAD
+#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING         0x8210
+#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE         0x8211
+#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE               0x8212
+#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE             0x8213
+#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE              0x8214
+#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE             0x8215
+#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE             0x8216
+#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE           0x8217
+#define GL_FRAMEBUFFER_DEFAULT                           0x8218
+#define GL_FRAMEBUFFER_UNDEFINED                         0x8219
+#define GL_DEPTH_STENCIL_ATTACHMENT                      0x821A
+#define GL_DEPTH_STENCIL                                 0x84F9
+#define GL_UNSIGNED_INT_24_8                             0x84FA
+#define GL_DEPTH24_STENCIL8                              0x88F0
+#define GL_UNSIGNED_NORMALIZED                           0x8C17
+#define GL_DRAW_FRAMEBUFFER_BINDING                      GL_FRAMEBUFFER_BINDING
+#define GL_READ_FRAMEBUFFER                              0x8CA8
+#define GL_DRAW_FRAMEBUFFER                              0x8CA9
+#define GL_READ_FRAMEBUFFER_BINDING                      0x8CAA
+#define GL_RENDERBUFFER_SAMPLES                          0x8CAB
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER          0x8CD4
+#define GL_MAX_COLOR_ATTACHMENTS                         0x8CDF
+#define GL_COLOR_ATTACHMENT1                             0x8CE1
+#define GL_COLOR_ATTACHMENT2                             0x8CE2
+#define GL_COLOR_ATTACHMENT3                             0x8CE3
+#define GL_COLOR_ATTACHMENT4                             0x8CE4
+#define GL_COLOR_ATTACHMENT5                             0x8CE5
+#define GL_COLOR_ATTACHMENT6                             0x8CE6
+#define GL_COLOR_ATTACHMENT7                             0x8CE7
+#define GL_COLOR_ATTACHMENT8                             0x8CE8
+#define GL_COLOR_ATTACHMENT9                             0x8CE9
+#define GL_COLOR_ATTACHMENT10                            0x8CEA
+#define GL_COLOR_ATTACHMENT11                            0x8CEB
+#define GL_COLOR_ATTACHMENT12                            0x8CEC
+#define GL_COLOR_ATTACHMENT13                            0x8CED
+#define GL_COLOR_ATTACHMENT14                            0x8CEE
+#define GL_COLOR_ATTACHMENT15                            0x8CEF
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE            0x8D56
+#define GL_MAX_SAMPLES                                   0x8D57
+#define GL_HALF_FLOAT                                    0x140B
+#define GL_MAP_READ_BIT                                  0x0001
+#define GL_MAP_WRITE_BIT                                 0x0002
+#define GL_MAP_INVALIDATE_RANGE_BIT                      0x0004
+#define GL_MAP_INVALIDATE_BUFFER_BIT                     0x0008
+#define GL_MAP_FLUSH_EXPLICIT_BIT                        0x0010
+#define GL_MAP_UNSYNCHRONIZED_BIT                        0x0020
+#define GL_RG                                            0x8227
+#define GL_RG_INTEGER                                    0x8228
+#define GL_R8                                            0x8229
+#define GL_RG8                                           0x822B
+#define GL_R16F                                          0x822D
+#define GL_R32F                                          0x822E
+#define GL_RG16F                                         0x822F
+#define GL_RG32F                                         0x8230
+#define GL_R8I                                           0x8231
+#define GL_R8UI                                          0x8232
+#define GL_R16I                                          0x8233
+#define GL_R16UI                                         0x8234
+#define GL_R32I                                          0x8235
+#define GL_R32UI                                         0x8236
+#define GL_RG8I                                          0x8237
+#define GL_RG8UI                                         0x8238
+#define GL_RG16I                                         0x8239
+#define GL_RG16UI                                        0x823A
+#define GL_RG32I                                         0x823B
+#define GL_RG32UI                                        0x823C
+#define GL_VERTEX_ARRAY_BINDING                          0x85B5
+#define GL_R8_SNORM                                      0x8F94
+#define GL_RG8_SNORM                                     0x8F95
+#define GL_RGB8_SNORM                                    0x8F96
+#define GL_RGBA8_SNORM                                   0x8F97
+#define GL_SIGNED_NORMALIZED                             0x8F9C
+#define GL_PRIMITIVE_RESTART_FIXED_INDEX                 0x8D69
+#define GL_COPY_READ_BUFFER                              0x8F36
+#define GL_COPY_WRITE_BUFFER                             0x8F37
+#define GL_COPY_READ_BUFFER_BINDING                      GL_COPY_READ_BUFFER
+#define GL_COPY_WRITE_BUFFER_BINDING                     GL_COPY_WRITE_BUFFER
+#define GL_UNIFORM_BUFFER                                0x8A11
+#define GL_UNIFORM_BUFFER_BINDING                        0x8A28
+#define GL_UNIFORM_BUFFER_START                          0x8A29
+#define GL_UNIFORM_BUFFER_SIZE                           0x8A2A
+#define GL_MAX_VERTEX_UNIFORM_BLOCKS                     0x8A2B
+#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS                   0x8A2D
+#define GL_MAX_COMBINED_UNIFORM_BLOCKS                   0x8A2E
+#define GL_MAX_UNIFORM_BUFFER_BINDINGS                   0x8A2F
+#define GL_MAX_UNIFORM_BLOCK_SIZE                        0x8A30
+#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS        0x8A31
+#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS      0x8A33
+#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT               0x8A34
+#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH          0x8A35
+#define GL_ACTIVE_UNIFORM_BLOCKS                         0x8A36
+#define GL_UNIFORM_TYPE                                  0x8A37
+#define GL_UNIFORM_SIZE                                  0x8A38
+#define GL_UNIFORM_NAME_LENGTH                           0x8A39
+#define GL_UNIFORM_BLOCK_INDEX                           0x8A3A
+#define GL_UNIFORM_OFFSET                                0x8A3B
+#define GL_UNIFORM_ARRAY_STRIDE                          0x8A3C
+#define GL_UNIFORM_MATRIX_STRIDE                         0x8A3D
+#define GL_UNIFORM_IS_ROW_MAJOR                          0x8A3E
+#define GL_UNIFORM_BLOCK_BINDING                         0x8A3F
+#define GL_UNIFORM_BLOCK_DATA_SIZE                       0x8A40
+#define GL_UNIFORM_BLOCK_NAME_LENGTH                     0x8A41
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS                 0x8A42
+#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES          0x8A43
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER     0x8A44
+#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER   0x8A46
+#define GL_INVALID_INDEX                                 0xFFFFFFFFu
+#define GL_MAX_VERTEX_OUTPUT_COMPONENTS                  0x9122
+#define GL_MAX_FRAGMENT_INPUT_COMPONENTS                 0x9125
+#define GL_MAX_SERVER_WAIT_TIMEOUT                       0x9111
+#define GL_OBJECT_TYPE                                   0x9112
+#define GL_SYNC_CONDITION                                0x9113
+#define GL_SYNC_STATUS                                   0x9114
+#define GL_SYNC_FLAGS                                    0x9115
+#define GL_SYNC_FENCE                                    0x9116
+#define GL_SYNC_GPU_COMMANDS_COMPLETE                    0x9117
+#define GL_UNSIGNALED                                    0x9118
+#define GL_SIGNALED                                      0x9119
+#define GL_ALREADY_SIGNALED                              0x911A
+#define GL_TIMEOUT_EXPIRED                               0x911B
+#define GL_CONDITION_SATISFIED                           0x911C
+#define GL_WAIT_FAILED                                   0x911D
+#define GL_SYNC_FLUSH_COMMANDS_BIT                       0x00000001
+#define GL_TIMEOUT_IGNORED                               0xFFFFFFFFFFFFFFFFull
+#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR                   0x88FE
+#define GL_ANY_SAMPLES_PASSED                            0x8C2F
+#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE               0x8D6A
+#define GL_SAMPLER_BINDING                               0x8919
+#define GL_RGB10_A2UI                                    0x906F
+#define GL_TEXTURE_SWIZZLE_R                             0x8E42
+#define GL_TEXTURE_SWIZZLE_G                             0x8E43
+#define GL_TEXTURE_SWIZZLE_B                             0x8E44
+#define GL_TEXTURE_SWIZZLE_A                             0x8E45
+#define GL_GREEN                                         0x1904
+#define GL_BLUE                                          0x1905
+#define GL_INT_2_10_10_10_REV                            0x8D9F
+#define GL_TRANSFORM_FEEDBACK                            0x8E22
+#define GL_TRANSFORM_FEEDBACK_PAUSED                     0x8E23
+#define GL_TRANSFORM_FEEDBACK_ACTIVE                     0x8E24
+#define GL_TRANSFORM_FEEDBACK_BINDING                    0x8E25
+#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT               0x8257
+#define GL_PROGRAM_BINARY_LENGTH                         0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS                    0x87FE
+#define GL_PROGRAM_BINARY_FORMATS                        0x87FF
+#define GL_COMPRESSED_R11_EAC                            0x9270
+#define GL_COMPRESSED_SIGNED_R11_EAC                     0x9271
+#define GL_COMPRESSED_RG11_EAC                           0x9272
+#define GL_COMPRESSED_SIGNED_RG11_EAC                    0x9273
+#define GL_COMPRESSED_RGB8_ETC2                          0x9274
+#define GL_COMPRESSED_SRGB8_ETC2                         0x9275
+#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2      0x9276
+#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2     0x9277
+#define GL_COMPRESSED_RGBA8_ETC2_EAC                     0x9278
+#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC              0x9279
+#define GL_TEXTURE_IMMUTABLE_FORMAT                      0x912F
+#define GL_MAX_ELEMENT_INDEX                             0x8D6B
+#define GL_NUM_SAMPLE_COUNTS                             0x9380
+#define GL_TEXTURE_IMMUTABLE_LEVELS                      0x8D63
+
+/*------------------------------------------------------------------------*
+ * EXT extension tokens
+ *------------------------------------------------------------------------*/
+
+/* GL_EXT_blend_minmax */
+#ifndef GL_EXT_blend_minmax
+#define GL_MIN_EXT                                              0x8007
+#define GL_MAX_EXT                                              0x8008
+#endif
+
+/* GL_EXT_discard_framebuffer */
+#ifndef GL_EXT_discard_framebuffer
+#define GL_COLOR_EXT                                            0x1800
+#define GL_DEPTH_EXT                                            0x1801
+#define GL_STENCIL_EXT                                          0x1802
+#endif
+
+/* GL_EXT_multi_draw_arrays */
+/* No new tokens introduced by this extension. */
+
+/* GL_EXT_read_format_bgra */
+#ifndef GL_EXT_read_format_bgra
+#define GL_BGRA_EXT                                             0x80E1
+#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT                       0x8365
+#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT                       0x8366
+#endif
+
+/* GL_EXT_texture_filter_anisotropic */
+#ifndef GL_EXT_texture_filter_anisotropic
+#define GL_TEXTURE_MAX_ANISOTROPY_EXT                           0x84FE
+#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT                       0x84FF
+#endif
+
+/* GL_EXT_texture_format_BGRA8888 */
+#ifndef GL_EXT_texture_format_BGRA8888
+#define GL_BGRA_EXT                                             0x80E1
+#endif
+
+/* GL_EXT_texture_type_2_10_10_10_REV */
+#ifndef GL_EXT_texture_type_2_10_10_10_REV
+#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT                      0x8368
+#endif
+
+/* GL_OES_get_program_binary */
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES                            0x8741
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES                       0x87FE
+#define GL_PROGRAM_BINARY_FORMATS_OES                           0x87FF
+#endif
+
+
+#endif // __DALI_INTERNAL_GL_DEFINES_H__
diff --git a/dali/integration-api/gl-sync-abstraction.h b/dali/integration-api/gl-sync-abstraction.h
new file mode 100644 (file)
index 0000000..a06cf8b
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__
+#define __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+namespace Integration
+{
+
+/**
+ * This abstraction defines an API for syncing CPU with GPU.
+ * A typical use case is to determine when GL draw calls have finished drawing
+ * to a framebuffer.
+ */
+class GlSyncAbstraction
+{
+protected:
+  /**
+   * Virtual protected destructor, no deletion through this interface
+   */
+  virtual ~GlSyncAbstraction() {}
+
+public:
+
+  class SyncObject
+  {
+  protected:
+    /**
+     * Virtual protected destructor, no deletion through this interface. This prevents
+     * Core from deleting SyncObjects - only Adaptor implementation is able to delete
+     * them.
+     */
+    virtual ~SyncObject() {}
+
+  public:
+
+    /**
+     * Determine if the synchronisation object has been signalled.
+     * @return false if the sync object has not been signalled, true if it has been signalled (and
+     * can now be destroyed)
+     */
+    virtual bool IsSynced() = 0;
+  };
+
+  /**
+   * Create a synchronisation object based on the resource id, typically that of
+   * a framebuffer texture. It can then be polled using the same resource id.
+   * @return A pointer to an opaque sync object
+   */
+  virtual SyncObject* CreateSyncObject() = 0;
+
+  /**
+   * Destroy the synchronisation object.
+   * @param[in] syncObject The sync object to destroy
+   */
+  virtual void DestroySyncObject(SyncObject* syncObject) = 0;
+};
+
+} // namespace Integration
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_GL_SYNC_ABSTRACTION_H__
diff --git a/dali/integration-api/image-data.cpp b/dali/integration-api/image-data.cpp
new file mode 100644 (file)
index 0000000..a0d772a
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/image-data.h>
+
+// INTERNAL INCLUDES
+
+// EXTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+ImageData::ImageData( const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ) :
+  mData( new uint8_t[numBytes] ),
+  dataSize( numBytes ),
+  imageWidth( imageWidth ),
+  imageHeight( imageHeight ),
+  pixelFormat( pixelFormat ),
+  mAlphaChannelUsed( ALPHA_USAGE_UNDETERMINED )
+{
+  DALI_ASSERT_DEBUG( numBytes > 0U && imageWidth > 0U && imageHeight > 0U );
+}
+
+ImageData::ImageData( uint8_t * const imageBuffer, const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat ) :
+  mData( imageBuffer ),
+  dataSize( numBytes ),
+  imageWidth( imageWidth ),
+  imageHeight( imageHeight ),
+  pixelFormat( pixelFormat ),
+  mAlphaChannelUsed( ALPHA_USAGE_UNDETERMINED )
+{
+  DALI_ASSERT_DEBUG( imageBuffer != 0 && numBytes > 0U && imageWidth > 0U && imageHeight > 0U );
+}
+
+ImageData::~ImageData()
+{
+  delete[] mData;
+}
+
+ImageDataPtr ImageData::New(  const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat )
+{
+  DALI_ASSERT_DEBUG( numBytes.bufferSize > 0 && "Zero allocations are pointless if also harmless."  );
+  DALI_ASSERT_DEBUG( imageWidth > 0 && imageHeight > 0 && "Zero dimensioned images are pointless if also harmless." );
+  return ImageDataPtr( new ImageData( numBytes, imageWidth, imageHeight, pixelFormat ) );
+}
+
+ImageDataPtr ImageData::New( uint8_t * const imageBuffer, const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat )
+{
+  DALI_ASSERT_DEBUG( numBytes.bufferSize > 0 && "Zero-length buffers are pointless if also harmless."  );
+  DALI_ASSERT_DEBUG( imageWidth > 0 && imageHeight > 0 && "Zero dimensioned images are pointless if also harmless." );
+  return ImageDataPtr( new ImageData( imageBuffer, numBytes, imageWidth, imageHeight, pixelFormat ) );
+}
+
+ImageDataPtr NewBitmapImageData( unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat )
+{
+  DALI_ASSERT_DEBUG( pixelFormat <= Pixel::BGRA8888 && "Pixel format must be an addressable one." );
+  const size_t numBytes = imageWidth * imageHeight * Pixel::GetBytesPerPixel( pixelFormat );
+
+  return ImageData::New( BufferSize(numBytes), imageWidth, imageHeight, pixelFormat );
+}
+
+} //namespace Integration
+
+} //namespace Dali
+
diff --git a/dali/integration-api/image-data.h b/dali/integration-api/image-data.h
new file mode 100644 (file)
index 0000000..58c9d80
--- /dev/null
@@ -0,0 +1,197 @@
+#ifndef __DALI_INTEGRATION_IMAGE_DATA_H__
+#define __DALI_INTEGRATION_IMAGE_DATA_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h> // For DALI_LOG_OBJECT_STRING_DECLARATION
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/images/pixel.h>
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+class ImageData;
+typedef IntrusivePtr<ImageData> ImageDataPtr;
+
+typedef uint8_t PixelBuffer;
+
+/**
+ * Used to avoid accidentally mixing the order of parameters where some are uint
+ * dimensions and one is a buffer size.
+ **/
+class BufferSize
+{
+public:
+  explicit BufferSize(size_t size) : bufferSize( size )
+  { }
+  operator size_t() const { return bufferSize; }
+  const size_t bufferSize;
+};
+
+/**
+ * @brief A simple container for image data.
+ *
+ * Just a pointer to a buffer and some minimal metadata. It always owns the
+ * buffer of image data that it points to until it is destroyed or the buffer
+ * is released with ReleaseImageBuffer().
+ *
+ * The width and height stored are the logical image values. Compressed formats
+ * such as ETC group pixels into blocks (ETC = 4*4) and these logical width and
+ * height may indicate, for example for ETC, that 1 to 3 pixels in the rightmost
+ * column of blocks or bottom row are ignored for rendering.
+ * For simple uncompressed images, the buffer is exactly width * height *
+ * bytes-per-pixel in size with no spare bytes at right or bottom edge.
+ */
+class DALI_IMPORT_API ImageData : public Dali::RefObject
+{
+public:
+  /**
+   * @brief Three values for the information about the alpha values in the
+   * pixels.
+   *
+   * Alpha in pixels with the channel can be undetermined, it can be all-ones,
+   * or it can have at least one pixel that is translucent with an alpha < 1.0.
+   **/
+  enum AlphaUsage
+  {
+    /** Alpha not yet been tested.*/
+    ALPHA_USAGE_UNDETERMINED,
+    /** Alpha == 1.0 in every pixel.*/
+    ALPHA_USAGE_ALL_OPAQUE,
+    /** Alpha < 1.0 in at least one pixel.*/
+    ALPHA_USAGE_SOME_TRANSLUCENT
+  };
+
+private:
+
+  /**
+   * Construct an instance and allocate a buffer owned by it.
+   * @param[in] numBytes The number of bytes to allocate to hold the image data.
+   * @param[in] imageWidth The width in pixels of the image.
+   * @param[in] imageHeight The height in pixels of the image.
+   * @param[in] pixelFormat The format of the image data in the buffer.
+   */
+  ImageData( const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat );
+
+  /**
+   * Construct an instance and have it take ownership of the buffer passed in.
+   * @param[in] imageBuffer A buffer of pixel data that should have been allocated using <code>new uint8_t[]</code>.
+   * @param[in] numBytes The number of bytes in the buffer pointed to by imageBuffer.
+   * @param[in] imageWidth The width in pixels of the image.
+   * @param[in] imageHeight The height in pixels of the image.
+   * @param[in] pixelFormat The format of the image data in the buffer.
+   */
+  ImageData( uint8_t * const imageBuffer, const size_t numBytes, const unsigned imageWidth, const unsigned imageHeight, const Pixel::Format pixelFormat );
+
+  ~ImageData();
+
+public:
+
+  /** Allocate and initialize a fresh ImageData object pointing at a new buffer,
+   * returning a smart pointer owning it.
+   * @note Clients can alternatively use the helper function NewBitmapImageData() to
+   * calculate the buffer size from other parameters if the image data represents
+   * a bitmap (a 2d grid of addressable pixels).
+   * @param[in] numBytes The number of bytes to allocate to hold the image data.
+   * @param[in] imageWidth The width in pixels of the image.
+   * @param[in] imageHeight The height in pixels of the image.
+   * @param[in] pixelFormat The format of the image data in the buffer.
+   **/
+  static ImageDataPtr New( const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat );
+
+  /** Allocate and initialise a fresh ImageData object, taking ownership of the
+   * buffer passed in.
+   * @param[in] imageBuffer A block of memory allocated with
+   * <code>new uint8_t[]</code>. <em>This is owned by the new ImageData instance
+   * on successful return and should be forgotten by the caller</em>.
+   * @param[in] numBytes The number of bytes in the buffer pointed to by imageBuffer.
+   * @param[in] imageWidth The width in pixels of the image.
+   * @param[in] imageHeight The height in pixels of the image.
+   * @param[in] pixelFormat The format of the image data in the buffer.
+   **/
+  static ImageDataPtr New( uint8_t * const imageBuffer, const BufferSize numBytes, unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat );
+
+  /** Access the buffer of image data. */
+  const uint8_t * GetBuffer() const { return mData; }
+
+  /** Access the buffer of image data. */
+  uint8_t * GetBuffer() { return mData; }
+
+  /**
+   * Pass ownership of the buffer of pixel-level data that this instance
+   * currently owns to the caller, and forget about the buffer here as a
+   * side effect.
+   * @returns A pointer to the underlying buffer of pixel-level image data.
+   * The caller takes ownership of the buffer and is responsible for calling
+   * delete[] on it eventually.
+   **/
+  uint8_t * ReleaseImageBuffer() { uint8_t * const data = mData; mData = 0; return data; }
+
+  /**
+   * @brief Get whether the alpha channel in the pixels is used.
+   */
+  AlphaUsage GetAlphaUsage() const { return mAlphaChannelUsed; }
+
+  /**
+   * @brief Set whether the alpha channel in the pixels is used.
+   */
+  void SetAlphaUsed( const bool alphaUsed ) { mAlphaChannelUsed = alphaUsed ? ALPHA_USAGE_SOME_TRANSLUCENT : ALPHA_USAGE_ALL_OPAQUE; }
+
+private:
+
+  ImageData(const ImageData& other);  ///< defined private to prevent use
+  ImageData& operator = (const ImageData& other); ///< defined private to prevent use
+
+  /** Pointer to the buffer of image data. */
+  uint8_t*     mData;
+
+public:
+  const size_t        dataSize;   ///< Number of bytes in buffer pointed at by mData
+  const uint16_t      imageWidth;  ///< Image logical width in pixels
+  const uint16_t      imageHeight; ///< Image logical height in pixels
+  const Pixel::Format pixelFormat; ///< Pixel format
+
+private:
+  AlphaUsage mAlphaChannelUsed;
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+/**
+ * A convenience function for creating the common case of an uncompressed image
+ * having width * height pixels in the buffer.
+ * @param[in] imageWidth The width in pixels of the image.
+ * @param[in] imageHeight The height in pixels of the image.
+ * @param[in] pixelFormat The format of the image data in the buffer.
+ */
+DALI_IMPORT_API ImageDataPtr NewBitmapImageData( unsigned imageWidth, unsigned imageHeight, Pixel::Format pixelFormat );
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_IMAGE_DATA_H__
diff --git a/dali/integration-api/input-options.cpp b/dali/integration-api/input-options.cpp
new file mode 100644 (file)
index 0000000..e05619f
--- /dev/null
@@ -0,0 +1,108 @@
+#include "input-options.h"
+
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+
+using Dali::Internal::GestureEventProcessor;
+using Dali::Internal::ThreadLocalStorage;
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+void SetPanGesturePredictionMode( int mode )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGesturePredictionMode(mode);
+}
+
+void SetPanGesturePredictionAmount( unsigned int amount )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGesturePredictionAmount(amount);
+}
+
+void SetPanGestureMaximumPredictionAmount( unsigned int amount )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureMaximumPredictionAmount(amount);
+}
+
+void SetPanGestureMinimumPredictionAmount( unsigned int amount )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureMinimumPredictionAmount(amount);
+}
+
+void SetPanGesturePredictionAmountAdjustment( unsigned int amount )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGesturePredictionAmountAdjustment(amount);
+}
+
+void SetPanGestureSmoothingMode( int mode )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureSmoothingMode(mode);
+}
+
+void SetPanGestureSmoothingAmount( float amount )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureSmoothingAmount(amount);
+}
+
+void SetPanGestureUseActualTimes( bool value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureUseActualTimes( value );
+}
+
+void SetPanGestureInterpolationTimeRange( int value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureInterpolationTimeRange( value );
+}
+
+void SetPanGestureScalarOnlyPredictionEnabled( bool value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureScalarOnlyPredictionEnabled( value );
+}
+
+void SetPanGestureTwoPointPredictionEnabled( bool value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureTwoPointPredictionEnabled( value );
+}
+
+void SetPanGestureTwoPointInterpolatePastTime( int value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureTwoPointInterpolatePastTime( value );
+}
+
+void SetPanGestureTwoPointVelocityBias( float value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureTwoPointVelocityBias( value );
+}
+
+void SetPanGestureTwoPointAccelerationBias( float value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureTwoPointAccelerationBias( value );
+}
+
+void SetPanGestureMultitapSmoothingRange( int value )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+  eventProcessor.SetPanGestureMultitapSmoothingRange( value );
+}
+
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/input-options.h b/dali/integration-api/input-options.h
new file mode 100644 (file)
index 0000000..1e58d18
--- /dev/null
@@ -0,0 +1,151 @@
+#ifndef __DALI_INTEGRATION_INPUT_OPTIONS_H__
+#define __DALI_INTEGRATION_INPUT_OPTIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * @brief Called by adaptor to set the pan gesture prediction mode from
+ * an environment variable
+ *
+ * @pre Should be called after Core creation.
+ * @param mode The pan gesture prediction mode.
+ */
+DALI_IMPORT_API void SetPanGesturePredictionMode( int mode );
+
+/**
+ * @brief Called by adaptor to set the prediction amount of the pan gesture
+ * from an environment variable
+ *
+ * @param[in] amount The prediction amount in milliseconds
+ */
+DALI_IMPORT_API void SetPanGesturePredictionAmount(unsigned int amount);
+
+/**
+ * @brief Sets the upper bound of the prediction amount for clamping
+ * from an environment variable
+ *
+ * @param[in] amount The prediction amount in milliseconds
+ */
+DALI_IMPORT_API void SetPanGestureMaximumPredictionAmount( unsigned int amount );
+
+/**
+ * @brief Sets the lower bound of the prediction amount for clamping
+ * from an environment variable
+ *
+ * @param[in] amount The prediction amount in milliseconds
+ */
+DALI_IMPORT_API void SetPanGestureMinimumPredictionAmount( unsigned int amount );
+
+/**
+ * @brief Sets the prediction amount to adjust when the pan velocity is changed
+ * from an environment variable. If the pan velocity is accelerating, the prediction
+ * amount will be increased by the specified amount until it reaches the upper bound.
+ * If the pan velocity is decelerating, the prediction amount will be decreased by
+ * the specified amount until it reaches the lower bound.
+ *
+ * @param[in] amount The prediction amount in milliseconds
+ */
+DALI_IMPORT_API void SetPanGesturePredictionAmountAdjustment( unsigned int amount );
+
+/**
+ * @brief Called to set how pan gestures smooth input
+ *
+ * @param[in] mode The smoothing mode to use
+ */
+DALI_IMPORT_API void SetPanGestureSmoothingMode( int mode );
+
+/**
+ * @brief Sets the smoothing amount of the pan gesture
+ *
+ * @param[in] amount The smoothing amount [0.0f,1.0f] - 0.0f would be no smoothing, 1.0f maximum smoothing
+ */
+DALI_IMPORT_API void SetPanGestureSmoothingAmount( float amount );
+
+/**
+ * @brief Sets whether to use actual times of the real gesture and frames or not.
+ *
+ * @param[in] value True = use actual times, False = use perfect values
+ */
+DALI_IMPORT_API void SetPanGestureUseActualTimes( bool value );
+
+/**
+ * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
+ *
+ * @param[in] value Time range in ms
+ */
+DALI_IMPORT_API void SetPanGestureInterpolationTimeRange( int value );
+
+/**
+ * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
+ *
+ * @param[in] value True = use scalar prediction only
+ */
+DALI_IMPORT_API void SetPanGestureScalarOnlyPredictionEnabled( bool value );
+
+/**
+ * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
+ *
+ * @param[in] value True = use two point prediction
+ */
+DALI_IMPORT_API void SetPanGestureTwoPointPredictionEnabled( bool value );
+
+/**
+ * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
+ *
+ * @param[in] value Time in past in ms
+ */
+DALI_IMPORT_API void SetPanGestureTwoPointInterpolatePastTime( int value );
+
+/**
+ * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
+ *
+ * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+ */
+DALI_IMPORT_API void SetPanGestureTwoPointVelocityBias( float value );
+
+/**
+ * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
+ *
+ * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+ */
+DALI_IMPORT_API void SetPanGestureTwoPointAccelerationBias( float value );
+
+/**
+ * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
+ *
+ * @param[in] value Time in past in ms
+ */
+DALI_IMPORT_API void SetPanGestureMultitapSmoothingRange( int value );
+
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_INPUT_OPTIONS_H__
diff --git a/dali/integration-api/lockless-buffer.cpp b/dali/integration-api/lockless-buffer.cpp
new file mode 100644 (file)
index 0000000..b704dbc
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "lockless-buffer.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+LocklessBuffer::LocklessBuffer( size_t size )
+: mState( R0W1 ),
+  mSize( size )
+{
+  // allocate memory to speed up operation
+  mBuffer[0] = new unsigned char[size];
+  mBuffer[1] = new unsigned char[size];
+
+  memset (mBuffer[0], 0, size );
+  memset (mBuffer[1], 0, size );
+}
+
+LocklessBuffer::~LocklessBuffer()
+{
+  delete[] mBuffer[0];
+  delete[] mBuffer[1];
+}
+
+void LocklessBuffer::Write( const unsigned char *src, size_t size )
+{
+  DALI_ASSERT_ALWAYS( size <= mSize );
+
+  // set WRITING bit
+  BufferState currentState( __sync_fetch_and_or( &mState, WRITING ) );
+  DALI_ASSERT_DEBUG( !(currentState & WRITING_MASK) ); // WRITING bit should never be set when we get here
+
+  // copy data to current write buffer, negate state to get actual index (recap: R0W1 = 0, R1W0 = 1)
+  const unsigned int index = (currentState & WRITE_BUFFER_MASK);
+  memcpy( mBuffer[index], src, size );
+
+  // unset WRITING bit, set UPDATED bit
+  BufferState checkState = __sync_val_compare_and_swap( &mState,
+                                                        static_cast<BufferState>(currentState | WRITING),
+                                                        static_cast<BufferState>(index | UPDATED) );
+
+  DALI_ASSERT_DEBUG( checkState & WRITING );
+  (void)checkState; // Avoid unused variable warning
+}
+
+const unsigned char* LocklessBuffer::Read()
+{
+  // current state (only to avoid multiple memory reads with volatile variable)
+  BufferState currentState( mState );
+  BufferState currentWriteBuf( static_cast<BufferState>( currentState & WRITE_BUFFER_MASK ) );
+
+  if( currentState & UPDATED_MASK )
+  {
+    // Try to swap buffers.
+    // This will set mState to 1 if readbuffer 0 was updated, 0 if readbuffer 1 was updated and fail if WRITING is set
+    if( __sync_bool_compare_and_swap( &mState,
+                                      static_cast<BufferState>(currentWriteBuf | UPDATED),
+                                      static_cast<BufferState>(!currentWriteBuf) )  )
+    {
+      // swap successful
+      return mBuffer[currentWriteBuf];
+    }
+  }
+
+  // UPDATE bit wasn't set or WRITING bit was set in other thread
+  // swap failed, read from current readbuffer
+  return mBuffer[!currentWriteBuf];
+}
+
+unsigned int LocklessBuffer::GetSize() const
+{
+  return static_cast<unsigned int>(mSize);
+}
+
+} // Internal
+
+} // Dali
diff --git a/dali/integration-api/lockless-buffer.h b/dali/integration-api/lockless-buffer.h
new file mode 100644 (file)
index 0000000..dfb9a90
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef __DALI_INTEGRATION_LOCKLESS_BUFFER_H__
+#define __DALI_INTEGRATION_LOCKLESS_BUFFER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <cstring>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * The LocklessBuffer class implements double buffering eligible for multi-(two) threaded use,
+ * where it's possible to read from one thread and write from another
+ * without requiring a mutex lock to avoid performance hit.
+ * It's intended to be used for reading bitmap data in render thread
+ * while still possible to write data in another thread.
+ *
+ * Ideally Write() and Read() calls should be alternating, otherwise written data might be thrown away.
+ *
+ * The buffers are swapped in the reading thread, just before reading begins.
+ * In case the other thread is writing at that moment, buffers are not swapped and previously available data is read.
+ * Similarly if Write() is called before a Read() has finished the previous write buffer is overwritten.
+ */
+class DALI_IMPORT_API LocklessBuffer
+{
+
+public:
+  /**
+   * Constructor.
+   * @param[in] size The size of buffers in bytes.
+   */
+  LocklessBuffer( size_t size );
+
+  /**
+   * Destructor.
+   */
+  ~LocklessBuffer();
+
+  /**
+   * Write data to buffer.
+   * @param[in] src data source
+   * @param[in] size size of data in bytes
+   */
+  void Write( const unsigned char *src, size_t size );
+
+  /**
+   * Try to swap buffers and read data.
+   * @note returned value only valid until Read() is called again or object is destroyed
+   * @return current read buffer contents
+   */
+  const unsigned char* Read();
+
+  /**
+   * @return the buffer size in bytes
+   */
+  unsigned int GetSize() const;
+
+private:
+  /**
+   * Atomically set state.
+   * We're always writing to one buffer and reading from the other.
+   * Write() sets WRITING bit when started and unsets it when finished.
+   */
+  enum BufferState
+  {
+    R0W1    = 0, ///< Read from buffer 0 write to buffer 1
+    R1W0    = 1, ///< Read from buffer 1 write to buffer 0
+    WRITING = 2, ///< Currently writing to buffer
+    UPDATED = 4, ///< Swapping buffer required; there is new data available
+    WRITE_BUFFER_MASK = 1, ///< indicates which buffer to write to
+    WRITING_MASK      = 2, ///< indicates whether currently writing
+    UPDATED_MASK      = 4  ///< indicates whether new data is available
+  };
+
+private:
+  LocklessBuffer(); ///< undefined default constructor, need to give size on construction
+  LocklessBuffer( const LocklessBuffer& );            ///< undefined copy constructor
+  LocklessBuffer& operator=( const LocklessBuffer& ); ///< undefined assignment operator
+
+private:
+  unsigned char* mBuffer[2];     ///< bitmap buffers
+  BufferState volatile mState;   ///< readbuffer number and whether we're currently writing into writebuffer or not
+  size_t mSize;                  ///< size of buffers
+};
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTEGRATION_LOCKLESS_H__
diff --git a/dali/integration-api/platform-abstraction.h b/dali/integration-api/platform-abstraction.h
new file mode 100644 (file)
index 0000000..3b3f460
--- /dev/null
@@ -0,0 +1,245 @@
+#ifndef __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__
+#define __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+#include <dali/integration-api/resource-cache.h>
+#include <dali/integration-api/bitmap.h> ///@todo Remove this include (a bunch of stuff needs to include it though)
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * PlatformAbstraction is an abstract interface, used by Dali to access platform specific services.
+ * A concrete implementation must be created for each platform, and provided when creating the
+ * Dali::Integration::Core object.
+ */
+class PlatformAbstraction
+{
+public:
+
+  virtual ~PlatformAbstraction() {}
+
+  // Dali Lifecycle
+
+  /**
+   * Get the monotonic time since an unspecified reference point.
+   * This is used by Dali to calculate time intervals during animations; the interval is
+   * recalculated when Dali is resumed with Dali::Integration::Core::Resume().
+   * Multi-threading note: this method may be called from either the main or rendering thread.
+   * @param[out] seconds The time in seconds since the reference point.
+   * @param[out] microSeconds The remainder in microseconds.
+   */
+  virtual void GetTimeMicroseconds(unsigned int& seconds, unsigned int& microSeconds) = 0;
+
+  /**
+   * Tell the platform abstraction that Dali is ready to pause, such as when the
+   * application enters a background state.
+   * Allows background threads to pause their work until Resume() is called.
+   * This is a good time to release recreatable data such as memory caches
+   * to cooperate with other apps and reduce the chance of this one being
+   * force-killed in a low memory situation.
+   */
+  virtual void Suspend() = 0;
+
+  /**
+   * Tell the platform abstraction that Dali is resuming from a pause, such as
+   * when it has transitioned from a background state to a foreground one.
+   * It is time to wake up sleeping background threads and recreate memory
+   * caches and other temporary data.
+   */
+  virtual void Resume() = 0;
+
+  // Resource Loading
+
+  /**
+   * @brief Determine the size of an image the resource loaders will provide when
+   * given the same image loading parameters.
+   *
+   * This is a synchronous request.
+   * This function is used to determine the size of an image before it has loaded.
+   * @param[in] filename name of the image.
+   * @param[in] size The requested size for the image.
+   * @param[in] fittingMode The method to use to map the source image to the desired
+   * dimensions.
+   * @param[in] samplingMode The image filter to use if the image needs to be
+   * downsampled to the requested size.
+   * @param[in] orientationCorrection Whether to use image metadata to rotate or
+   * flip the image, e.g., from portrait to landscape.
+   * @return dimensions that image will have if it is loaded with given parameters.
+   */
+  virtual ImageDimensions GetClosestImageSize( const std::string& filename,
+                                               ImageDimensions size = ImageDimensions( 0, 0 ),
+                                               FittingMode::Type fittingMode = FittingMode::SHRINK_TO_FIT,
+                                               SamplingMode::Type samplingMode = SamplingMode::BOX,
+                                               bool orientationCorrection = true) = 0;
+
+  /**
+   @brief Determine the size of an image the resource loaders will provide when
+   * given the same image loading parameters.
+   *
+   * This is a synchronous request.
+   * This function is used to determine the size of an image before it has loaded.
+   * @param[in] filename name of the image.
+   * @param[in] size The requested size for the image.
+   * @param[in] fittingMode The method to use to map the source image to the desired
+   * dimensions.
+   * @param[in] samplingMode The image filter to use if the image needs to be
+   * downsampled to the requested size.
+   * @param[in] orientationCorrection Whether to use image metadata to rotate or
+   * flip the image, e.g., from portrait to landscape.
+   * @return dimensions that image will have if it is loaded with given parameters.
+   */
+  virtual ImageDimensions GetClosestImageSize( ResourcePointer resourceBuffer,
+                                               ImageDimensions size = ImageDimensions( 0, 0 ),
+                                               FittingMode::Type fittingMode = FittingMode::SHRINK_TO_FIT,
+                                               SamplingMode::Type samplingMode = SamplingMode::BOX,
+                                               bool orientationCorrection = true) = 0;
+
+  /**
+   * Request a resource from the native filesystem. This is an asynchronous request.
+   * After this method returns, FillResourceCache() will be called to retrieve the result(s) of the
+   * resource loading operation. Loading resources in separate worker thread is recommended.
+   * Multi-threading note: this method will be called from the main thread only i.e. not
+   * from within the Core::Render() method.
+   * @param[in] request A unique resource request. This is not guaranteed to survive after LoadResource
+   * returns; the loading process should take a copy.
+   */
+  virtual void LoadResource(const ResourceRequest& request) = 0;
+
+  /**
+   * Request a resource from the native filesystem. This is a synchronous request, i.e.
+   * it will block the main loop whilst executing. It should therefore be used sparingly.
+   *
+   * Multi-threading note: this method will be called from the main thread only i.e. not
+   * from within the Core::Render() method.
+   * @param[in] resourceType The type of resource to load
+   * @param[in] resourcePath The path to the resource
+   * @return A pointer to a ref-counted resource
+   */
+  virtual ResourcePointer LoadResourceSynchronously( const ResourceType& resourceType, const std::string& resourcePath ) = 0;
+
+  /**
+   * Decode a buffer of data synchronously.
+   * @param[in] resourceType The type of resource to load
+   * @param[in] buffer The decoded data
+   * @param[in] bufferSize The size of the buffer used by the decoded data.
+   *
+   * @return A pointer to the decoded buffer.
+   */
+  virtual BitmapPtr DecodeBuffer( const ResourceType& resourceType, uint8_t * buffer, size_t bufferSize ) = 0;
+
+  /**
+   * Cancel an ongoing LoadResource() request.
+   * Multi-threading note: this method will be called from the main thread only i.e. not
+   * from within the Core::Render() method.
+   * @param[in] id The ID of the resource to cancel.
+   * @param[in] typeId The ID type of the resource to cancel.
+   */
+  virtual void CancelLoad(ResourceId id, ResourceTypeId typeId) = 0;
+
+  /**
+   * Query whether any asynchronous LoadResource() requests are ongoing.
+   * Multi-threading note: this method may be called from either the main or rendering thread.
+   * @return True if resources are being loaded.
+   */
+  virtual bool IsLoading() = 0;
+
+  /**
+   * Retrieve newly loaded resources.
+   * If no resources have finished loading, then this method returns immediately.
+   * Multi-threading note: this method will be called from the update thread, from within
+   * the UpdateManager::Update() method.
+   * @param[in] cache The resource cache to fill.
+   */
+  virtual void GetResources(ResourceCache& cache) = 0;
+
+  /**
+   * Waits for the asynchronous loader threads (if any) to finish.
+   * This will be only be called before Core destruction; no resource loading requests will be
+   * made following this method.
+   */
+  virtual void JoinLoaderThreads() = 0;
+
+  // Font Queries
+
+  /**
+   * Called by Dali to retrieve the default font size for the platform.
+   * This is an accessibility size, which is mapped to a UI Control specific point-size in stylesheets.
+   * For example if zero the smallest size, this could potentially map to TextLabel point-size 8.
+   * Multi-threading note: this method will be called from the main thread only i.e. not
+   * from within the Core::Render() method.
+   * @return The default font size.
+   */
+  virtual int GetDefaultFontSize() const = 0;
+
+  /**
+   * Sets horizontal and vertical pixels per inch value that is used by the display
+   * @param[in] dpiHorizontal horizontal dpi value
+   * @param[in] dpiVertical   vertical dpi value
+   */
+  virtual void SetDpi (unsigned int dpiHorizontal, unsigned int dpiVertical) = 0;
+
+  /**
+   * Load a file into a buffer
+   * @param[in] filename The filename to load
+   * @param[out] buffer  A buffer to receive the file.
+   * @result             true if the file is loaded.
+   */
+  virtual bool LoadFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const = 0;
+
+  /**
+   * Load a file into a buffer
+   * @param[in] filename The filename to save
+   * @param[out] buffer  A buffer containing some data
+   *                     The buffer is implemeneted with a Dali::Vector. The size() member specifies the buffer length.
+   * @result             true if the file is saved.
+   */
+  virtual bool SaveFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const = 0;
+
+  /**
+   * Load a shader binary file into a buffer
+   * @param[in] filename The shader binary filename to load
+   * @param[out] buffer  A buffer to receive the file.
+   * @result             true if the file is loaded.
+   */
+  virtual bool LoadShaderBinaryFile( const std::string& filename, Dali::Vector< unsigned char >& buffer ) const = 0;
+
+  /**
+   * Save a shader binary file to the resource file system.
+   * @param[in] filename The shader binary filename to save to.
+   * @param[in] buffer  A buffer to write the file from.
+   * @param[in] numbytes Size of the buffer.
+   * @result             true if the file is saved, else false.
+   */
+  virtual bool SaveShaderBinaryFile( const std::string& filename, const unsigned char * buffer, unsigned int numBytes ) const = 0;
+
+}; // class PlatformAbstraction
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_PLATFORM_ABSTRACTION_H__
diff --git a/dali/integration-api/profiling.cpp b/dali/integration-api/profiling.cpp
new file mode 100644 (file)
index 0000000..fbe6236
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/profiling.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/actors/image-actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+#include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
+#include <dali/internal/event/actor-attachments/image-attachment-impl.h>
+#include <dali/internal/event/actor-attachments/renderer-attachment-impl.h>
+
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/animation/animator-connector.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/scene-graph-animation.h>
+#include <dali/internal/update/animation/scene-graph-constraint.h>
+
+
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/image-factory-cache.h>
+
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/resources/image-ticket.h>
+
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
+
+#include <dali/internal/update/resources/bitmap-metadata.h>
+
+#include <dali/internal/render/gl-resources/bitmap-texture.h>
+#include <dali/internal/render/renderers/scene-graph-image-renderer.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+
+using Dali::Internal::GestureEventProcessor;
+using Dali::Internal::ThreadLocalStorage;
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+void EnableProfiling( ProfilingType type )
+{
+  GestureEventProcessor& eventProcessor = ThreadLocalStorage::Get().GetGestureEventProcessor();
+
+  switch( type )
+  {
+    case PROFILING_TYPE_PAN_GESTURE:
+    {
+      eventProcessor.EnablePanGestureProfiling();
+      break;
+    }
+    case PROFILING_TYPE_END:
+    {
+      // nothing to do
+      break;
+    }
+  }
+}
+
+namespace Profiling
+{
+
+const int ANIMATION_MEMORY_SIZE(
+  sizeof( Internal::Animation ) +
+  sizeof( Internal::AnimatorConnector<float> ) +
+  sizeof( Internal::SceneGraph::Animation ) );
+const int CONSTRAINT_MEMORY_SIZE(
+  sizeof( Internal::Constraint<float> ) +
+  sizeof( Internal::SceneGraph::Constraint<float, Internal::PropertyAccessor<float> > ) );
+const int ACTOR_MEMORY_SIZE(
+  sizeof( Internal::Actor ) +
+  sizeof( Internal::ActorAttachment ) +
+  sizeof( Internal::SceneGraph::Node ) +
+  sizeof( Internal::SceneGraph::NodeAttachment ));
+const int CAMERA_ACTOR_MEMORY_SIZE(
+  sizeof( Internal::CameraActor ) +
+  sizeof( Internal::CameraAttachment ) +
+  sizeof( Internal::SceneGraph::Node ) +
+  sizeof( Internal::SceneGraph::CameraAttachment ) );
+const int IMAGE_ACTOR_MEMORY_SIZE(
+  sizeof( Internal::ImageActor ) +
+  sizeof( Internal::ImageAttachment ) +
+  sizeof( Internal::SceneGraph::Node ) +
+  sizeof( Internal::SceneGraph::ImageAttachment ) +
+  sizeof( Internal::SceneGraph::ImageRenderer ));
+const int LAYER_MEMORY_SIZE(
+  sizeof( Internal::Layer ) +
+  sizeof( Internal::ActorAttachment ) +
+  sizeof( Internal::SceneGraph::Layer ) +
+  sizeof( Internal::SceneGraph::NodeAttachment ) );
+const int IMAGE_MEMORY_SIZE(
+  sizeof( Internal::Image ) +
+  sizeof( Internal::ImageFactoryCache::Request ) +
+  sizeof( Integration::Bitmap ) +
+  sizeof( Internal::BitmapMetadata ) +
+  sizeof( Internal::BitmapTexture ) +
+  sizeof( Internal::ImageTicket ) );
+const int RENDERER_MEMORY_SIZE(
+  sizeof( Internal::Renderer ) +
+  sizeof( Internal::RendererAttachment ) +
+  sizeof( Internal::SceneGraph::RendererAttachment ) +
+  sizeof( Internal::SceneGraph::Renderer ) +
+  sizeof( Internal::SceneGraph::NewRenderer ) );
+const int GEOMETRY_MEMORY_SIZE(
+  sizeof( Internal::Geometry ) +
+  sizeof( Internal::SceneGraph::Geometry ) );
+const int PROPERTY_BUFFER_MEMORY_SIZE(
+  sizeof( Internal::PropertyBuffer ) +
+  sizeof( Internal::SceneGraph::PropertyBuffer ) );
+const int MATERIAL_MEMORY_SIZE(
+  sizeof( Internal::Material ) +
+  sizeof( Internal::SceneGraph::Material ) );
+const int SAMPLER_MEMORY_SIZE(
+  sizeof( Internal::Sampler ) +
+  sizeof( Internal::SceneGraph::Sampler ) );
+const int SHADER_MEMORY_SIZE(
+  sizeof( Internal::Shader ) +
+  sizeof( Internal::SceneGraph::Shader ) );
+
+} // namespace Profiling
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/profiling.h b/dali/integration-api/profiling.h
new file mode 100644 (file)
index 0000000..2b60ca8
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __DALI_INTEGRATION_PROFILING_H__
+#define __DALI_INTEGRATION_PROFILING_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+enum ProfilingType
+{
+  PROFILING_TYPE_PAN_GESTURE,
+
+  PROFILING_TYPE_END
+};
+
+/**
+ * Called by adaptor to provide profiling information.
+ *
+ * @pre Should be called after Core creation.
+ * @param type The type of profiling information to output.
+ */
+DALI_IMPORT_API void EnableProfiling( ProfilingType type );
+
+
+namespace Profiling
+{
+
+DALI_IMPORT_API extern const int ANIMATION_MEMORY_SIZE;    ///< Total size of animation and associated internal objects
+DALI_IMPORT_API extern const int CONSTRAINT_MEMORY_SIZE;   ///< Total size of constraint and associated internal objects
+DALI_IMPORT_API extern const int ACTOR_MEMORY_SIZE;        ///< Total size of actor and associated internal objects
+DALI_IMPORT_API extern const int CAMERA_ACTOR_MEMORY_SIZE; ///< Total size of camera actor and associated internal objects
+DALI_IMPORT_API extern const int IMAGE_ACTOR_MEMORY_SIZE;  ///< Total size of image actor and associated internal objects
+DALI_IMPORT_API extern const int LAYER_MEMORY_SIZE;        ///< Total size of layer and associated internal objects
+DALI_IMPORT_API extern const int IMAGE_MEMORY_SIZE;        ///< Total size of image and associated internal objects
+
+DALI_IMPORT_API extern const int RENDERER_MEMORY_SIZE;     ///< Total size of renderer and associated internal objects
+DALI_IMPORT_API extern const int GEOMETRY_MEMORY_SIZE;     ///< Total size of geometry and associated internal objects
+DALI_IMPORT_API extern const int PROPERTY_BUFFER_MEMORY_SIZE;     ///< Total size of property-0buffer and associated internal objects
+DALI_IMPORT_API extern const int MATERIAL_MEMORY_SIZE;     ///< Total size of material and associated internal objects
+DALI_IMPORT_API extern const int SAMPLER_MEMORY_SIZE;     ///< Total size of material and associated internal objects
+DALI_IMPORT_API extern const int SHADER_MEMORY_SIZE;     ///< Total size of material and associated internal objects
+} // namespace Profiling
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_PROFILING_H__
diff --git a/dali/integration-api/render-controller.h b/dali/integration-api/render-controller.h
new file mode 100644 (file)
index 0000000..253c67e
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __DALI_INTEGRATION_RENDER_CONTROLLER_H__
+#define __DALI_INTEGRATION_RENDER_CONTROLLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * Abstract interface for an object which controls rendering.
+ * This will be informed when Dali has new content to render.
+ */
+class RenderController
+{
+protected:
+
+  /**
+   * Virtual protected destructor, no deletion through this interface
+   */
+  virtual ~RenderController() {}
+
+public:
+
+  /**
+   * Requests a future call to Dali::Integration::Core::Update().
+   * This is called when Dali has new content, typically in response to Actors/Animations being added.
+   * Multi-threading note: this method will be called from the main thread only.
+   */
+  virtual void RequestUpdate() = 0;
+
+  /**
+   * Requests a future call to Dali::Integration::Core::ProcessEvents(), when the application is idle.
+   * Multi-threading note: this method will be called from the main thread only.
+   */
+  virtual void RequestProcessEventsOnIdle() = 0;
+
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_RENDER_CONTROLLER_H__
diff --git a/dali/integration-api/resource-cache.h b/dali/integration-api/resource-cache.h
new file mode 100644 (file)
index 0000000..0ca6803
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_CACHE_H__
+#define __DALI_INTEGRATION_RESOURCE_CACHE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/integration-api/resource-request.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+/**
+ * Used to determine why a resource IO operation has failed.
+ */
+enum ResourceFailure
+{
+  FailureUnknown,
+  FailureFileNotFound,
+  FailureInvalidPath
+};
+
+/**
+ * Used to return loaded resources for rendering etc.
+ */
+typedef IntrusivePtr<Dali::RefObject> ResourcePointer;
+
+/**
+ * Abstract interface to receive notifications of resource IO operations.
+ * This is used when pulling loaded resources from the PlatformAbstraction.
+ */
+class ResourceCache
+{
+protected:
+
+  /**
+   * Virtual protected destructor, no deletion through this interface
+   */
+  virtual ~ResourceCache() {}
+
+public:
+
+  /**
+   * Provide the results of a resource loading operation to the cache.
+   * @param[in] id The unique ID of the load request.
+   *               This should match an ID previously passed into PlatformAbstraction::LoadResource().
+   *               LoadResponse() may be called multiple times with the same ID, when results are available
+   *               at different stages e.g. a thumbnail image may be provided, before the full image is loaded.
+   * @param[in] type The type of the resource.
+   * @param[in] resource A pointer to a resource (Bitmap etc).
+   * @param[in] status The current loading status. RESOURCE_LOADING and RESOURCE_PARTIALLY_LOADED indicate there are more responses to come, RESOURCE_COMPLETELY_LOADED indicates this is the last response for this id.
+   */
+  virtual void LoadResponse(ResourceId id, ResourceTypeId type, ResourcePointer resource, LoadStatus status) = 0;
+
+  /**
+   * Report that a resource loading operation has failed.
+   * @param[in] id The unique ID of the load request.
+   *               This should match an ID previously passed into PlatformAbstraction::LoadResource().
+   * @param[in] failure An error code, used to determine why the load failed.
+   */
+  virtual void LoadFailed(ResourceId id, ResourceFailure failure) = 0;
+};
+
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_RESOURCE_CACHE_H__
diff --git a/dali/integration-api/resource-declarations.h b/dali/integration-api/resource-declarations.h
new file mode 100644 (file)
index 0000000..69dface
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__
+#define __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+/**
+ * @brief Used to identify a resource loading operation.
+ *
+ * These unique ResourceId values can be used to identify a resource loading
+ * transaction in core-adaptor communication.
+ * A resource transaction is asynchronous and many can be in-flight
+ * concurrently.
+ * A ResourceId allows the core to track a resource transaction over its
+ * lifetime and match an asynchronous completion notification to the
+ * corresponding load request or to cancel the operation early.
+ *
+ * A resource transaction begins with a call to PlatformAbstraction::LoadResource()
+ * Later asynchronous status notifications obtained by polling
+ * PlatformAbstraction::GetResources() can be mapped to corresponding
+ * LoadResource() invocations using the ResourceId value.
+ * It is the core's responsibility to ensure that each invocation of
+ * PlatformAbstraction::LoadResource() passes in a Request object with a unique
+ * integer ResourceId.
+ *
+ * @sa Dali::Integration::PlatformAbstraction::LoadResource
+ * Dali::Integration::PlatformAbstraction::GetResources
+ * Dali::Integration::ResourceCache
+ * Dali::Internal::ImageFactoryCache::RequestId
+ */
+typedef unsigned int ResourceId;
+
+/**
+ * Used to inform the current loading status
+ */
+enum LoadStatus
+{
+  RESOURCE_LOADING,            ///< There are missing resources, being loaded
+  RESOURCE_PARTIALLY_LOADED,   ///< Enough resource has been loaded to start low quality rendering
+  RESOURCE_COMPLETELY_LOADED,  ///< The resource has been completely loaded
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_RESOURCE_DECLARATIONS_H__
diff --git a/dali/integration-api/resource-policies.h b/dali/integration-api/resource-policies.h
new file mode 100644 (file)
index 0000000..4713fb3
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_POLICIES_H__
+#define __DALI_INTEGRATION_RESOURCE_POLICIES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Dali
+{
+namespace ResourcePolicy
+{
+
+/**
+ * The data retention policy describes how dali should retain resource data.
+ */
+enum DataRetention
+{
+  DALI_RETAINS_ALL_DATA,  // retains all data e.g. bitmaps
+  DALI_DISCARDS_ALL_DATA, // discards all data (expects application to regenerate UI on context loss)
+};
+
+/**
+ * The discardable policy describes whether a resource is owned or can be discarded.
+ * Discarded means that it can be released after uploading to GPU.
+ */
+enum Discardable
+{
+  OWNED_DISCARD,
+  OWNED_RETAIN,
+  NOT_OWNED
+};
+
+} // namespace ResourcePolicy
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_DISCARD_POLICY_H__
diff --git a/dali/integration-api/resource-request.h b/dali/integration-api/resource-request.h
new file mode 100644 (file)
index 0000000..6690c64
--- /dev/null
@@ -0,0 +1,203 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_REQUEST_H__
+#define __DALI_INTEGRATION_RESOURCE_REQUEST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/resource-types.h>
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+class RefObject;
+
+namespace Integration
+{
+
+// Resource Requests
+
+/**
+ * Used to return loaded resources for rendering etc.
+ */
+typedef IntrusivePtr<Dali::RefObject> ResourcePointer;
+
+/**
+ * Used to prioritize between loading operations.
+ */
+enum LoadResourcePriority
+{
+  LoadPriorityLowest,
+  LoadPriorityLow,
+  LoadPriorityNormal,
+  LoadPriorityHigh,
+  LoadPriorityHighest,
+};
+
+/**
+ * Used to request a resource from the native filesystem.
+ */
+class ResourceRequest
+{
+public:
+
+  /**
+   * Used to request a resource be accessed from the native filesystem.
+   * @param[in] newId         A unique ID for this request.
+   * @param[in] resourceType  The type of resource requested. The implementation of
+   *                          PlatformAbstraction::LoadResource() is responsible for
+   *                          converting the native file(s) to this type
+   *                          e.g. decoding a jpeg to a bitmap.
+   * @param[in] resourcePath  The path of the resource; typically a filename.
+   * @param[in] loadPriority  The priority of the request.
+   */
+  ResourceRequest(ResourceId newId,
+                  const ResourceType& resourceType,
+                  const std::string& resourcePath,
+                  LoadResourcePriority loadPriority = LoadPriorityNormal)
+  : id(newId),
+    type(NULL),
+    path(resourcePath),
+    priority(loadPriority)
+  {
+    type = resourceType.Clone();
+  }
+
+  /**
+   * Used to request or save a resource from/to the native filesystem.
+   * @param[in] newId         A unique ID for this request.
+   * @param[in] resourceType  The type of resource.
+   * @param[in] resourcePath  The location of the resource / where the resource should be saved.
+   * @param[in] resourcePtr   The resource to decode / save.
+   * @param[in] savePriority  The priority of the request.
+   */
+  ResourceRequest(ResourceId newId,
+                  const ResourceType& resourceType,
+                  const std::string& resourcePath,
+                  ResourcePointer resourcePtr,
+                  LoadResourcePriority savePriority = LoadPriorityNormal)
+  : id(newId),
+    type(NULL),
+    path(resourcePath),
+    resource(resourcePtr),
+    priority(savePriority)
+  {
+    type = resourceType.Clone();
+  }
+
+  /**
+   * Copy constructor.
+   * @param[in] request The resource request to copy.
+   */
+  ResourceRequest(const ResourceRequest& request)
+  : id(request.id),
+    type(NULL),
+    path(request.path),
+    resource(request.resource),
+    priority(request.priority)
+  {
+    type = request.type->Clone();
+  }
+
+  /**
+   * Assignment operator.
+   * @param[in] rhs The resource request to copy.
+   */
+  ResourceRequest& operator=(const ResourceRequest& rhs)
+  {
+    if( this != &rhs )
+    {
+      id = rhs.id;
+      type = rhs.type->Clone();
+      path = rhs.path;
+      resource = rhs.resource;
+      priority = rhs.priority;
+    }
+
+    return *this;
+  }
+
+  /**
+   * Non-virtual destructor; not intended as a base class
+   */
+  ~ResourceRequest()
+  {
+    delete type;
+  }
+
+  /**
+   * Retrieve the resource ID
+   * @return The ID
+   */
+  ResourceId GetId() const
+  {
+    return id;
+  }
+
+  /**
+   * Retrieve the resource type
+   * @return The type
+   */
+  ResourceType* GetType() const
+  {
+    return type;
+  }
+
+  /**
+   * Retrieve the resource path
+   * @return The path
+   */
+  const std::string& GetPath() const
+  {
+    return path;
+  }
+
+  /**
+   * Retrieve the resource (for save and decode requests)
+   * @return The resource
+   */
+  ResourcePointer GetResource() const
+  {
+    return resource;
+  }
+
+  /**
+   * Retrieve the load priority
+   * @return The priority
+   */
+  LoadResourcePriority GetPriority() const
+  {
+    return priority;
+  }
+
+private:
+
+  ResourceId           id;
+  ResourceType*        type;
+  std::string          path;
+  /** When saving resources or decoding them, the resource data will be passed
+   *  through in a reference counted object here. When Loading, it will be null. */
+  ResourcePointer      resource;
+  LoadResourcePriority priority;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_RESOURCE_REQUEST_H__
diff --git a/dali/integration-api/resource-types.h b/dali/integration-api/resource-types.h
new file mode 100644 (file)
index 0000000..1d5182e
--- /dev/null
@@ -0,0 +1,239 @@
+#ifndef __DALI_INTEGRATION_RESOURCE_TYPES_H__
+#define __DALI_INTEGRATION_RESOURCE_TYPES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/math/uint-16-pair.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/resource-declarations.h>
+
+namespace Dali
+{
+
+typedef Uint16Pair ImageDimensions;
+
+namespace Integration
+{
+
+// Resource Types
+
+/**
+ * Extendable set of resource types
+ */
+enum ResourceTypeId
+{
+  ResourceBitmap,
+  ResourceNativeImage,
+  ResourceTargetImage
+};
+
+/**
+ * The abstract base class for resource types.
+ */
+struct ResourceType
+{
+  /**
+   * Constructor.
+   * @param[in] typeId resource type id
+   */
+  ResourceType(ResourceTypeId typeId)
+  : id(typeId) {}
+
+  /**
+   * Destructor.
+   */
+  virtual ~ResourceType() {}
+
+  /**
+   * Create a copy of the resource type with the same attributes.
+   * @return pointer to the new ResourceType.
+   */
+  virtual ResourceType* Clone() const = 0;
+
+  const ResourceTypeId id;
+
+private:
+
+  // Undefined copy constructor.
+  ResourceType(const ResourceType& typePath);
+
+  // Undefined assignment operator.
+  ResourceType& operator=(const ResourceType& rhs);
+};
+
+/**
+ * BitmapResourceType describes a bitmap resource, which can be requested
+ * from ResourceLoader::LoadResource() or AllocateBitmapImage.
+ */
+struct BitmapResourceType : public ResourceType
+{
+  /**
+   * Constructor.
+   * @param[in] size The requested size for the bitmap.
+   * @param[in] scalingMode The method to use to map the source bitmap to the desired
+   * dimensions.
+   * @param[in] samplingMode The filter to use if the bitmap needs to be downsampled
+   * to the requested size.
+   * @param[in] orientationCorrection Whether to use bitmap metadata to rotate or
+   * flip the bitmap, e.g., from portrait to landscape.
+   */
+  BitmapResourceType( ImageDimensions size = ImageDimensions( 0, 0 ),
+                      FittingMode::Type scalingMode = FittingMode::DEFAULT,
+                      SamplingMode::Type samplingMode = SamplingMode::DEFAULT,
+                      bool orientationCorrection = true )
+  : ResourceType(ResourceBitmap),
+    size(size), scalingMode(scalingMode), samplingMode(samplingMode), orientationCorrection(orientationCorrection) {}
+
+  /**
+   * Destructor.
+   */
+  virtual ~BitmapResourceType() {}
+
+  /**
+   * @copydoc ResourceType::Clone
+   */
+  virtual ResourceType* Clone() const
+  {
+    return new BitmapResourceType( size, scalingMode, samplingMode, orientationCorrection );
+  }
+
+  /**
+   * Attributes are copied from the request.
+   */
+  ImageDimensions size;
+  FittingMode::Type scalingMode;
+  SamplingMode::Type samplingMode;
+  bool orientationCorrection;
+
+private:
+
+  // Undefined copy constructor.
+  BitmapResourceType(const BitmapResourceType& typePath);
+
+  // Undefined assignment operator.
+  BitmapResourceType& operator=(const BitmapResourceType& rhs);
+};
+
+/**
+ * NativeImageResourceType describes a native image resource, which can be injected
+ * through ResourceManager::AddNativeImage() or requested through ResourceLoader::LoadResource().
+ * If the adaptor does not support NativeImages, it can fall back to Bitmap type.
+ */
+struct NativeImageResourceType : public ResourceType
+{
+  /**
+   * Constructor.
+   */
+  NativeImageResourceType()
+  : ResourceType(ResourceNativeImage) {}
+
+  /**
+   * Constructor.
+   * @param[in] dimensions Width and Height to allocate for image.
+   */
+  NativeImageResourceType( ImageDimensions dimensions )
+  : ResourceType(ResourceNativeImage),
+    imageDimensions(dimensions) {}
+
+  /**
+   * Destructor.
+   */
+  virtual ~NativeImageResourceType() {}
+
+ /**
+  * @copydoc ResourceType::Clone
+  */
+  virtual ResourceType* Clone() const
+  {
+    return new NativeImageResourceType(imageDimensions);
+  }
+
+  /**
+   * Attributes are copied from the request (if supplied).
+   */
+  ImageDimensions imageDimensions;
+
+private:
+
+  // Undefined copy constructor.
+  NativeImageResourceType(const NativeImageResourceType& typePath);
+
+  // Undefined assignment operator.
+  NativeImageResourceType& operator=(const NativeImageResourceType& rhs);
+};
+
+/**
+ * RenderTargetResourceType describes a bitmap resource, which can injected
+ * through ResourceManager::AddTargetImage()
+ */
+struct RenderTargetResourceType : public ResourceType
+{
+  /**
+   * Constructor.
+   */
+  RenderTargetResourceType()
+  : ResourceType(ResourceTargetImage) {}
+
+  /**
+   * Constructor.
+   * @param[in] dims Width and Height to allocate for image.
+   */
+  RenderTargetResourceType( ImageDimensions dims )
+  : ResourceType(ResourceTargetImage),
+    imageDimensions(dims) {}
+
+  /**
+   * Destructor.
+   */
+  virtual ~RenderTargetResourceType() {}
+
+  /**
+   * @copydoc ResourceType::Clone
+   */
+  virtual ResourceType* Clone() const
+  {
+    return new RenderTargetResourceType(imageDimensions);
+  }
+
+  /**
+   * Image size is copied from the request.
+   */
+  ImageDimensions imageDimensions;
+
+private:
+
+  // Undefined copy constructor.
+  RenderTargetResourceType(const RenderTargetResourceType& typePath);
+
+  // Undefined assignment operator.
+  RenderTargetResourceType& operator=(const RenderTargetResourceType& rhs);
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_RESOURCE_TYPES_H__
diff --git a/dali/integration-api/system-overlay.cpp b/dali/integration-api/system-overlay.cpp
new file mode 100644 (file)
index 0000000..a6ab5ad
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/integration-api/system-overlay.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/system-overlay-impl.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+SystemOverlay::~SystemOverlay()
+{
+  delete mImpl;
+}
+
+void SystemOverlay::Add( Actor actor )
+{
+  mImpl->Add( GetImplementation(actor) );
+}
+
+void SystemOverlay::Remove( Actor actor )
+{
+  mImpl->Remove( GetImplementation(actor) );
+}
+
+RenderTaskList SystemOverlay::GetOverlayRenderTasks()
+{
+  return RenderTaskList( &mImpl->GetOverlayRenderTasks() );
+}
+
+SystemOverlay::SystemOverlay( Internal::SystemOverlay* impl )
+: mImpl( impl )
+{
+}
+
+Internal::SystemOverlay* SystemOverlay::GetImpl()
+{
+  return mImpl;
+}
+
+} // namespace Integration
+
+} // namespace Dali
diff --git a/dali/integration-api/system-overlay.h b/dali/integration-api/system-overlay.h
new file mode 100644 (file)
index 0000000..0d90702
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef __DALI_INTEGRATION_SYSTEM_OVERLAY_H__
+#define __DALI_INTEGRATION_SYSTEM_OVERLAY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+class Actor;
+class RenderTaskList;
+
+namespace Internal
+{
+class SystemOverlay;
+}
+
+namespace Integration
+{
+
+/**
+ * Use this interface to draw content for system-level indicators, dialogs etc.
+ * The SystemOverlay is accessible using Dali::Integration::Core::GetSystemOverlay().
+ */
+class DALI_IMPORT_API SystemOverlay
+{
+public:
+
+  /**
+   * Non-virtual destructor. SystemOverlay is not intended as a base class.
+   */
+  ~SystemOverlay();
+
+  /**
+   * Add an Actor to the SystemOverlay.
+   * @pre The actor handle is not empty.
+   * @param [in] actor A handle to the actor to add.
+   * @post The actor will be referenced.
+   */
+  void Add( Actor actor );
+
+  /**
+   * Remove an Actor that was added to the SystemOverlay.
+   * @pre The actor handle is not empty.
+   * @param [in] actor A handle to the actor to remove.
+   * @post The actor will be unreferenced.
+   */
+  void Remove( Actor actor );
+
+  /**
+   * Retrieve the list of render-tasks for system-level overlays.
+   * This is a seperate list, processed after the render-tasks provided by Stage::GetRenderTaskList().
+   * @return The list of overlay render-tasks.
+   */
+  RenderTaskList GetOverlayRenderTasks();
+
+  /**
+   * Create the SystemOverlay entrance.
+   * This is not intended for adaptor implementors; see also Dali::Integration::Core::GetSystemOverlay().
+   * @param[in] impl The SystemOverlay implementation.
+   */
+  SystemOverlay( Internal::SystemOverlay* impl );
+
+  /**
+   * Retreive the internal implementation; this is not intended for adaptor implementors.
+   * @return The SystemOverlay implementation.
+   */
+  Internal::SystemOverlay* GetImpl();
+
+private:
+
+  // Undefined copy-constructor.
+  SystemOverlay( const SystemOverlay& core );
+
+  // Undefined assignment operator.
+  SystemOverlay& operator=( const SystemOverlay& rhs );
+
+private:
+
+  Dali::Internal::SystemOverlay* mImpl;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_SYSTEM_OVERLAY_H__
diff --git a/dali/internal/common/blending-options.cpp b/dali/internal/common/blending-options.cpp
new file mode 100644 (file)
index 0000000..181b8f6
--- /dev/null
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/blending-options.h>
+
+namespace // unnamed namespace
+{
+
+using namespace Dali;
+
+const int MASK_SRC_FACTOR_RGB    = 0x0000000F;
+const int MASK_SRC_FACTOR_ALPHA  = 0x000000F0;
+const int MASK_DEST_FACTOR_RGB   = 0x00000F00;
+const int MASK_DEST_FACTOR_ALPHA = 0x0000F000;
+const int MASK_EQUATION_RGB      = 0x000F0000;
+const int MASK_EQUATION_ALPHA    = 0x00F00000;
+
+const int SHIFT_TO_SRC_FACTOR_RGB    =  0;
+const int SHIFT_TO_SRC_FACTOR_ALPHA  =  4;
+const int SHIFT_TO_DEST_FACTOR_RGB   =  8;
+const int SHIFT_TO_DEST_FACTOR_ALPHA = 12;
+const int SHIFT_TO_EQUATION_RGB      = 16;
+const int SHIFT_TO_EQUATION_ALPHA    = 20;
+
+static unsigned int CLEAR_BLEND_FUNC_MASK     = 0xFFFF0000; // Bottom 16 bits cleared
+static unsigned int CLEAR_BLEND_EQUATION_MASK = 0xFF00FFFF; // 8 bits cleared
+
+/**
+ * Utility to store one of the BlendFunc values.
+ * @param[out] options A bitmask used to store the BlendFunc values.
+ * @param[in] factor The BlendFunc value.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ */
+void StoreBlendingFactor( unsigned int& options, BlendingFactor::Type factor, int bitShift )
+{
+  switch ( factor )
+  {
+    case BlendingFactor::ZERO:
+      options |= ( 0u << bitShift );
+      break;
+
+    case BlendingFactor::ONE:
+      options |= ( 1u << bitShift );
+      break;
+
+    case BlendingFactor::SRC_COLOR:
+      options |= ( 2u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_SRC_COLOR:
+      options |= ( 3u << bitShift );
+      break;
+
+    case BlendingFactor::SRC_ALPHA:
+      options |= ( 4u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_SRC_ALPHA:
+      options |= ( 5u << bitShift );
+      break;
+
+    case BlendingFactor::DST_ALPHA:
+      options |= ( 6u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_DST_ALPHA:
+      options |= ( 7u << bitShift );
+      break;
+
+    case BlendingFactor::DST_COLOR:
+      options |= ( 8u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_DST_COLOR:
+      options |= ( 9u << bitShift );
+      break;
+
+    case BlendingFactor::SRC_ALPHA_SATURATE:
+      options |= ( 10u << bitShift );
+      break;
+
+    case BlendingFactor::CONSTANT_COLOR:
+      options |= ( 11u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_CONSTANT_COLOR:
+      options |= ( 12u << bitShift );
+      break;
+
+    case BlendingFactor::CONSTANT_ALPHA:
+      options |= ( 13u << bitShift );
+      break;
+
+    case BlendingFactor::ONE_MINUS_CONSTANT_ALPHA:
+      options |= ( 14u << bitShift );
+      break;
+  }
+}
+
+/**
+ * Utility to store one of the BlendEquation values.
+ * @param[out] options A bitmask used to store the BlendEquation values.
+ * @param[in] factor The BlendEquation value.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ */
+void StoreBlendingEquation( unsigned int& options, BlendingEquation::Type factor, int bitShift )
+{
+  switch ( factor )
+  {
+    case BlendingEquation::ADD:
+      options |= ( 0u << bitShift );
+      break;
+
+    case BlendingEquation::SUBTRACT:
+      options |= ( 1u << bitShift );
+      break;
+
+    case BlendingEquation::REVERSE_SUBTRACT:
+      options |= ( 2u << bitShift );
+      break;
+  }
+}
+
+const unsigned int BLENDING_FACTOR_COUNT   = 15;
+const unsigned int BLENDING_EQUATION_COUNT = 3;
+
+BlendingFactor::Type BLENDING_FACTORS[ BLENDING_FACTOR_COUNT ] =
+  { BlendingFactor::ZERO,
+    BlendingFactor::ONE,
+    BlendingFactor::SRC_COLOR,
+    BlendingFactor::ONE_MINUS_SRC_COLOR,
+    BlendingFactor::SRC_ALPHA,
+    BlendingFactor::ONE_MINUS_SRC_ALPHA,
+    BlendingFactor::DST_ALPHA,
+    BlendingFactor::ONE_MINUS_DST_ALPHA,
+    BlendingFactor::DST_COLOR,
+    BlendingFactor::ONE_MINUS_DST_COLOR,
+    BlendingFactor::SRC_ALPHA_SATURATE,
+    BlendingFactor::CONSTANT_COLOR,
+    BlendingFactor::ONE_MINUS_CONSTANT_COLOR,
+    BlendingFactor::CONSTANT_ALPHA,
+    BlendingFactor::ONE_MINUS_CONSTANT_ALPHA };
+
+BlendingEquation::Type BLENDING_EQUATIONS[ BLENDING_EQUATION_COUNT ] =
+  { BlendingEquation::ADD,
+    BlendingEquation::SUBTRACT,
+    BlendingEquation::REVERSE_SUBTRACT };
+
+/**
+ * Utility to retrieve one of the BlendFunc values.
+ * @param[in] options A bitmask of blending values.
+ * @param[in] mask The used to mask unwanted values.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ * @return The blending factor.
+ */
+BlendingFactor::Type RetrieveBlendingFactor( unsigned int options, int mask, int bitShift )
+{
+  unsigned int index = options & mask;
+  index = index >> bitShift;
+
+  DALI_ASSERT_DEBUG( index < BLENDING_FACTOR_COUNT );
+
+  return BLENDING_FACTORS[ index ];
+}
+
+/**
+ * Utility to retrieve one of the BlendEquation values.
+ * @param[in] options A bitmask of blending values.
+ * @param[in] mask The used to mask unwanted values.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ * @return The blending equation.
+ */
+BlendingEquation::Type RetrieveBlendingEquation( unsigned int options, int mask, int bitShift )
+{
+  unsigned int index = options & mask;
+  index = index >> bitShift;
+
+  DALI_ASSERT_DEBUG( index < BLENDING_EQUATION_COUNT );
+
+  return BLENDING_EQUATIONS[ index ];
+}
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+BlendingOptions::BlendingOptions()
+: mBitmask( 0u ),
+  mOptionalColor( NULL )
+{
+  SetBlendFunc( DEFAULT_BLENDING_SRC_FACTOR_RGB,   DEFAULT_BLENDING_DEST_FACTOR_RGB,
+                DEFAULT_BLENDING_SRC_FACTOR_ALPHA, DEFAULT_BLENDING_DEST_FACTOR_ALPHA );
+
+  SetBlendEquation( DEFAULT_BLENDING_EQUATION_RGB, DEFAULT_BLENDING_EQUATION_ALPHA );
+}
+
+BlendingOptions::~BlendingOptions()
+{
+  delete mOptionalColor;
+}
+
+void BlendingOptions::SetBitmask( unsigned int bitmask )
+{
+  mBitmask = bitmask;
+}
+
+unsigned int BlendingOptions::GetBitmask() const
+{
+  return mBitmask;
+}
+
+void BlendingOptions::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                                    BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
+{
+  mBitmask &= CLEAR_BLEND_FUNC_MASK; // Clear the BlendFunc values
+
+  StoreBlendingFactor( mBitmask, srcFactorRgb,    SHIFT_TO_SRC_FACTOR_RGB );
+  StoreBlendingFactor( mBitmask, destFactorRgb,   SHIFT_TO_DEST_FACTOR_RGB );
+  StoreBlendingFactor( mBitmask, srcFactorAlpha,  SHIFT_TO_SRC_FACTOR_ALPHA );
+  StoreBlendingFactor( mBitmask, destFactorAlpha, SHIFT_TO_DEST_FACTOR_ALPHA );
+}
+
+BlendingFactor::Type BlendingOptions::GetBlendSrcFactorRgb() const
+{
+  return RetrieveBlendingFactor( mBitmask, MASK_SRC_FACTOR_RGB,  SHIFT_TO_SRC_FACTOR_RGB );
+}
+
+BlendingFactor::Type BlendingOptions::GetBlendDestFactorRgb() const
+{
+  return RetrieveBlendingFactor( mBitmask, MASK_DEST_FACTOR_RGB, SHIFT_TO_DEST_FACTOR_RGB );
+}
+
+BlendingFactor::Type BlendingOptions::GetBlendSrcFactorAlpha() const
+{
+  return RetrieveBlendingFactor( mBitmask, MASK_SRC_FACTOR_ALPHA,  SHIFT_TO_SRC_FACTOR_ALPHA );
+}
+
+BlendingFactor::Type BlendingOptions::GetBlendDestFactorAlpha() const
+{
+  return RetrieveBlendingFactor( mBitmask, MASK_DEST_FACTOR_ALPHA, SHIFT_TO_DEST_FACTOR_ALPHA );
+}
+
+void BlendingOptions::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
+{
+  mBitmask &= CLEAR_BLEND_EQUATION_MASK; // Clear the BlendEquation values
+
+  StoreBlendingEquation( mBitmask, equationRgb,   SHIFT_TO_EQUATION_RGB );
+  StoreBlendingEquation( mBitmask, equationAlpha, SHIFT_TO_EQUATION_ALPHA );
+}
+
+BlendingEquation::Type BlendingOptions::GetBlendEquationRgb() const
+{
+  return RetrieveBlendingEquation( mBitmask, MASK_EQUATION_RGB, SHIFT_TO_EQUATION_RGB );
+}
+
+BlendingEquation::Type BlendingOptions::GetBlendEquationAlpha() const
+{
+  return RetrieveBlendingEquation( mBitmask, MASK_EQUATION_ALPHA, SHIFT_TO_EQUATION_ALPHA );
+}
+
+bool BlendingOptions::SetBlendColor( const Vector4& color )
+{
+  bool changed( false );
+
+  if( Vector4::ZERO == color )
+  {
+    if( mOptionalColor )
+    {
+      // Discard unnecessary vector
+      delete mOptionalColor;
+      mOptionalColor = NULL;
+
+      changed = true;
+    }
+  }
+  else if( !mOptionalColor )
+  {
+    // Lazy allocation when non-default is set
+    mOptionalColor = new Vector4( color );
+    changed = true;
+  }
+  else if( *mOptionalColor != color )
+  {
+    *mOptionalColor = color;
+    changed = true;
+  }
+
+  return changed;
+}
+
+const Vector4* BlendingOptions::GetBlendColor() const
+{
+  return mOptionalColor;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/common/blending-options.h b/dali/internal/common/blending-options.h
new file mode 100644 (file)
index 0000000..cc6a938
--- /dev/null
@@ -0,0 +1,129 @@
+#ifndef __DALI_BLENDING_OPTIONS_H__
+#define __DALI_BLENDING_OPTIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/blending.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// This is an optimization to avoid storing 6 separate blending values
+struct BlendingOptions
+{
+  /**
+   * Create some default blending options.
+   */
+  BlendingOptions();
+
+  /**
+   * Non-virtual destructor.
+   */
+  ~BlendingOptions();
+
+  /**
+   * Set the blending options.
+   * @param[in] A bitmask of blending options.
+   */
+  void SetBitmask( unsigned int bitmask );
+
+  /**
+   * Retrieve the blending options as a bitmask.
+   * @return A bitmask of blending options.
+   */
+  unsigned int GetBitmask() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  BlendingFactor::Type GetBlendSrcFactorRgb() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  BlendingFactor::Type GetBlendDestFactorRgb() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  BlendingFactor::Type GetBlendSrcFactorAlpha() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  BlendingFactor::Type GetBlendDestFactorAlpha() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendEquation()
+   */
+  BlendingEquation::Type GetBlendEquationRgb() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendEquation()
+   */
+  BlendingEquation::Type GetBlendEquationAlpha() const;
+
+  /**
+   * Set the blend color.
+   * @param[in] color The blend color.
+   * @return True if the blend color changed, otherwise it was already the same color.
+   */
+  bool SetBlendColor( const Vector4& color );
+
+  /**
+   * Query the blend color.
+   * The blend color, or NULL if no blend color was set.
+   */
+  const Vector4* GetBlendColor() const;
+
+private:
+
+  // Undefined copy constructor.
+  BlendingOptions(const BlendingOptions& typePath);
+
+  // Undefined copy constructor.
+  BlendingOptions& operator=(const BlendingOptions& rhs);
+
+private:
+
+  unsigned int mBitmask; ///< A bitmask of blending options
+
+  Vector4* mOptionalColor; ///< A heap-allocated color (owned)
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_BLENDING_OPTIONS_H__
diff --git a/dali/internal/common/buffer-index.h b/dali/internal/common/buffer-index.h
new file mode 100644 (file)
index 0000000..f5dee67
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef __DALI_INTERNAL_BUFFER_INDEX_H__
+#define __DALI_INTERNAL_BUFFER_INDEX_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef unsigned int BufferIndex;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_BUFFER_INDEX_H__
diff --git a/dali/internal/common/core-impl.cpp b/dali/internal/common/core-impl.cpp
new file mode 100644 (file)
index 0000000..0489dcf
--- /dev/null
@@ -0,0 +1,469 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/core-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/system-overlay.h>
+#include <dali/integration-api/core.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/integration-api/render-controller.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/animation/animation-playlist.h>
+#include <dali/internal/event/common/property-notification-manager.h>
+#include <dali/internal/event/common/notification-manager.h>
+#include <dali/integration-api/events/event.h>
+#include <dali/internal/event/events/event-processor.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/internal/update/common/discard-queue.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/effects/shader-factory.h>
+#include <dali/internal/update/touch/touch-resampler.h>
+#include <dali/internal/event/common/type-registry-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
+
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/gl-resources/context.h>
+
+using Dali::Internal::SceneGraph::UpdateManager;
+using Dali::Internal::SceneGraph::RenderManager;
+using Dali::Internal::SceneGraph::DiscardQueue;
+using Dali::Internal::SceneGraph::RenderQueue;
+using Dali::Internal::SceneGraph::TextureCache;
+
+namespace
+{
+// The Update for frame N+1 may be processed whilst frame N is being rendered.
+const unsigned int MAXIMUM_UPDATE_COUNT = 2u;
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gCoreFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CORE");
+#endif
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+using Integration::RenderController;
+using Integration::PlatformAbstraction;
+using Integration::GlSyncAbstraction;
+using Integration::GestureManager;
+using Integration::GlAbstraction;
+using Integration::Event;
+using Integration::UpdateStatus;
+using Integration::RenderStatus;
+
+Core::Core( RenderController& renderController, PlatformAbstraction& platform,
+            GlAbstraction& glAbstraction, GlSyncAbstraction& glSyncAbstraction,
+            GestureManager& gestureManager, ResourcePolicy::DataRetention dataRetentionPolicy)
+: mRenderController( renderController ),
+  mPlatform(platform),
+  mGestureEventProcessor(NULL),
+  mEventProcessor(NULL),
+  mUpdateManager(NULL),
+  mRenderManager(NULL),
+  mDiscardQueue(NULL),
+  mResourcePostProcessQueue(),
+  mNotificationManager(NULL),
+  mImageFactory(NULL),
+  mShaderFactory(NULL),
+  mIsActive(true),
+  mProcessingEvent(false)
+{
+  // Create the thread local storage
+  CreateThreadLocalStorage();
+
+  // This does nothing until Core is built with --enable-performance-monitor
+  PERFORMANCE_MONITOR_INIT( platform );
+
+  mNotificationManager = new NotificationManager();
+
+  mAnimationPlaylist = AnimationPlaylist::New();
+
+  mPropertyNotificationManager = PropertyNotificationManager::New();
+
+  std::vector< ResourcePostProcessRequest> init;
+  mResourcePostProcessQueue = new ResourcePostProcessList(init);
+
+  mRenderManager = RenderManager::New( glAbstraction, *mResourcePostProcessQueue );
+
+  RenderQueue& renderQueue = mRenderManager->GetRenderQueue();
+  TextureCache& textureCache = mRenderManager->GetTextureCache();
+
+  ResourcePolicy::Discardable discardPolicy = ResourcePolicy::OWNED_DISCARD;
+  if( dataRetentionPolicy == ResourcePolicy::DALI_RETAINS_ALL_DATA )
+  {
+    discardPolicy = ResourcePolicy::OWNED_RETAIN;
+  }
+  textureCache.SetDiscardBitmapsPolicy(discardPolicy);
+
+  mDiscardQueue = new DiscardQueue( renderQueue );
+
+  mResourceManager = new ResourceManager(  mPlatform,
+                                          *mNotificationManager,
+                                           textureCache,
+                                          *mResourcePostProcessQueue,
+                                          *mRenderManager,
+                                          *mDiscardQueue,
+                                           renderQueue );
+
+  mTouchResampler = TouchResampler::New();
+
+  mUpdateManager = new UpdateManager( *mNotificationManager,
+                                       glSyncAbstraction,
+                                      *mAnimationPlaylist,
+                                      *mPropertyNotificationManager,
+                                      *mResourceManager,
+                                      *mDiscardQueue,
+                                       renderController,
+                                      *mRenderManager,
+                                       renderQueue,
+                                       textureCache,
+                                      *mTouchResampler );
+
+  mRenderManager->SetShaderSaver( *mUpdateManager );
+
+  mStage = IntrusivePtr<Stage>( Stage::New( *mAnimationPlaylist, *mPropertyNotificationManager, *mUpdateManager, *mNotificationManager ) );
+
+  // This must be called after stage is created but before stage initialization
+  mRelayoutController = IntrusivePtr< RelayoutController >( new RelayoutController( mRenderController ) );
+
+  mStage->Initialize();
+
+  mResourceClient = new ResourceClient( *mResourceManager, *mStage );
+
+  mGestureEventProcessor = new GestureEventProcessor(*mStage, gestureManager, mRenderController);
+  mEventProcessor = new EventProcessor(*mStage, *mNotificationManager, *mGestureEventProcessor);
+
+  mImageFactory = new ImageFactory( *mResourceClient );
+  mShaderFactory = new ShaderFactory();
+  mUpdateManager->SetShaderSaver( *mShaderFactory );
+  mShaderFactory->LoadDefaultShaders();
+
+  GetImplementation(Dali::TypeRegistry::Get()).CallInitFunctions();
+}
+
+Core::~Core()
+{
+  /**
+   * TODO this should be done by Adaptor, Core does not know about threading
+   * First stop the resource loading thread(s)
+   */
+  mPlatform.JoinLoaderThreads();
+
+  /*
+   * The order of destructing these singletons is important!!!
+   */
+
+  // clear the thread local storage first
+  // allows core to be created / deleted many times in the same thread (how TET cases work).
+  // Do this before mStage.Reset() so Stage::IsInstalled() returns false
+  ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+  if( tls )
+  {
+    tls->Remove();
+  }
+
+  // Stop relayout requests being raised on stage destruction
+  mRelayoutController.Reset();
+
+  // Clean-up stage - remove default camera and root layer
+  mStage->Uninitialize();
+
+  // remove (last?) reference to stage
+  mStage.Reset();
+
+  delete mEventProcessor;
+  delete mGestureEventProcessor;
+  delete mNotificationManager;
+  delete mImageFactory;
+  delete mShaderFactory;
+  delete mResourceClient;
+  delete mResourceManager;
+  delete mUpdateManager;
+  delete mTouchResampler;
+  delete mRenderManager;
+  delete mDiscardQueue;
+  delete mResourcePostProcessQueue;
+}
+
+Integration::ContextNotifierInterface* Core::GetContextNotifier()
+{
+  return mStage.Get();
+}
+
+void Core::RecoverFromContextLoss()
+{
+  DALI_LOG_INFO(gCoreFilter, Debug::Verbose, "Core::RecoverFromContextLoss()\n");
+
+  mImageFactory->RecoverFromContextLoss(); // Reload images from files
+  mStage->GetRenderTaskList().RecoverFromContextLoss(); // Re-trigger render-tasks
+}
+
+void Core::ContextCreated()
+{
+  mRenderManager->ContextCreated();
+}
+
+void Core::ContextDestroyed()
+{
+  mRenderManager->ContextDestroyed();
+}
+
+void Core::SurfaceResized( unsigned int width, unsigned int height )
+{
+  mStage->SetSize( width, height );
+  mRelayoutController->SetStageSize( width, height );
+}
+
+void Core::SetDpi( unsigned int dpiHorizontal, unsigned int dpiVertical )
+{
+  mPlatform.SetDpi( dpiHorizontal, dpiVertical );
+  mStage->SetDpi( Vector2( dpiHorizontal , dpiVertical) );
+}
+
+void Core::Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status )
+{
+  // set the time delta so adaptor can easily print FPS with a release build with 0 as
+  // it is cached by frametime
+  status.secondsFromLastFrame = elapsedSeconds;
+
+  // Render returns true when there are updates on the stage or one or more animations are completed.
+  // Use the estimated time diff till we render as the elapsed time.
+  status.keepUpdating = mUpdateManager->Update( elapsedSeconds,
+                                                lastVSyncTimeMilliseconds,
+                                                nextVSyncTimeMilliseconds );
+
+  // Check the Notification Manager message queue to set needsNotification
+  status.needsNotification = mNotificationManager->MessagesToProcess();
+
+  // No need to keep update running if there are notifications to process.
+  // Any message to update will wake it up anyways
+
+  if ( mResourceManager->ResourcesToProcess() )
+  {
+    // If we are still processing resources, then we have to continue the update
+    status.keepUpdating |= Integration::KeepUpdating::LOADING_RESOURCES;
+  }
+}
+
+void Core::Render( RenderStatus& status )
+{
+  bool updateRequired = mRenderManager->Render( status );
+
+  status.SetNeedsUpdate( updateRequired );
+}
+
+void Core::Suspend()
+{
+  mPlatform.Suspend();
+
+  mIsActive = false;
+}
+
+void Core::Resume()
+{
+  mPlatform.Resume();
+
+  mIsActive = true;
+
+  // trigger processing of events queued up while paused
+  ProcessEvents();
+}
+
+void Core::SceneCreated()
+{
+  mStage->EmitSceneCreatedSignal();
+
+  mRelayoutController->OnApplicationSceneCreated();
+}
+
+void Core::QueueEvent( const Integration::Event& event )
+{
+  mEventProcessor->QueueEvent( event );
+}
+
+void Core::ProcessEvents()
+{
+  // Guard against calls to ProcessEvents() during ProcessEvents()
+  if( mProcessingEvent )
+  {
+    DALI_LOG_ERROR( "ProcessEvents should not be called from within ProcessEvents!" );
+    mRenderController.RequestProcessEventsOnIdle();
+    return;
+  }
+
+  mProcessingEvent = true;
+  mRelayoutController->SetProcessingCoreEvents( true );
+
+  // Signal that any messages received will be flushed soon
+  mUpdateManager->EventProcessingStarted();
+
+  mEventProcessor->ProcessEvents();
+
+  mNotificationManager->ProcessMessages();
+
+  // Avoid allocating MessageBuffers, triggering size-negotiation or sending any other spam whilst paused
+  if( mIsActive )
+  {
+    // Emit signal here to start size negotiation and control relayout.
+    mStage->EmitEventProcessingFinishedSignal();
+
+    // Run the size negotiation after event processing finished signal
+    mRelayoutController->Relayout();
+
+    // Flush discard queue for image factory
+    mImageFactory->FlushReleaseQueue();
+
+    // Flush any queued messages for the update-thread
+    const bool messagesToProcess = mUpdateManager->FlushQueue();
+
+    // Check if the touch or gestures require updates.
+    const bool touchNeedsUpdate = mTouchResampler->NeedsUpdate();
+    const bool gestureNeedsUpdate = mGestureEventProcessor->NeedsUpdate();
+
+    if( messagesToProcess || touchNeedsUpdate || gestureNeedsUpdate )
+    {
+      // tell the render controller to keep update thread running
+      mRenderController.RequestUpdate();
+    }
+  }
+
+  mRelayoutController->SetProcessingCoreEvents( false );
+
+  // ProcessEvents() may now be called again
+  mProcessingEvent = false;
+}
+
+void Core::UpdateTouchData(const Integration::TouchData& touch)
+{
+  mTouchResampler->SendTouchData( touch );
+}
+
+unsigned int Core::GetMaximumUpdateCount() const
+{
+  return MAXIMUM_UPDATE_COUNT;
+}
+
+Integration::SystemOverlay& Core::GetSystemOverlay()
+{
+  return mStage->GetSystemOverlay();
+}
+
+void Core::SetViewMode( ViewMode viewMode )
+{
+  mStage->SetViewMode( viewMode );
+}
+
+ViewMode Core::GetViewMode() const
+{
+  return mStage->GetViewMode();
+}
+
+void Core::SetStereoBase( float stereoBase )
+{
+  mStage->SetStereoBase( stereoBase );
+}
+
+float Core::GetStereoBase() const
+{
+  return mStage->GetStereoBase();
+}
+
+void Core::SetPixmapYInverted( bool yInverted )
+{
+  mRenderManager->SetPixmapYInverted( yInverted );
+}
+
+StagePtr Core::GetCurrentStage()
+{
+  return mStage.Get();
+}
+
+PlatformAbstraction& Core::GetPlatform()
+{
+  return mPlatform;
+}
+
+UpdateManager& Core::GetUpdateManager()
+{
+  return *(mUpdateManager);
+}
+
+RenderManager& Core::GetRenderManager()
+{
+  return *(mRenderManager);
+}
+
+NotificationManager& Core::GetNotificationManager()
+{
+  return *(mNotificationManager);
+}
+
+ResourceManager& Core::GetResourceManager()
+{
+  return *(mResourceManager);
+}
+
+ResourceClient& Core::GetResourceClient()
+{
+  return *(mResourceClient);
+}
+
+ImageFactory& Core::GetImageFactory()
+{
+  return *(mImageFactory);
+}
+
+ShaderFactory& Core::GetShaderFactory()
+{
+  return *(mShaderFactory);
+}
+
+GestureEventProcessor& Core::GetGestureEventProcessor()
+{
+  return *(mGestureEventProcessor);
+}
+
+RelayoutController& Core::GetRelayoutController()
+{
+  return *(mRelayoutController.Get());
+}
+
+void Core::CreateThreadLocalStorage()
+{
+  // a pointer to the ThreadLocalStorage object will be stored in TLS
+  // and automatically deleted when the thread is killed
+  new ThreadLocalStorage(this);
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/common/core-impl.h b/dali/internal/common/core-impl.h
new file mode 100644 (file)
index 0000000..8d130b4
--- /dev/null
@@ -0,0 +1,320 @@
+#ifndef __DALI_INTERNAL_CORE_H__
+#define __DALI_INTERNAL_CORE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/context-notifier.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/event/animation/animation-playlist-declarations.h>
+#include <dali/internal/event/common/stage-def.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/public-api/common/view-mode.h>
+#include <dali/integration-api/resource-policies.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class RenderController;
+class PlatformAbstraction;
+class GestureManager;
+class GlAbstraction;
+class GlSyncAbstraction;
+class SystemOverlay;
+class UpdateStatus;
+class RenderStatus;
+struct Event;
+struct TouchData;
+}
+
+namespace Internal
+{
+
+class NotificationManager;
+class AnimationPlaylist;
+class PropertyNotificationManager;
+class EventProcessor;
+class GestureEventProcessor;
+class ResourceClient;
+class ResourceManager;
+class ImageFactory;
+class ShaderFactory;
+class TouchResampler;
+class RelayoutController;
+
+namespace SceneGraph
+{
+class UpdateManager;
+class RenderManager;
+class DiscardQueue;
+}
+
+/**
+ * Internal class for Dali::Integration::Core
+ */
+class Core
+{
+public:
+
+  /**
+   * Create and initialise a new Core instance
+   */
+  Core( Integration::RenderController& renderController,
+        Integration::PlatformAbstraction& platform,
+        Integration::GlAbstraction& glAbstraction,
+        Integration::GlSyncAbstraction& glSyncAbstraction,
+        Integration::GestureManager& gestureManager,
+        ResourcePolicy::DataRetention dataRetentionPolicy );
+
+  /**
+   * Destructor
+   */
+  ~Core();
+
+  /**
+   * @copydoc Dali::Integration::Core::GetContextNotifier()
+   */
+  Integration::ContextNotifierInterface* GetContextNotifier();
+
+  /**
+   * @copydoc Dali::Integration::Core::ContextCreated()
+   */
+  void ContextCreated();
+
+  /**
+   * @copydoc Dali::Integration::Core::ContextDestroyed()
+   */
+  void ContextDestroyed();
+
+  /**
+   * @copydoc Dali::Integration::Core::RecoverFromContextLoss()
+   */
+  void RecoverFromContextLoss();
+
+  /**
+   * @copydoc Dali::Integration::Core::SurfaceResized(unsigned int, unsigned int)
+   */
+  void SurfaceResized(unsigned int width, unsigned int height);
+
+  /**
+   * @copydoc Dali::Integration::Core::SetDpi(unsigned int, unsigned int)
+   */
+  void SetDpi(unsigned int dpiHorizontal, unsigned int dpiVertical);
+
+  /**
+   * @copydoc Dali::Integration::Core::SetMinimumFrameTimeInterval(unsigned int)
+   */
+  void SetMinimumFrameTimeInterval(unsigned int interval);
+
+  /**
+   * @copydoc Dali::Integration::Core::Update()
+   */
+  void Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds, Integration::UpdateStatus& status );
+
+  /**
+   * @copydoc Dali::Integration::Core::Render()
+   */
+  void Render( Integration::RenderStatus& status );
+
+  /**
+   * @copydoc Dali::Integration::Core::Suspend()
+   */
+  void Suspend();
+
+  /**
+   * @copydoc Dali::Integration::Core::Resume()
+   */
+  void Resume();
+
+  /**
+   * @copydoc Dali::Integration::Core::SceneCreated()
+   */
+  void SceneCreated();
+
+  /**
+   * @copydoc Dali::Integration::Core::QueueEvent(const Integration::Event&)
+   */
+  void QueueEvent( const Integration::Event& event );
+
+  /**
+   * @copydoc Dali::Integration::Core::ProcessEvents()
+   */
+  void ProcessEvents();
+
+  /**
+   * @copydoc Dali::Integration::Core::UpdateTouchData(const Integration::TouchData&)
+   */
+  void UpdateTouchData(const Integration::TouchData& touch);
+
+  /**
+   * @copydoc Dali::Integration::Core::GetMaximumUpdateCount()
+   */
+  unsigned int GetMaximumUpdateCount() const;
+
+  /**
+   * @copydoc Dali::Integration::Core::GetSystemOverlay()
+   */
+  Integration::SystemOverlay& GetSystemOverlay();
+
+  // Stereoscopy
+
+  /**
+   * @copydoc Dali::Integration::Core::SetViewMode()
+   */
+  void SetViewMode( ViewMode viewMode );
+
+  /**
+   * @copydoc Dali::Integration::Core::GetViewMode()
+   */
+  ViewMode GetViewMode() const;
+
+  /**
+   * @copydoc Dali::Integration::Core::SetStereoBase()
+   */
+  void SetStereoBase( float stereoBase );
+
+  /**
+   * @copydoc Dali::Integration::Core::GetStereoBase()
+   */
+  float GetStereoBase() const;
+
+  // Pixmap
+
+  /**
+   * @copydoc Dali::Integration::Core::SetPixmapYInverted()
+   */
+  void SetPixmapYInverted( bool yInverted );
+
+private:  // for use by ThreadLocalStorage
+
+  /**
+   * Returns the current stage.
+   * @return A smart-pointer to the current stage.
+   */
+  StagePtr GetCurrentStage();
+
+  /**
+   * Returns the platform abstraction.
+   * @return A reference to the platform abstraction.
+   */
+  Integration::PlatformAbstraction& GetPlatform();
+
+  /**
+   * Returns the update manager.
+   * @return A reference to the update manager.
+   */
+  SceneGraph::UpdateManager& GetUpdateManager();
+
+  /**
+   * Returns the render manager.
+   * @return A reference to the render manager.
+   */
+  SceneGraph::RenderManager& GetRenderManager();
+
+  /**
+   * Returns the notification manager.
+   * @return A reference to the Notification Manager.
+   */
+  NotificationManager& GetNotificationManager();
+
+  /**
+   * Returns the Resource Manager.
+   * @return A reference to the Resource Manager.
+   */
+  ResourceManager& GetResourceManager();
+
+  /**
+   * Returns the Resource client.
+   * @return A reference to the Resource Client.
+   */
+  ResourceClient& GetResourceClient();
+
+  /**
+   * Returns the Image factory
+   * @return A reference to the Image factory.
+   */
+  ImageFactory& GetImageFactory();
+
+  /**
+   * Returns the Shader factory
+   * @return A reference to the Shader binary factory.
+   */
+  ShaderFactory& GetShaderFactory();
+
+  /**
+   * Returns the gesture event processor.
+   * @return A reference to the gesture event processor.
+   */
+  GestureEventProcessor& GetGestureEventProcessor();
+
+  /**
+   * Return the relayout controller
+   * @Return Return a reference to the relayout controller
+   */
+  RelayoutController& GetRelayoutController();
+
+private:
+
+  /**
+   * Undefined copy and assignment operators
+   */
+  Core(const Core& core);  // No definition
+  Core& operator=(const Core& core);  // No definition
+
+  /**
+   * Create Thread local storage
+   */
+  void CreateThreadLocalStorage();
+
+private:
+
+  Integration::RenderController&            mRenderController;            ///< Reference to Render controller to tell it to keep rendering
+  Integration::PlatformAbstraction&         mPlatform;                    ///< The interface providing platform specific services.
+
+  IntrusivePtr<Stage>                       mStage;                       ///< The current stage
+  GestureEventProcessor*                    mGestureEventProcessor;       ///< The gesture event processor
+  EventProcessor*                           mEventProcessor;              ///< The event processor
+  SceneGraph::UpdateManager*                mUpdateManager;               ///< Update manager
+  SceneGraph::RenderManager*                mRenderManager;               ///< Render manager
+  SceneGraph::DiscardQueue*                 mDiscardQueue;                ///< Used to cleanup nodes & resources when no longer in use.
+  ResourcePostProcessList*                  mResourcePostProcessQueue;    ///< Stores resource ids which require post processing after render
+  NotificationManager*                      mNotificationManager;         ///< Notification manager
+  AnimationPlaylistOwner                    mAnimationPlaylist;           ///< For 'Fire and forget' animation support
+  OwnerPointer<PropertyNotificationManager> mPropertyNotificationManager; ///< For safe signal emmision of property changed notifications
+  ImageFactory*                             mImageFactory;                ///< Image resource factory
+  ShaderFactory*                            mShaderFactory;               ///< Shader resource factory
+  ResourceClient*                           mResourceClient;              ///< Asynchronous Resource Loading
+  ResourceManager*                          mResourceManager;             ///< Asynchronous Resource Loading
+  TouchResampler*                           mTouchResampler;              ///< Resamples touches to correct frame rate.
+  IntrusivePtr< RelayoutController >        mRelayoutController;          ///< Size negotiation relayout controller
+
+  bool                                      mIsActive         : 1;        ///< Whether Core is active or suspended
+  bool                                      mProcessingEvent  : 1;        ///< True during ProcessEvents()
+
+  friend class ThreadLocalStorage;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CORE_H__
diff --git a/dali/internal/common/fixed-size-memory-pool.cpp b/dali/internal/common/fixed-size-memory-pool.cpp
new file mode 100644 (file)
index 0000000..8b69193
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/fixed-size-memory-pool.h>
+
+// INTERNAL HEADERS
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Private implementation class
+ */
+struct FixedSizeMemoryPool::Impl
+{
+  /**
+   * @brief Struct to represent a block of memory from which allocations can be made.
+   *
+   * The block forms a linked list.
+   */
+  struct Block
+  {
+    void* blockMemory;      ///< The allocated memory from which allocations can be made
+    Block* nextBlock;       ///< The next block in the linked list
+
+    /**
+     * @brief Construct a new block with given size
+     *
+     * @param size The size of the memory block to allocate in bytes. Must be non-zero.
+     */
+    Block( SizeType size )
+    : nextBlock( NULL )
+    {
+      blockMemory = ::operator new( size );
+      DALI_ASSERT_ALWAYS( blockMemory && "Out of memory" );
+    }
+
+    /**
+     * @brief Destructor
+     */
+    ~Block()
+    {
+      ::operator delete( blockMemory );
+    }
+
+  private:
+    // Undefined
+    Block( const Block& block );
+
+    // Undefined
+    Block& operator=( const Block& block );
+  };
+
+  /**
+   * @brief Constructor
+   */
+  Impl( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
+  :  mFixedSize( fixedSize ),
+     mMemoryBlocks( initialCapacity * mFixedSize ),
+     mMaximumBlockCapacity( maximumBlockCapacity ),
+     mCurrentBlock( &mMemoryBlocks ),
+     mCurrentBlockCapacity( initialCapacity ),
+     mCurrentBlockSize( 0 ),
+     mDeletedObjects( NULL )
+  {
+    // We need enough room to store the deleted list in the data
+    DALI_ASSERT_DEBUG( mFixedSize >= sizeof( void* ) );
+  }
+
+  /**
+   * @brief Destructor
+   */
+  ~Impl()
+  {
+    // Clean up memory block linked list (mMemoryBlocks will be auto-destroyed by its destructor)
+    Block* block = mMemoryBlocks.nextBlock;
+    while( block )
+    {
+      Block* nextBlock = block->nextBlock;
+      delete block;
+      block = nextBlock;
+    }
+  }
+
+  /**
+   * @brief Allocate a new block for allocating memory from
+   */
+  void AllocateNewBlock()
+  {
+    // Double capacity for the new block
+    SizeType size = mCurrentBlockCapacity * 2;
+    if( size > mMaximumBlockCapacity || size < mCurrentBlockCapacity )    // Check for overflow of size type
+    {
+      size = mMaximumBlockCapacity;
+    }
+
+    mCurrentBlockCapacity = size;
+
+    // Allocate
+    Block* block = new Block( mCurrentBlockCapacity * mFixedSize );
+    mCurrentBlock->nextBlock = block;       // Add to end of linked list
+    mCurrentBlock = block;
+
+    mCurrentBlockSize = 0;
+  }
+
+  SizeType mFixedSize;                ///< The size of each allocation in bytes
+
+  Block mMemoryBlocks;                ///< Linked list of allocated memory blocks
+  SizeType mMaximumBlockCapacity;     ///< The maximum allowed capacity of allocations in a new memory block
+
+  Block* mCurrentBlock;               ///< Pointer to the active block
+  SizeType mCurrentBlockCapacity;     ///< The maximum number of allocations that can be allocated for the current block
+  SizeType mCurrentBlockSize;         ///< The number of allocations allocated to the current block
+
+  void* mDeletedObjects;              ///< Pointer to the head of the list of deleted objects. The addresses are stored in the allocated memory blocks.
+};
+
+FixedSizeMemoryPool::FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity, SizeType maximumBlockCapacity )
+{
+  mImpl = new Impl( fixedSize, initialCapacity, maximumBlockCapacity );
+}
+
+FixedSizeMemoryPool::~FixedSizeMemoryPool()
+{
+  delete mImpl;
+}
+
+void* FixedSizeMemoryPool::Allocate()
+{
+  // First, recycle deleted objects
+  if( mImpl->mDeletedObjects )
+  {
+    void* recycled = mImpl->mDeletedObjects;
+    mImpl->mDeletedObjects = *( reinterpret_cast< void** >( mImpl->mDeletedObjects ) );  // Pop head off front of deleted objects list
+    return recycled;
+  }
+
+  // Check if current block is full
+  if( mImpl->mCurrentBlockSize >= mImpl->mCurrentBlockCapacity )
+  {
+    mImpl->AllocateNewBlock();
+  }
+
+  // Placement new the object in block memory
+  unsigned char* objectAddress = static_cast< unsigned char* >( mImpl->mCurrentBlock->blockMemory );
+  objectAddress += mImpl->mCurrentBlockSize * mImpl->mFixedSize;
+  mImpl->mCurrentBlockSize++;
+
+  return objectAddress;
+}
+
+void FixedSizeMemoryPool::Free( void* memory )
+{
+  // Add memory to head of deleted objects list. Store next address in the same memory space as the old object.
+  *( reinterpret_cast< void** >( memory ) ) = mImpl->mDeletedObjects;
+  mImpl->mDeletedObjects = memory;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/common/fixed-size-memory-pool.h b/dali/internal/common/fixed-size-memory-pool.h
new file mode 100644 (file)
index 0000000..4389106
--- /dev/null
@@ -0,0 +1,109 @@
+#ifndef __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__
+#define __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+#include <cstddef>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Calculate the size of a type taking alignment into account
+ */
+template< typename T >
+struct TypeSizeWithAlignment
+{
+  ///< The size of the type with alignment taken into account
+  static const size_t size = ( ( sizeof( T ) + sizeof( void* ) - 1 ) / sizeof( void* ) ) * sizeof( void* );
+};
+
+/**
+ * @brief Memory pool for a given fixed size of memory.
+ *
+ * The pool will allocate and reclaim blocks of memory without concern for what is
+ * stored in them. This means it is up to the client to construct/destruct objects
+ * and hence determine what data type is stored in the memory block. See FixedSizeObjectAllocator
+ * below for an example client for creating objects of a given type. It is also up to the client
+ * to ensure that the size of the block takes memory alignment into account for the
+ * type of data they wish to store in the block. The TypeSizeWithAlignment<T> template
+ * can be useful for determining the size of memory aligned blocks for a given type.
+ */
+class FixedSizeMemoryPool
+{
+public:
+
+  typedef uint32_t SizeType;
+
+public:
+
+  /**
+   * @brief Constructor.
+   *
+   * @param fixedSize The fixed size of each memory allocation. Use TypeSizeWithAlignment if aligned memory is required.
+   * @param initialCapacity The initial size of the memory pool. Defaults to a small value (32) after
+   *                        which the capacity will double as needed.
+   * @param maximumBlockCapacity The maximum size that a new block of memory can be allocated. Defaults to
+   *                             a large value (1024 * 1024 = 1048576).
+   */
+  explicit FixedSizeMemoryPool( SizeType fixedSize, SizeType initialCapacity = 32, SizeType maximumBlockCapacity = 1048576 );
+
+  /**
+   * @brief Destructor.
+   */
+  ~FixedSizeMemoryPool();
+
+  /**
+   * @brief Allocate a new fixed size block of memory
+   *
+   * @return Return the newly allocated memory
+   */
+  void* Allocate();
+
+  /**
+   * @brief Delete a block of memory for the allocation that has been allocated by this memory pool
+   *
+   * @param memory The memory to be deleted. Must have been allocated by this memory pool
+   */
+  void Free( void* memory );
+
+private:
+
+  // Undefined
+  FixedSizeMemoryPool( const FixedSizeMemoryPool& fixedSizeMemoryPool );
+
+  // Undefined
+  FixedSizeMemoryPool& operator=( const FixedSizeMemoryPool& fixedSizeMemoryPool );
+
+private:
+
+  struct Impl;
+  Impl* mImpl;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif /* __DALI_INTERNAL_FIXED_SIZE_MEMORY_POOL_H__ */
diff --git a/dali/internal/common/image-attributes.cpp b/dali/internal/common/image-attributes.cpp
new file mode 100644 (file)
index 0000000..134debc
--- /dev/null
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/image-attributes.h>
+
+// EXTERNAL INCLUDES
+#include <cmath>
+
+namespace Dali
+{
+namespace Internal
+{
+
+const ImageAttributes ImageAttributes::DEFAULT_ATTRIBUTES;
+
+struct ImageAttributes::ImageAttributesImpl
+{
+  ImageAttributesImpl()
+  :  width(0),
+     height(0),
+     scaling(Dali::FittingMode::SHRINK_TO_FIT),
+     filtering(SamplingMode::BOX),
+     mOrientationCorrection(false)
+  {
+  }
+
+  ~ImageAttributesImpl()
+  {
+  }
+
+  ImageAttributesImpl(const ImageAttributesImpl& rhs)
+  : width( rhs.width ),
+    height( rhs.height ),
+    scaling( rhs.scaling ),
+    filtering( rhs.filtering ),
+    mOrientationCorrection( rhs.mOrientationCorrection )
+  {
+  }
+
+  ImageAttributesImpl& operator=(const ImageAttributesImpl& rhs)
+  {
+    if (this != &rhs)
+    {
+      width = rhs.width;
+      height = rhs.height;
+      scaling = rhs.scaling;
+      filtering = rhs.filtering;
+
+      mOrientationCorrection = rhs.mOrientationCorrection;
+    }
+
+    return *this;
+  }
+
+  unsigned int  width : 16;       ///< image width in pixels
+  unsigned int  height : 16;      ///< image height in pixels
+  ScalingMode   scaling : 3;      ///< scaling option, ShrinkToFit is default
+  FilterMode    filtering : 3;    ///< filtering option. Box is the default
+  bool          mOrientationCorrection : 1; ///< If true, image pixels are reordered according to orientation metadata on load.
+  bool          isDistanceField : 1;  ///< true, if the image is a distancefield. Default is false.
+};
+
+
+ImageAttributes::ImageAttributes()
+: impl( new ImageAttributesImpl() )
+{
+}
+
+ImageAttributes::ImageAttributes(const ImageAttributes& rhs)
+: impl( new ImageAttributesImpl(*rhs.impl) )
+{
+}
+
+ImageAttributes& ImageAttributes::operator=(const ImageAttributes& rhs)
+{
+  *impl = *rhs.impl;
+
+  return *this;
+}
+
+ImageAttributes::~ImageAttributes()
+{
+  delete impl;
+}
+
+void ImageAttributes::SetSize(unsigned int width, unsigned int height)
+{
+  impl->width = width;
+  impl->height = height;
+}
+
+void ImageAttributes::SetSize( const Size& size )
+{
+  impl->width = size.width;
+  impl->height = size.height;
+}
+
+void ImageAttributes::SetScalingMode( ScalingMode scale )
+{
+  impl->scaling = scale;
+}
+
+void ImageAttributes::SetFilterMode( FilterMode filtering )
+{
+  impl->filtering = filtering;
+}
+
+void ImageAttributes::SetOrientationCorrection(const bool enabled)
+{
+  impl->mOrientationCorrection = enabled;
+}
+
+void ImageAttributes::Reset( ImageDimensions dimensions, ScalingMode scaling, FilterMode sampling, bool orientationCorrection )
+{
+  impl->width = dimensions.GetWidth();
+  impl->height = dimensions.GetHeight();
+  impl->scaling = scaling;
+  impl->filtering = sampling;
+  impl->mOrientationCorrection = orientationCorrection;
+}
+
+unsigned int ImageAttributes::GetWidth() const
+{
+  return impl->width;
+}
+
+unsigned int ImageAttributes::GetHeight() const
+{
+  return impl->height;
+}
+
+Size ImageAttributes::GetSize() const
+{
+  return Size(impl->width, impl->height);
+}
+
+ImageAttributes::ScalingMode ImageAttributes::GetScalingMode() const
+{
+  return impl->scaling;
+}
+
+ImageAttributes::FilterMode ImageAttributes::GetFilterMode() const
+{
+  return impl->filtering;
+}
+
+bool ImageAttributes::GetOrientationCorrection() const
+{
+  return impl->mOrientationCorrection;
+}
+
+ImageAttributes ImageAttributes::New()
+{
+  return ImageAttributes();
+}
+
+ImageAttributes ImageAttributes::New(unsigned int imageWidth, unsigned int imageHeight)
+{
+  ImageAttributes attributes;
+  attributes.impl->width = imageWidth;
+  attributes.impl->height = imageHeight;
+  return attributes;
+}
+
+/**
+ * Less then comparison operator.
+ * @param [in] a parameter tested
+ * @param [in] b parameter tested
+ */
+bool operator<(const ImageAttributes& a, const ImageAttributes& b)
+{
+  // Bail out if one is distance field and the other is not.
+  if (a.impl->isDistanceField != b.impl->isDistanceField)
+  {
+    return a.impl->isDistanceField < b.impl->isDistanceField;
+  }
+
+  if (a.impl->width != b.impl->width)
+  {
+    return a.impl->width < b.impl->width;
+  }
+
+  if (a.impl->height != b.impl->height)
+  {
+    return a.impl->height < b.impl->height;
+  }
+
+  if (a.impl->mOrientationCorrection != b.impl->mOrientationCorrection)
+  {
+    return a.impl->mOrientationCorrection < b.impl->mOrientationCorrection;
+  }
+
+  if (a.impl->scaling != b.impl->scaling)
+  {
+    return a.impl->scaling < b.impl->scaling;
+  }
+
+  if (a.impl->filtering != b.impl->filtering)
+  {
+    return a.impl->filtering < b.impl->filtering;
+  }
+
+  // they are equal
+  return false;
+}
+
+/**
+ * Equal to comparison operator.
+ * @param [in] a parameter tested for equality
+ * @param [in] b parameter tested for equality
+ */
+bool operator==(const ImageAttributes& a, const ImageAttributes& b)
+{
+  return a.impl->width                  == b.impl->width       &&
+         a.impl->height                 == b.impl->height      &&
+         a.impl->mOrientationCorrection == b.impl->mOrientationCorrection &&
+         a.impl->scaling                == b.impl->scaling     &&
+         a.impl->filtering              == b.impl->filtering;
+}
+
+/**
+ * Not equal to comparison operator.
+ * @param [in] a parameter tested for equality
+ * @param [in] b parameter tested for equality
+ */
+bool operator!=(const ImageAttributes& a, const ImageAttributes& b)
+{
+  return !(a == b);
+}
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/common/image-attributes.h b/dali/internal/common/image-attributes.h
new file mode 100644 (file)
index 0000000..a0803cb
--- /dev/null
@@ -0,0 +1,312 @@
+#ifndef __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__
+#define __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+/**
+ * @brief Describes Image properties like dimensions and pixel format and
+ * operations to be applied to images during the load process.
+ *
+ * ImageAttributes is used to define a set of properties of an image and a
+ * sequence of operations to be applied when loading it.
+ *
+ * The overall order of operations which can be applied is:
+ *   1. Determine the desired dimensions for the final bitmap.
+ *   2. Scale the image to fit the desired dimensions.
+ *
+ * The default for each stage is to do nothing.
+ * To enable a calculation of desired final image dimensions and fitting to it, SetSize() must be called.
+ *
+ * The loader does not guarantee to rescale a loaded image to the exact desired dimensions, but it will make a best effort to downscale images.
+ * The fitting to destination dimensions controlled by the ScalingMode may choose to fit to a larger area with an equivalent aspect ratio.
+ * If the requested dimensions are larger than the loaded ones, it will never upscale on load to fill them but will instead fit to smaller dimensions of identical aspect ratio.
+ * This is transparent to an application as the upscaling can happen during rendering.
+ *
+ * To enable scaling of images on load, desired dimensions must be set using SetSize().
+ * Only one of the dimensions need be supplied, in which case, the other is calculated based on the aspect ratio of the raw loaded image.
+ * The desired dimensions 2-tuple 'd' is determined as follows for loaded image dimensions 'l' and 's', the dimensions tuple set with SetSize():
+ *   *  `d = s, if s.x != 0 & s.y != 0, else:`
+ *   *  `d = [s.x, s.x * (l.y / l.x)], if s.x != 0 & s.y = 0, else:`
+ *   *  `d = [s.y * (l.x / l.y), s.y], if s.x = 0 & s.y != 0, else:`
+ *   *  `d = l, otherwise.`
+ *
+ * Use cases for scaling images on load include:
+ *   1. Full-screen image display: Limit loaded image resolution to device resolution using ShrinkToFit mode.
+ *   2. Thumbnail gallery grid: Limit loaded image resolution to screen tile using ScaleToFill mode.
+ *   3. Image columns: Limit loaded image resolution to column width using FitWidth mode.
+ *   4. Image rows: Limit loaded image resolution to row height using FitHeight mode.
+ *
+ * @note The aspect ratio of image contents is preserved by all scaling modes, so for example squares in input images stay square after loading.
+ */
+class ImageAttributes
+{
+public:
+
+  /**
+   * @brief Scaling options, used when resizing images on load to fit desired dimensions.
+   *
+   * A scaling mode controls the region of a loaded image to be mapped to the
+   * desired image rectangle specified using ImageAttributes.SetSize().
+   * All scaling modes preserve the aspect ratio of the image contents.
+   */
+  typedef Dali::FittingMode::Type ScalingMode;
+
+  /**
+   * @brief Filtering options, used when resizing images on load to sample original pixels.
+   *
+   * A FilterMode controls how pixels in the raw image on-disk are sampled and
+   * combined to generate each pixel of the destination loaded image.
+   *
+   * @note NoFilter and Box modes do not guarantee that the loaded pixel array
+   * exactly matches the rectangle specified by the desired dimensions and
+   * ScalingMode, but all other filter modes do if the desired dimensions are
+   * `<=` the raw dimensions of the image file.
+   */
+  typedef Dali::SamplingMode::Type FilterMode;
+
+  static const ImageAttributes DEFAULT_ATTRIBUTES; ///< Default attributes have no size
+
+  /**
+   * @brief Default constructor, initializes to default values.
+   */
+  ImageAttributes();
+
+  /**
+   * @brief This copy constructor is required for correctly copying internal implementation.
+   *
+   * @param [in] rhs A reference to the copied handle
+   */
+  ImageAttributes(const ImageAttributes& rhs);
+
+  /**
+   * @brief This assignment operator is required for correctly handling the internal implementation.
+   *
+   * @param [in] rhs  A reference to the copied handle
+   * @return a reference to this object
+   */
+  ImageAttributes& operator=(const ImageAttributes& rhs);
+
+  /**
+   * @brief Default destructor.
+   */
+  ~ImageAttributes();
+
+  /**
+   * @brief Create an initialised image attributes object.
+   *
+   * @return A handle to a newly allocated object
+   */
+  static ImageAttributes New();
+
+  /**
+   * @brief Create an initialised image attributes object.
+   *
+   * @param [in] width         desired width.
+   * @param [in] height        desired height
+   * @return A handle to a newly allocated object
+   */
+   static ImageAttributes New(unsigned int width, unsigned int height);
+
+  /**
+   * @brief Set the size properties.
+   *
+   * By default width and height are set to zero which means the image loaded has the original size.
+   * If one dimension is set to non-zero, but the other zeroed, the unspecified one is derived from
+   * the one that is set and the aspect ratio of the image.
+   *
+   * @param [in] width  desired width.
+   * @param [in] height desired height
+   */
+  void SetSize(unsigned int width, unsigned int height);
+
+  /**
+   * @brief Set the image dimension properties.
+   *
+   * By default, width and height are set to zero which means the image loaded has the original size.
+   * If one dimension is set to non-zero, but the other zeroed, the unspecified one is derived from
+   * the one that is set and the aspect ratio of the image.
+   *
+   * @param [in] size desired size.
+   */
+  void SetSize( const Size& size );
+
+  /**
+   * @brief Set the scale field of the image attributes.
+   *
+   * By default, ShrinkToFit is set.
+   * @param [in] scalingMode The desired scaling mode
+   */
+  void SetScalingMode( ScalingMode scalingMode );
+
+  /**
+   * @brief Setter for the FilterMode.
+   * By default, Box is set.
+   * @param [in] filterMode The desired filter mode.
+   */
+  void SetFilterMode( FilterMode filterMode );
+
+  /**
+   * @brief Set whether the image will be rotated/flipped back into portrait orientation.
+   *
+   * This will only be necessary if metadata indicates that the
+   * image has a different viewing orientation.
+   *
+   * This metadata, optionally present in formats that use exif for example,
+   * can encode the physical orientation of the camera which took the picture,
+   * establishing which directions in the image correspond to real-world "up"
+   * and the horizon.
+   * By default the metadata is ignored, but if this function is called with
+   * the value "true", the pixels of an image are reordered at load time to reflect
+   * the orientation in the metadata.
+   *
+   * @param [in] enabled If true, the image orientation metadata will be used to
+   *                     transform the pixels of the image as laid-out in memory.
+   */
+  void SetOrientationCorrection(bool enabled);
+
+  /**
+   * @brief Change all members in one operation.
+   * @param[in] dimensions width and height
+   * @param[in] scaling Scaling mode for resizing loads.
+   * @param[in] sampling Sampling mode.
+   * @param[in] orientation Orientation correction toggle.
+   */
+  void Reset( ImageDimensions dimensions = ImageDimensions(0, 0), ScalingMode scaling = ScalingMode(), FilterMode sampling = FilterMode(), bool orientationCorrection = true );
+
+
+  /**
+   * @brief Return the width currently represented by the attribute.
+   *
+   * @return width
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * @brief Return the height currently represented by the attribute.
+   *
+   * @return height
+   */
+  unsigned int GetHeight() const;
+
+  /**
+   * @brief Return the size currently represented by the attribute.
+   *
+   * @return size
+   */
+  Size GetSize() const;
+
+  /**
+   * @brief Return the scale currently represented by the attribute.
+   *
+   * @return scale
+   */
+  ScalingMode GetScalingMode() const;
+
+  /**
+   * @brief Getter for the FilterMode
+   *
+   * @return The FilterMode previously set, or the default value if none has
+   *         been.
+   */
+  FilterMode GetFilterMode() const;
+
+  /**
+   * @brief Whether to correct for physical orientation of an image.
+   *
+   * @return Whether image pixels should be transformed according to the
+   *         orientation metadata, if any.
+   */
+  bool GetOrientationCorrection() const;
+
+  /**
+   * @brief Less then comparison operator.
+   *
+   * @param [in] a parameter tested
+   * @param [in] b parameter tested
+   * @return true if a is less than b
+   */
+  friend bool operator<(const ImageAttributes& a, const ImageAttributes& b);
+
+  /**
+   * @brief Equal to comparison operator.
+   *
+   * @param [in] a parameter tested for equality
+   * @param [in] b parameter tested for equality
+   * @return true if a is equal to b
+   */
+  friend bool operator==(const ImageAttributes& a, const ImageAttributes& b);
+
+  /**
+   * @brief Not equal to comparison operator.
+   *
+   * @param [in] a parameter tested for equality
+   * @param [in] b parameter tested for equality
+   * @return true if a is not equal to b
+   */
+  friend bool operator!=(const ImageAttributes& a, const ImageAttributes& b);
+
+private:
+  struct ImageAttributesImpl;
+  ImageAttributesImpl* impl; ///< Implementation pointer
+};
+
+/**
+ * @brief Less then comparison operator.
+ *
+ * @param [in] a parameter tested
+ * @param [in] b parameter tested
+ * @return true if a is less than b
+ */
+bool operator<(const ImageAttributes& a, const ImageAttributes& b);
+
+/**
+ * @brief Equal to comparison operator.
+ *
+ * @param [in] a parameter tested for equality
+ * @param [in] b parameter tested for equality
+ * @return true if a is equal to b
+ */
+bool operator==(const ImageAttributes& a, const ImageAttributes& b);
+
+/**
+ * @brief Not equal to comparison operator.
+ *
+ * @param [in] a parameter tested for equality
+ * @param [in] b parameter tested for equality
+ * @return true if a is not equal to b
+ */
+bool operator!=(const ImageAttributes& a, const ImageAttributes& b);
+
+} // namespace Internal
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_ATTRIBUTES_H__
diff --git a/dali/internal/common/image-sampler.cpp b/dali/internal/common/image-sampler.cpp
new file mode 100644 (file)
index 0000000..036a69a
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/image-sampler.h>
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace ImageSampler
+{
+
+namespace
+{
+
+// @todo MESH_REWORK Remove file after image removal
+
+// Adjust these shift sizes if the FilterMode enum grows
+const int MINIFY_BIT_SHIFT  = 0;    // Room for 16
+const int MAGNIFY_BIT_SHIFT = 4;
+
+const int MASK_MINIFY_FILTER    = 0x0000000F;
+const int MASK_MAGNIFY_FILTER   = 0x000000F0;
+
+const unsigned int FILTER_MODE_COUNT = 4;
+
+FilterMode::Type FILTER_MODE_OPTIONS[ FILTER_MODE_COUNT ] =
+  { FilterMode::NONE,
+    FilterMode::DEFAULT,
+    FilterMode::NEAREST,
+    FilterMode::LINEAR };
+
+} // namespace
+
+/**
+ * Utility to store one of the FilterMode values.
+ * @param[out] options A bitmask used to store the FilterMode values.
+ * @param[in] factor The FilterMode value.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ */
+void StoreFilterMode( unsigned int& options, FilterMode::Type mode, int bitShift )
+{
+  // Start shifting from 1 as 0 is the unassigned state
+  switch ( mode )
+  {
+    case FilterMode::NONE:
+    {
+      // Nothing to do
+      break;
+    }
+    case FilterMode::DEFAULT:
+    {
+      options |= ( 1u << bitShift );
+      break;
+    }
+    case FilterMode::NEAREST:
+    {
+      options |= ( 2u << bitShift );
+      break;
+    }
+    case FilterMode::LINEAR:
+    {
+      options |= ( 3u << bitShift );
+      break;
+    }
+  }
+}
+
+/**
+ * Utility to retrieve one of the FilterMode values.
+ * @param[in] options A bitmask of filter values.
+ * @param[in] mask The used to mask unwanted values.
+ * @param[in] bitshift Used to shift to the correct part of options.
+ * @return Return the filter mode.
+ */
+FilterMode::Type RetrieveFilterMode( unsigned int options, int mask, int bitShift )
+{
+  unsigned int index = options & mask;
+
+  index = ( index >> bitShift );    // Zero based index for array
+
+  DALI_ASSERT_DEBUG( index < FILTER_MODE_COUNT );
+
+  return FILTER_MODE_OPTIONS[ index ];
+}
+
+unsigned int PackBitfield( FilterMode::Type minify, FilterMode::Type magnify )
+{
+  unsigned int bitfield = 0;
+  StoreFilterMode( bitfield, minify, MINIFY_BIT_SHIFT );
+  StoreFilterMode( bitfield, magnify, MAGNIFY_BIT_SHIFT );
+  return bitfield;
+}
+
+FilterMode::Type GetMinifyFilterMode( unsigned int bitfield )
+{
+  return RetrieveFilterMode( bitfield, MASK_MINIFY_FILTER, MINIFY_BIT_SHIFT );
+}
+
+FilterMode::Type GetMagnifyFilterMode( unsigned int bitfield )
+{
+  return RetrieveFilterMode( bitfield, MASK_MAGNIFY_FILTER, MAGNIFY_BIT_SHIFT );
+}
+
+} // namespace ImageSampler
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/common/image-sampler.h b/dali/internal/common/image-sampler.h
new file mode 100644 (file)
index 0000000..2ebd5a4
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef __DALI_IMAGE_SAMPLER_H__
+#define __DALI_IMAGE_SAMPLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/sampling.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * ImageSampler represents a set of sampling settings that can be applied to a texture.
+ */
+namespace ImageSampler
+{
+  /**
+   * @brief Pack the filter mode into a bitfield.
+   *
+   * @param[in] minify The minification filter.
+   * @param[in] magnify The magnification filter.
+   * @return Return the packed bitfield.
+   */
+   unsigned int PackBitfield( FilterMode::Type minify, FilterMode::Type magnify );
+
+   /**
+   * @brief Return the minification filter from a packed bitfield.
+   *
+   * @return Return the minification filter.
+   */
+   FilterMode::Type GetMinifyFilterMode( unsigned int bitfield );
+
+   /**
+   * @brief Return the magnification filter from a packed bitfield.
+   *
+   * @return Return the magnification filter.
+   */
+   FilterMode::Type GetMagnifyFilterMode( unsigned int bitfield );
+
+} // namespace ImageSampler
+
+} // namespace Internal
+
+} // namespace Dali
+
+
+#endif // __DALI_INTERNAL_IMAGE_SAMPLER_H__
+
+
+
diff --git a/dali/internal/common/internal-constants.cpp b/dali/internal/common/internal-constants.cpp
new file mode 100644 (file)
index 0000000..bbbd31b
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/internal-constants.h>
+
+namespace Dali
+{
+
+const float Internal::FULLY_OPAQUE      = 0.99f;
+const float Internal::FULLY_TRANSPARENT = 0.01f;
+
+} // namespace Dali
diff --git a/dali/internal/common/internal-constants.h b/dali/internal/common/internal-constants.h
new file mode 100644 (file)
index 0000000..b0b3a75
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __DALI_INTERNAL_CONSTANTS_H__
+#define __DALI_INTERNAL_CONSTANTS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// Constants used by renderers and actors to determine if something is visible.
+extern const float FULLY_OPAQUE;      ///< Alpha values must drop below this, before an object is considered to be transparent.
+extern const float FULLY_TRANSPARENT; ///< Alpha values must rise above this, before an object is considered to be visible.
+
+} // namespace Internal
+
+} // namespace Dali
+
+
+#endif // __DALI_INTERNAL_CONSTANTS_H__
diff --git a/dali/internal/common/memory-pool-object-allocator.h b/dali/internal/common/memory-pool-object-allocator.h
new file mode 100644 (file)
index 0000000..0349cf8
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__
+#define __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/fixed-size-memory-pool.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Helper for allocating/deallocating objects using a memory pool.
+ *
+ * This is a helper class for creating and destroying objects of a single given type.
+ * The type may be a class or POD.
+ *
+ */
+template< typename T >
+class MemoryPoolObjectAllocator
+{
+public:
+
+  /**
+   * @brief Constructor
+   */
+  MemoryPoolObjectAllocator()
+  : mPool( NULL )
+  {
+    ResetMemoryPool();
+  }
+
+  /**
+   * @brief Destructor
+   */
+  ~MemoryPoolObjectAllocator()
+  {
+    delete mPool;
+  }
+
+  /**
+   * @brief Allocate from the memory pool
+   *
+   * @return Return the allocated object
+   */
+  T* Allocate()
+  {
+    return new ( mPool->Allocate() ) T();
+  }
+
+  /**
+   * @brief Allocate a block of memory from the memory pool of the appropriate size to
+   *        store an object of type T. This is usually so the memory can be used in a
+   *        placement new for an object of type T with a constructor that takes multiple
+   *        parameters.
+   *
+   * @return Return the allocated memory block
+   */
+  void* AllocateRaw()
+  {
+    return mPool->Allocate();
+  }
+
+  /**
+   * @brief Return the object to the memory pool
+   *
+   * @param object Pointer to the object to delete
+   */
+  void Free( T* object )
+  {
+    object->~T();
+
+    mPool->Free( object );
+  }
+
+  /**
+   * @brief Reset the memory pool, unloading all block memory previously allocated
+   */
+  void ResetMemoryPool()
+  {
+    if( mPool )
+    {
+      delete mPool;
+    }
+
+    mPool = new FixedSizeMemoryPool( TypeSizeWithAlignment< T >::size );
+  }
+
+private:
+
+  // Undefined
+  MemoryPoolObjectAllocator( const MemoryPoolObjectAllocator& memoryPoolObjectAllocator );
+
+  // Undefined
+  MemoryPoolObjectAllocator& operator=( const MemoryPoolObjectAllocator& memoryPoolObjectAllocator );
+
+private:
+
+  FixedSizeMemoryPool* mPool;      ///< Memory pool from which allocations are made
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif /* __DALI_INTERNAL_MEMORY_POOL_OBJECT_ALLOCATOR_H__ */
diff --git a/dali/internal/common/message-buffer.cpp b/dali/internal/common/message-buffer.cpp
new file mode 100644 (file)
index 0000000..22822aa
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/common/message-buffer.h>
+
+// EXTERNAL INCLUDES
+#include <limits>
+#include <cstdlib>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace // unnamed namespace
+{
+
+// Increase capacity by 1.5 when buffer limit reached
+const unsigned int INCREMENT_NUMERATOR   = 3u;
+const unsigned int INCREMENT_DENOMINATOR = 2u;
+
+const unsigned int MESSAGE_SIZE_FIELD = 1u; // Size required to mark the message size
+const unsigned int MESSAGE_END_FIELD  = 1u; // Size required to mark the end of messages
+
+const unsigned int MESSAGE_SIZE_PLUS_END_FIELD = MESSAGE_SIZE_FIELD + MESSAGE_END_FIELD;
+
+const unsigned int MAX_DIVISION_BY_WORD_REMAINDER = sizeof(Dali::Internal::MessageBuffer::WordType) - 1u; // For word alignment on ARM
+const unsigned int WORD_SIZE = sizeof(Dali::Internal::MessageBuffer::WordType);
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+MessageBuffer::MessageBuffer( std::size_t initialCapacity )
+: mInitialCapacity( initialCapacity / WORD_SIZE ),
+  mData( NULL ),
+  mNextSlot( NULL ),
+  mCapacity( 0 ),
+  mSize( 0 )
+{
+}
+
+MessageBuffer::~MessageBuffer()
+{
+  free( mData );
+}
+
+unsigned int* MessageBuffer::ReserveMessageSlot( std::size_t size )
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  DALI_ASSERT_DEBUG( 0 != size );
+
+  // Number of aligned words required to handle a message of size in bytes
+  std::size_t requestedSize = (size + MAX_DIVISION_BY_WORD_REMAINDER) / WORD_SIZE;
+  std::size_t requiredSize = requestedSize + MESSAGE_SIZE_PLUS_END_FIELD;
+
+  // Keep doubling the additional capacity until we have enough
+  std::size_t nextCapacity = mCapacity ? mCapacity : mInitialCapacity;
+
+  if ( (nextCapacity - mSize) < requiredSize )
+  {
+    nextCapacity = nextCapacity * INCREMENT_NUMERATOR / INCREMENT_DENOMINATOR;
+
+    // Something has gone badly wrong if requiredSize is this big
+    DALI_ASSERT_DEBUG( (nextCapacity - mSize) > requiredSize );
+  }
+
+  if ( nextCapacity > mCapacity )
+  {
+    IncreaseCapacity( nextCapacity );
+  }
+
+  // Now reserve the slot
+  WordType* slot = mNextSlot;
+
+  *slot++ = requestedSize; // Object size marker is stored in first word
+
+  mSize += requestedSize + MESSAGE_SIZE_FIELD;
+  mNextSlot = mData + mSize;
+
+  // End marker
+  *mNextSlot = 0;
+
+  // @todo Remove cast & change all messages to use WordType instead
+  return reinterpret_cast<unsigned int*>(slot);
+}
+
+std::size_t MessageBuffer::GetCapacity() const
+{
+  return mCapacity * WORD_SIZE;
+}
+
+MessageBuffer::Iterator MessageBuffer::Begin() const
+{
+  if ( 0 != mSize )
+  {
+    return Iterator( mData );
+  }
+
+  return Iterator( NULL );
+}
+
+void MessageBuffer::Reset()
+{
+  // All messages have been processed, reset the buffer
+  mSize = 0;
+  mNextSlot = mData;
+}
+
+void MessageBuffer::IncreaseCapacity( std::size_t newCapacity )
+{
+  DALI_ASSERT_DEBUG( newCapacity > mCapacity );
+
+  if ( mData )
+  {
+    // Often this avoids the need to copy memory
+
+    WordType* oldData = mData;
+    mData = reinterpret_cast<WordType*>( realloc( mData, newCapacity * WORD_SIZE ) );
+
+    // if realloc fails the old data is still valid
+    if( !mData )
+    {
+      // TODO: Process message queue to free up some data?
+      free(oldData);
+      DALI_ASSERT_DEBUG( false && "Realloc failed we're out of memory!" );
+    }
+  }
+  else
+  {
+    mData = reinterpret_cast<WordType*>( malloc( newCapacity * WORD_SIZE ) );
+  }
+  DALI_ASSERT_ALWAYS( NULL != mData );
+
+  mCapacity = newCapacity;
+  mNextSlot = mData + mSize;
+}
+
+MessageBuffer::Iterator::Iterator(WordType* current)
+: mCurrent(current),
+  mMessageSize(0)
+{
+  if( NULL != mCurrent )
+  {
+    // The first word is the size of the following object
+    mMessageSize = *mCurrent++;
+  }
+}
+
+MessageBuffer::Iterator::Iterator(const Iterator& copy)
+: mCurrent( copy.mCurrent ),
+  mMessageSize( copy.mMessageSize )
+{
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/common/message-buffer.h b/dali/internal/common/message-buffer.h
new file mode 100644 (file)
index 0000000..d731b9d
--- /dev/null
@@ -0,0 +1,156 @@
+#ifndef __DALI_INTERNAL_MESSAGE_BUFFER_H__
+#define __DALI_INTERNAL_MESSAGE_BUFFER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/mutex.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Utility class to reserve a buffer for storing messages.
+ */
+class MessageBuffer
+{
+public:
+  typedef std::ptrdiff_t WordType;
+
+  /**
+   * Create a new MessageBuffer
+   * @param[in] The smallest capacity which the buffer will allocate, with respect to the size of type "char".
+   * @note The buffer will not allocate memory until the first call to ReserveMessageSlot().
+   */
+  MessageBuffer( std::size_t initialCapacity );
+
+  /**
+   * Non-virtual destructor; not suitable as a base class
+   */
+  ~MessageBuffer();
+
+  /**
+   * Reserve space for another message in the buffer.
+   * @pre size is greater than zero.
+   * @param[in] size The message size with respect to the size of type "char".
+   * @return A pointer to the address allocated for the message, aligned to a word boundary
+   */
+  unsigned int* ReserveMessageSlot( std::size_t size );
+
+  /**
+   * Query the capacity of the message buffer.
+   * @return The capacity with respect to the size of type "char".
+   */
+  std::size_t GetCapacity() const;
+
+  /**
+   * Used to iterate though the messages in the buffer.
+   */
+  class Iterator
+  {
+  public:
+
+    // Constructor
+    Iterator(WordType* current);
+
+    // Inlined for performance
+    bool IsValid()
+    {
+      // Valid until end marker has been found
+      return 0 != mMessageSize;
+    }
+
+    // Inlined for performance
+    WordType* Get()
+    {
+      return ( 0 != mMessageSize ) ? mCurrent : NULL;
+    }
+
+    // Inlined for performance
+    void Next()
+    {
+      // Jump to next object and read size
+      mCurrent += mMessageSize;
+      mMessageSize = *mCurrent++;
+    }
+
+    // Copy constructor
+    Iterator(const Iterator& copy);
+
+  private:
+
+    // Undefined
+    Iterator& operator=(const Iterator& rhs);
+
+  private:
+
+    WordType* mCurrent;
+    std::size_t mMessageSize;
+  };
+
+  /**
+   * Returns an iterator to the first message in the buffer.
+   * There is no past-the-end iterator; use Iterator::IsValid() to determine when the has been reached.
+   * @note Adding more messages with ReserveMessageSlot() may corrupt this iterator.
+   * @return The iterator.
+   */
+  Iterator Begin() const;
+
+  /**
+   * Sets the size of the buffer to zero (does not deallocate memory)
+   */
+  void Reset();
+
+private:
+
+  // Undefined
+  MessageBuffer(const MessageBuffer&);
+
+  // Undefined
+  MessageBuffer& operator=(const MessageBuffer& rhs);
+
+  /**
+   * Helper to increase the capacity of the buffer.
+   * @pre The newCapacity is greater than mCapacity.
+   * @param[in] The newCapacity
+   */
+  void IncreaseCapacity( std::size_t newCapacity );
+
+private:
+
+  std::size_t mInitialCapacity; ///< The capacity to allocate during first call to ReserveMessageSlot
+
+  WordType* mData;     ///< The data allocated for the message buffer
+  WordType* mNextSlot; ///< The next free location in the buffer
+
+  std::size_t mCapacity; ///< The memory allocated with respect to sizeof(WordType)
+  std::size_t mSize;     ///< The memory reserved for messages with respect to sizeof(WordType)
+  Dali::Mutex mMutex;    ///< Mutex to ensure correct access locking
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_MESSAGE_BUFFER_H__
diff --git a/dali/internal/common/message.h b/dali/internal/common/message.h
new file mode 100644 (file)
index 0000000..201186c
--- /dev/null
@@ -0,0 +1,872 @@
+#ifndef __DALI_INTERNAL_MESSAGE_H__
+#define __DALI_INTERNAL_MESSAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/type-abstraction.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * An abstract base class for messages queued across threads.
+ * Messages are only allowed to contain value objects, either copies of the parameters or pointers
+ * If message parameter type is & or const& the message will try to take a copy of the actual type
+ */
+class MessageBase
+{
+public:
+
+  /**
+   * Construct the message base.
+   */
+  MessageBase( )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageBase()
+  {
+  }
+
+  /**
+   * Called to process the message.
+   * @param [in] bufferIndex The current update/render buffer index (depending on which thread processes the message).
+   */
+  virtual void Process( BufferIndex bufferIndex ) = 0;
+
+private:
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This allows nodes etc. to be modified in a thread-safe manner, when the update occurs in a separate thread.
+ * The object lifetime must controlled i.e. not destroyed before the message is processed.
+ */
+template< typename T >
+class Message : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)();
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object to be updated in a separate thread.
+   * @param[in] member The member function of the object.
+   */
+  Message( const T* obj, MemberFunction member )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Message()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)();
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes one value-type parameter.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P >
+class MessageValue1 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)( typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first value-type parameter to pass to the member function.
+   */
+  MessageValue1( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P >::PassingType p1 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue1()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)( ParameterType< P >::PassObject( param1 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P >::HolderType param1;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes two value-type parameters.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+
+template< typename T, typename P1, typename P2 >
+class MessageValue2 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      typename ParameterType< P1 >::PassingType,
+      typename ParameterType< P2 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first parameter to pass to the member function.
+   * @param[in] p2 The second parameter to pass to the member function.
+   */
+  MessageValue2( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P1 >::PassingType p1,
+                 typename ParameterType< P2 >::PassingType p2 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 ),
+    param2( p2 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue2()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        ParameterType< P1 >::PassObject( param1 ),
+        ParameterType< P2 >::PassObject( param2 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P1 >::HolderType param1;
+  typename ParameterType< P2 >::HolderType param2;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes three value-type parameters.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P1, typename P2, typename P3 >
+class MessageValue3 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      typename ParameterType< P1 >::PassingType,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first parameter to pass to the member function.
+   * @param[in] p2 The second parameter to pass to the member function.
+   * @param[in] p3 The third parameter to pass to the member function.
+   */
+  MessageValue3( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P1 >::PassingType p1,
+                 typename ParameterType< P2 >::PassingType p2,
+                 typename ParameterType< P3 >::PassingType p3 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 ),
+    param2( p2 ),
+    param3( p3 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue3()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        ParameterType< P1 >::PassObject( param1 ),
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P1 >::HolderType param1;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes four value-type parameters.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P1, typename P2, typename P3, typename P4 >
+class MessageValue4 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      typename ParameterType< P1 >::PassingType,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType,
+      typename ParameterType< P4 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first parameter to pass to the member function.
+   * @param[in] p2 The second parameter to pass to the member function.
+   * @param[in] p3 The third parameter to pass to the member function.
+   * @param[in] p4 The fourth parameter to pass to the member function.
+   */
+  MessageValue4( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P1 >::PassingType p1,
+                 typename ParameterType< P2 >::PassingType p2,
+                 typename ParameterType< P3 >::PassingType p3,
+                 typename ParameterType< P4 >::PassingType p4 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 ),
+    param2( p2 ),
+    param3( p3 ),
+    param4( p4 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue4()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        ParameterType< P1 >::PassObject( param1 ),
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ),
+        ParameterType< P4 >::PassObject( param4 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P1 >::HolderType param1;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+  typename ParameterType< P4 >::HolderType param4;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes five value-type parameters.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5 >
+class MessageValue5 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      typename ParameterType< P1 >::PassingType,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType,
+      typename ParameterType< P4 >::PassingType,
+      typename ParameterType< P5 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first parameter to pass to the member function.
+   * @param[in] p2 The second parameter to pass to the member function.
+   * @param[in] p3 The third parameter to pass to the member function.
+   * @param[in] p4 The fourth parameter to pass to the member function.
+   * @param[in] p5 The fifth parameter to pass to the member function.
+   */
+  MessageValue5( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P1 >::PassingType p1,
+                 typename ParameterType< P2 >::PassingType p2,
+                 typename ParameterType< P3 >::PassingType p3,
+                 typename ParameterType< P4 >::PassingType p4,
+                 typename ParameterType< P5 >::PassingType p5 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 ),
+    param2( p2 ),
+    param3( p3 ),
+    param4( p4 ),
+    param5( p5 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue5()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        ParameterType< P1 >::PassObject( param1 ),
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ),
+        ParameterType< P4 >::PassObject( param4 ),
+        ParameterType< P5 >::PassObject( param5 ) );
+
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P1 >::HolderType param1;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+  typename ParameterType< P4 >::HolderType param4;
+  typename ParameterType< P5 >::HolderType param5;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes six value-type parameters.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6 >
+class MessageValue6 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      typename ParameterType< P1 >::PassingType,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType,
+      typename ParameterType< P4 >::PassingType,
+      typename ParameterType< P5 >::PassingType,
+      typename ParameterType< P6 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p1 The first parameter to pass to the member function.
+   * @param[in] p2 The second parameter to pass to the member function.
+   * @param[in] p3 The third parameter to pass to the member function.
+   * @param[in] p4 The fourth parameter to pass to the member function.
+   * @param[in] p5 The fifth parameter to pass to the member function.
+   * @param[in] p6 The sixth parameter to pass to the member function.
+   */
+  MessageValue6( const T* obj,
+                 MemberFunction member,
+                 typename ParameterType< P1 >::PassingType p1,
+                 typename ParameterType< P2 >::PassingType p2,
+                 typename ParameterType< P3 >::PassingType p3,
+                 typename ParameterType< P4 >::PassingType p4,
+                 typename ParameterType< P5 >::PassingType p5,
+                 typename ParameterType< P6 >::PassingType p6 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param1( p1 ),
+    param2( p2 ),
+    param3( p3 ),
+    param4( p4 ),
+    param5( p5 ),
+    param6( p6 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageValue6()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex /*bufferIndex*/ )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        ParameterType< P1 >::PassObject( param1 ),
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ),
+        ParameterType< P4 >::PassObject( param4 ),
+        ParameterType< P5 >::PassObject( param5 ),
+        ParameterType< P6 >::PassObject( param6 ) );
+
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P1 >::HolderType param1;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+  typename ParameterType< P4 >::HolderType param4;
+  typename ParameterType< P5 >::HolderType param5;
+  typename ParameterType< P6 >::HolderType param6;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes just the buffer index to the method, no parameters.
+ */
+template< typename T >
+class MessageDoubleBuffered0 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)( BufferIndex );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   */
+  MessageDoubleBuffered0( const T* obj, MemberFunction member )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageDoubleBuffered0()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex bufferIndex )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)( bufferIndex );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+
+};
+
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes a value-type to set a double-buffered property.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P >
+class MessageDoubleBuffered1 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      BufferIndex,
+      typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p The second parameter to pass.
+   */
+  MessageDoubleBuffered1( const T* obj,
+                          MemberFunction member,
+                          typename ParameterType< P >::PassingType p )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param( p )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageDoubleBuffered1()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex bufferIndex )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        bufferIndex,
+        ParameterType< P >::PassObject( param ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P >::HolderType param;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes two value-types to set double-buffered properties.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P2, typename P3 >
+class MessageDoubleBuffered2 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      BufferIndex,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p2 The second parameter to pass to the function.
+   * @param[in] p3 The third parameter to pass to the function.
+   */
+  MessageDoubleBuffered2( const T* obj,
+                          MemberFunction member,
+                          typename ParameterType< P2 >::PassingType p2,
+                          typename ParameterType< P3 >::PassingType p3 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param2( p2 ),
+    param3( p3 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageDoubleBuffered2()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex bufferIndex )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        bufferIndex,
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+
+};
+
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes three value-types to set double-buffered properties.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P2, typename P3, typename P4 >
+class MessageDoubleBuffered3 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      BufferIndex,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType,
+      typename ParameterType< P4 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p2 The second parameter to pass.
+   * @param[in] p3 The third parameter to pass.
+   * @param[in] p4 The forth parameter to pass.
+   */
+  MessageDoubleBuffered3( const T* obj,
+                          MemberFunction member,
+                          typename ParameterType< P2 >::PassingType p2,
+                          typename ParameterType< P3 >::PassingType p3,
+                          typename ParameterType< P4 >::PassingType p4 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param2( p2 ),
+    param3( p3 ),
+    param4( p4 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageDoubleBuffered3()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex bufferIndex )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        bufferIndex,
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ),
+        ParameterType< P4 >::PassObject( param4 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+  typename ParameterType< P4 >::HolderType param4;
+
+};
+
+/**
+ * Templated message which calls a member function of an object.
+ * This overload passes four value-types to set double-buffered properties.
+ * Template parameters need to match the MemberFunction!
+ * The message will contain copy of the value (in case of & or const&)
+ */
+template< typename T, typename P2, typename P3, typename P4, typename P5 >
+class MessageDoubleBuffered4 : public MessageBase
+{
+public:
+
+  typedef void(T::*MemberFunction)(
+      BufferIndex,
+      typename ParameterType< P2 >::PassingType,
+      typename ParameterType< P3 >::PassingType,
+      typename ParameterType< P4 >::PassingType,
+      typename ParameterType< P5 >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] obj The object.
+   * @param[in] member The member function of the object.
+   * @param[in] p2 The second parameter to pass.
+   * @param[in] p3 The third parameter to pass.
+   * @param[in] p4 The forth parameter to pass.
+   * @param[in] p5 The fifth parameter to pass.
+   */
+  MessageDoubleBuffered4( const T* obj,
+                          MemberFunction member,
+                          typename ParameterType< P2 >::PassingType p2,
+                          typename ParameterType< P3 >::PassingType p3,
+                          typename ParameterType< P4 >::PassingType p4,
+                          typename ParameterType< P5 >::PassingType p5 )
+  : MessageBase(),
+    object( const_cast< T* >( obj ) ),
+    memberFunction( member ),
+    param2( p2 ),
+    param3( p3 ),
+    param4( p4 ),
+    param5( p5 )
+  {
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MessageDoubleBuffered4()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex bufferIndex )
+  {
+    DALI_ASSERT_DEBUG( object && "Message does not have an object" );
+    (object->*memberFunction)(
+        bufferIndex,
+        ParameterType< P2 >::PassObject( param2 ),
+        ParameterType< P3 >::PassObject( param3 ),
+        ParameterType< P4 >::PassObject( param4 ),
+        ParameterType< P5 >::PassObject( param5 ) );
+  }
+
+private:
+
+  T* object;
+  MemberFunction memberFunction;
+  typename ParameterType< P2 >::HolderType param2;
+  typename ParameterType< P3 >::HolderType param3;
+  typename ParameterType< P4 >::HolderType param4;
+  typename ParameterType< P5 >::HolderType param5;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_MESSAGE_H__
diff --git a/dali/internal/common/owner-container.h b/dali/internal/common/owner-container.h
new file mode 100644 (file)
index 0000000..9131616
--- /dev/null
@@ -0,0 +1,178 @@
+#ifndef __DALI_INTERNAL_OWNER_CONTAINER_H__
+#define __DALI_INTERNAL_OWNER_CONTAINER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * OwnerContainer is a vector which own heap-allocated objects.
+ * Unlike vector this will call delete on the stored pointers during destruction.
+ * For example, you can define a vector of heap-allocated Node objects:
+ * @code
+ *   typedef OwnerContainer< Node* > NodeContainer;
+ *
+ *   NodeContainer container;
+ *   container.PushBack( new Node() );
+ *   // container is now responsible for calling delete on Node
+ *
+ * @endcode
+ */
+template< class T >
+class OwnerContainer : public Dali::Vector< T >
+{
+public:
+
+  typedef typename Dali::Vector< T >::SizeType SizeType;
+  typedef typename Vector< T >::Iterator Iterator;
+  typedef typename Vector< T >::ConstIterator ConstIterator;
+
+  /**
+   * Create a pointer-container.
+   */
+  OwnerContainer()
+  { }
+
+  /**
+   * Non-virtual destructor; OwnerContainer<T> is not suitable as base class.
+   */
+  ~OwnerContainer()
+  {
+    Clear();
+    VectorBase::Release();
+  }
+
+  /**
+   * Test whether the container is empty.
+   * @return True if the container is empty
+   */
+  bool IsEmpty() const
+  {
+    return VectorBase::Count() == 0u;
+  }
+
+  /**
+   * Erase an object from the container (delete from heap).
+   * @param[in] position A dereferencable iterator to an element in mContainer.
+   * @return iterator pointing to next element
+   */
+  Iterator Erase( Iterator position )
+  {
+    delete (*position);
+    return Vector< T >::Erase( position );
+  }
+
+  /**
+   * Release the ownership of an object, without deleting it.
+   * @param[in] position A dereferencable iterator to an element in mContainer.
+   * @post iterators are invalidated by this method.
+   * @return pointer to the released item
+   */
+  T Release( Iterator position )
+  {
+    T pointer = *position;
+    Vector< T >::Erase( position );
+    return pointer;
+  }
+
+  /**
+   * Destroy all of the elements in the container.
+   */
+  void Clear()
+  {
+    ConstIterator end = Vector< T >::End();
+    for( Iterator iter = Vector< T >::Begin(); iter != end; ++iter )
+    {
+      delete (*iter);
+    }
+    Vector< T >::Clear();
+  }
+
+  /**
+   * Resizes the container to hold specific amount of elements
+   * @param size to resize to
+   */
+  void Resize( SizeType size )
+  {
+    if( size < VectorBase::Count() )
+    {
+      // OwnerContainer owns these heap-allocated objects
+      ConstIterator end = Vector< T >::End();
+      for( Iterator iter = Vector< T >::Begin() + size; iter != end; ++iter )
+      {
+        delete (*iter);
+      }
+    }
+    Vector< T >::Resize( size );
+  }
+
+  /**
+   * Move the ownership of objects from another OwnerContainer to this one
+   * without deleting them. It will keep the original items here as well.
+   * @param[in] source where to move elements from to this OwnerContainer
+   */
+  void MoveFrom( OwnerContainer& source )
+  {
+    typename Vector< T >::SizeType sourceCount = source.Count();
+    // if source is empty, nothing to move
+    if( sourceCount > 0u )
+    {
+      // Optimisation for the case that this is empty
+      if( IsEmpty() )
+      {
+        VectorBase::Swap( source );
+      }
+      else
+      {
+        // make space for new items
+        Vector< T >::Reserve( VectorBase::Count() + sourceCount );
+        Iterator iter = source.Begin();
+        ConstIterator end = source.End();
+        for( ; iter != end; ++iter )
+        {
+          T pointer = *iter;
+          Vector< T >::PushBack( pointer );
+        }
+        // cannot call Clear on OwnerContainer as that deletes the elements
+        source.Vector< T >::Clear();
+      }
+    }
+  }
+
+private:
+
+  // Undefined copy constructor.
+  OwnerContainer( const OwnerContainer& );
+  // Undefined assignment operator.
+  OwnerContainer& operator=( const OwnerContainer& );
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_OWNER_CONTAINER_H__
diff --git a/dali/internal/common/owner-pointer.h b/dali/internal/common/owner-pointer.h
new file mode 100644 (file)
index 0000000..7b92978
--- /dev/null
@@ -0,0 +1,230 @@
+#ifndef __DALI_INTERNAL_OWNER_POINTER_H__
+#define __DALI_INTERNAL_OWNER_POINTER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>    // NULL
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+template < typename T >
+class OwnerPointer
+{
+public:
+  /**
+   * Default constructor. Creates an OwnerPointer that does not own any object.
+   */
+  OwnerPointer()
+  {
+    mObject = NULL;
+  }
+
+  /**
+   * Constructor. Creates an OwnerPointer that owns the object.
+   * @param[in] object A pointer to a heap allocated object.
+   */
+  OwnerPointer( T* object )
+  {
+    mObject = object;
+  }
+
+  /**
+   * Copy constructor. Passes the ownership of a pointer to another.
+   * @param[in] other The pointer that gives away the ownership.
+   */
+  OwnerPointer( OwnerPointer& other )
+  {
+    Init( other );
+  }
+
+  /**
+   * Assignment operator. Passes the ownership of a pointer to another.
+   * @param[in] other The pointer that gives away the ownership.
+   */
+  OwnerPointer& operator=( OwnerPointer& other )
+  {
+    if( this != &other )    // no self-assignment
+    {
+      Reset();
+      Init( other );
+    }
+
+    // return self
+    return *this;
+  }
+
+  /**
+   * Assignment operator. Takes the ownership of the object.
+   * If it owns an object already, it will be deleted.
+   * @param[in] pointer A pointer to a heap allocated object.
+   */
+  OwnerPointer& operator=( T* pointer )
+  {
+    if( mObject != pointer )
+    {
+      Reset();
+      mObject = pointer;
+    }
+
+    return *this;
+  }
+
+  /**
+   * Destructor.
+   */
+  ~OwnerPointer()
+  {
+    Reset();
+  }
+
+  /**
+   * Indirection operator.
+   * @return a reference to the object.
+   */
+  T& operator*()
+  {
+    DALI_ASSERT_DEBUG( mObject != NULL );
+
+    return *mObject;
+  }
+
+  /**
+   * Const indirection operator.
+   * @return a reference to the object from const OwnerPointer.
+   */
+  T& operator*() const
+  {
+    DALI_ASSERT_DEBUG( mObject != NULL );
+
+    // Pointer semantics: A const pointer does not mean const data.
+    return const_cast< T& >( *mObject );
+  }
+
+  /**
+   * Pointer operator.
+   * @return a pointer to the object.
+   */
+  T* operator->()
+  {
+    return mObject;
+  }
+
+  /**
+   * Const pointer operator.
+   * @return a pointer to the object referenced by a const OwnerPointer.
+   */
+  T* operator->() const
+  {
+    // Pointer semantics: A const pointer does not mean const data.
+    return const_cast< T* >( mObject );
+  }
+
+  /**
+   * Compare with a raw pointer.
+   * @return true if the raw pointer matches the one owned by this object.
+   */
+  bool operator==( const T* pointer )
+  {
+    return ( mObject == pointer );
+  }
+
+  /**
+   * Reset the pointer, deleting any owned object.
+   */
+  void Reset()
+  {
+    if ( mObject != NULL )
+    {
+      delete mObject;
+      mObject = NULL;
+    }
+  }
+
+  /**
+   * Release the ownership, it does not delete the object.
+   * @return a pointer to the object.
+   */
+  T* Release()
+  {
+    T* tmp = mObject;
+    mObject = NULL;
+    return tmp;
+  }
+
+  /**
+   * Returns a const pointer to the object owned.
+   * @return a const pointer to the object.
+   */
+  const T* Get() const
+  {
+    return mObject;
+  }
+
+  // Handle comparisons - This is a variation of the safe bool idiom
+
+  /**
+   * Pointer-to-member type. Objects can be implicitly converted to this for validity checks.
+   */
+  typedef void (OwnerPointer::*BooleanType)() const;
+
+  /**
+   * Converts an object handle to a BooleanType.
+   * This is useful for checking whether the handle is NULL.
+   */
+  operator BooleanType() const
+  {
+    return (mObject != NULL) ? &OwnerPointer::ThisIsSaferThanReturningVoidStar : NULL;
+  }
+
+private:
+
+  /**
+   * Used by the safe bool idiom.
+   */
+  void ThisIsSaferThanReturningVoidStar() const {}
+
+private:
+
+  /**
+   * Initialise this pointer from another one.
+   * ownerPointer parameter looses ownership.
+   * @param ownerPointer owner pointer
+   */
+  void Init( OwnerPointer& ownerPointer )
+  {
+    mObject = ownerPointer.mObject;
+    ownerPointer.mObject = NULL;
+  }
+
+  // data
+  T* mObject; ///< Raw pointer to the object
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_OWNER_POINTER_H__
diff --git a/dali/internal/common/shader-data.h b/dali/internal/common/shader-data.h
new file mode 100644 (file)
index 0000000..797568d
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef __DALI_INTERNAL_SHADER_DATA_H__
+#define __DALI_INTERNAL_SHADER_DATA_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ShaderData;
+typedef IntrusivePtr<ShaderData> ShaderDataPtr;
+
+/**
+ * ShaderData class.
+ * A container for shader source code and compiled binary byte code.
+ */
+class ShaderData : public Dali::RefObject
+{
+public:
+
+  /**
+   * Constructor
+   * @param[in] vertexSource   Source code for vertex program
+   * @param[in] fragmentSource Source code for fragment program
+   */
+  ShaderData(const std::string& vertexSource, const std::string& fragmentSource)
+  : mShaderHash( -1 ),
+    mVertexShader(vertexSource),
+    mFragmentShader(fragmentSource)
+  { }
+
+protected:
+  /**
+   * Protected Destructor
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ShaderData()
+  {
+    // vector releases its data
+  }
+
+public: // API
+
+  /**
+   * Set hash value which is created with vertex and fragment shader code
+   * @param [in] shaderHash  hash key created with vertex and fragment shader code
+   */
+  void SetHashValue(size_t shaderHash)
+  {
+    DALI_ASSERT_DEBUG( shaderHash != size_t(-1) );
+    mShaderHash = shaderHash;
+  }
+
+  /**
+   * Get hash value which is created with vertex and fragment shader code
+   * @return shaderHash  hash key created with vertex and fragment shader code
+   */
+  size_t GetHashValue() const
+  {
+    DALI_ASSERT_DEBUG( mShaderHash != size_t(-1) );
+    return mShaderHash;
+  }
+
+  /**
+   * @return the vertex shader
+   */
+  const char* GetVertexShader() const
+  {
+    return mVertexShader.c_str();
+  }
+
+  /**
+   * @return the vertex shader
+   */
+  const char* GetFragmentShader() const
+  {
+    return mFragmentShader.c_str();
+  }
+
+  /**
+   * Check whether there is a compiled binary available
+   * @return true if this objects contains a compiled binary
+   */
+  bool HasBinary() const
+  {
+    return 0 != mBuffer.Size();
+  }
+
+  /**
+   * Allocate a buffer for the compiled binary bytecode
+   * @param[in] size  The size of the buffer in bytes
+   */
+  void AllocateBuffer( size_t size )
+  {
+    mBuffer.Resize( size );
+  }
+
+  /**
+   * Get the program buffer
+   * @return reference to the buffer
+   */
+  size_t GetBufferSize() const
+  {
+    return mBuffer.Size();
+  }
+
+  /**
+   * Get the data that the buffer points to
+   * @return raw pointer to the buffer data
+   */
+  unsigned char* GetBufferData()
+  {
+    DALI_ASSERT_DEBUG( mBuffer.Size() > 0 );
+    return &mBuffer[0];
+  }
+
+  /**
+   * Get the data that the buffer points to
+   * @return raw pointer to the buffer data
+   */
+  Dali::Vector<unsigned char>& GetBuffer()
+  {
+    return mBuffer;
+  }
+
+private: // Not implemented
+
+  ShaderData(const ShaderData& other);            ///< no copying of this object
+  ShaderData& operator= (const ShaderData& rhs);  ///< no copying of this object
+
+private: // Data
+
+  size_t                      mShaderHash;     ///< hash key created with vertex and fragment shader code
+  std::string                 mVertexShader;   ///< source code for vertex program
+  std::string                 mFragmentShader; ///< source code for fragment program
+  Dali::Vector<unsigned char> mBuffer;         ///< buffer containing compiled binary bytecode
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SHADER_DATA_H__
diff --git a/dali/internal/common/shader-saver.h b/dali/internal/common/shader-saver.h
new file mode 100644 (file)
index 0000000..580cab6
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef __DALI_INTERNAL_SHADER_DISPATCHER_H__
+#define __DALI_INTERNAL_SHADER_DISPATCHER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
+// EXTERNAL INCLUDES
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+class ShaderData;
+typedef IntrusivePtr<ShaderData> ShaderDataPtr;
+
+/**
+ * Abstract interface for passing a ShaderData object towards being saved.
+ */
+class ShaderSaver
+{
+public:
+
+  /**
+   * A function saving the binary from a ShaderDataPtr or passing it on to where it can be saved.
+   * @param[in] shaderData A smart pointer to a ShaderData for which the program binary should be saved.
+   */
+  virtual void SaveBinary( Internal::ShaderDataPtr shaderData ) = 0;
+
+protected:
+  /**
+   * Destructor. Protected as no derived class should ever be deleted
+   * through a reference to this pure abstract interface.
+   */
+  virtual ~ShaderSaver(){}
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SHADER_DISPATCHER_H__
diff --git a/dali/internal/common/text-vertex-2d.h b/dali/internal/common/text-vertex-2d.h
new file mode 100644 (file)
index 0000000..54d5242
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __DALI_INTERNAL_TEXT_VERTEX_2D_H__
+#define __DALI_INTERNAL_TEXT_VERTEX_2D_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A 2D vertex with position, texture coordinate
+ * and texture coordinate for distance field drop shadow adjustment
+ */
+struct TextVertex2D
+{
+  float mX;
+  float mY;
+  float mU;
+  float mV;
+  float mU1;
+  float mV1;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TEXT_VERTEX_2D_H__
+
diff --git a/dali/internal/common/type-abstraction-enums.h b/dali/internal/common/type-abstraction-enums.h
new file mode 100644 (file)
index 0000000..465220b
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__
+#define __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/blending.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/internal/common/type-abstraction.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+template <> struct ParameterType< CullFaceMode > : public BasicType< CullFaceMode > {};
+template <> struct ParameterType< BlendingMode::Type > : public BasicType< BlendingMode::Type > {};
+
+} //namespace Internal
+
+} //namespace Dali
+
+#endif // __DALI_INTERNAL_TYPE_ABSTRACTION_ENUMS_H__
diff --git a/dali/internal/common/type-abstraction.h b/dali/internal/common/type-abstraction.h
new file mode 100644 (file)
index 0000000..3338913
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef __DALI_INTERNAL_TYPE_ABSTRACTION_H__
+#define __DALI_INTERNAL_TYPE_ABSTRACTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <climits>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/common/owner-pointer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Template helpers to strip of const reference and reference to prevent anyone
+ * from passing references as message parameters
+ */
+
+// For basic types, they are always pass by copy
+template <typename Type>
+struct BasicType
+{
+  typedef Type HolderType;
+  typedef Type PassingType;
+  static PassingType PassObject( PassingType object ) { return object; }
+};
+
+// For complex types that are copied into the message,
+// they are passed as const reference when they don't need to be copied
+template <typename Type>
+struct ComplexType
+{
+  typedef Type HolderType;
+  typedef const Type& PassingType;
+  static PassingType PassObject( PassingType object ) { return object; }
+};
+
+// For complex types that are owned by the message,
+// They are passed as raw pointer and hold in an OwnerPointer
+template <typename Type>
+struct OwnedType
+{
+  typedef OwnerPointer<Type> HolderType;
+  typedef Type* PassingType;
+  static PassingType PassObject( HolderType& object ) { return object.Release(); }
+};
+
+// Default for Vector3 and other structures
+template <class T> struct ParameterType : public ComplexType< T > {};
+
+// For message owned parameters
+template <class T> struct ParameterType< OwnerPointer<T> > : public OwnedType< T > {};
+
+// Basic types types
+template <typename T> struct ParameterType< T* > : public BasicType< T* > {};
+template <typename T> struct ParameterType< const T* > : public BasicType< const T* > {};
+template <> struct ParameterType< int > : public BasicType< int > {};
+template <> struct ParameterType< unsigned int > : public BasicType< unsigned int > {};
+template <> struct ParameterType< float > : public BasicType< float > {};
+template <> struct ParameterType< bool > : public BasicType< bool > {};
+template <> struct ParameterType< short int > : public BasicType< short int > {};
+
+#if INT_MAX != LONG_MAX
+template <> struct ParameterType< long > : public BasicType< long > {};
+template <> struct ParameterType< unsigned long > : public BasicType< unsigned long > {};
+#endif
+
+//TODO: Passing intrusive pointers through messages is potentially dangerous,
+//      this should be checked
+template <typename T> struct ParameterType< IntrusivePtr<T> >
+: public BasicType< IntrusivePtr<T> > {};
+
+// poorly constructed types, types should not be defined as references
+// this will trigger a compilation error.
+template <class U> struct ParameterType< U& > {};
+template <class U> struct ParameterType< const U& > {};
+
+} //namespace Internal
+
+} //namespace Dali
+
+#endif // __DALI_INTERNAL_TYPE_ABSTRACTION_H__
diff --git a/dali/internal/event/actor-attachments/actor-attachment-declarations.h b/dali/internal/event/actor-attachments/actor-attachment-declarations.h
new file mode 100644 (file)
index 0000000..8dbd795
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__
+#define __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ActorAttachment;
+class CameraAttachment;
+class ImageAttachment;
+
+typedef IntrusivePtr<ActorAttachment>  ActorAttachmentPtr;
+typedef IntrusivePtr<CameraAttachment> CameraAttachmentPtr;
+typedef IntrusivePtr<ImageAttachment>  ImageAttachmentPtr;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_ATTACHMENT_DECLARATIONS_H__
diff --git a/dali/internal/event/actor-attachments/actor-attachment-impl.cpp b/dali/internal/event/actor-attachments/actor-attachment-impl.cpp
new file mode 100644 (file)
index 0000000..fcd6e8c
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+bool ActorAttachment::OnStage() const
+{
+  return mIsOnStage;
+}
+
+/**
+ * This method is called by the parent actor.
+ */
+void ActorAttachment::Connect()
+{
+  mIsOnStage = true;
+
+  // Notification for derived classes
+  OnStageConnection();
+}
+
+/**
+ * This method is called by the parent actor.
+ */
+void ActorAttachment::Disconnect()
+{
+  // Notification for derived classes
+  OnStageDisconnection();
+
+  mIsOnStage = false;
+}
+
+ActorAttachment::ActorAttachment( EventThreadServices& eventThreadServices )
+: mEventThreadServices( eventThreadServices ),
+  mIsOnStage( false )
+{
+}
+
+ActorAttachment::~ActorAttachment()
+{
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actor-attachments/actor-attachment-impl.h b/dali/internal/event/actor-attachments/actor-attachment-impl.h
new file mode 100644 (file)
index 0000000..7bfef97
--- /dev/null
@@ -0,0 +1,119 @@
+#ifndef __DALI_INTERNAL_ACTOR_ATTACHMENT_H__
+#define __DALI_INTERNAL_ACTOR_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class EventThreadServices;
+
+/**
+ * An abstract base class for attachments, such a renderable objects and lights.
+ * ActorAttachments must be attached to an actor, in order to be displayed.
+ */
+class ActorAttachment : public Dali::RefObject
+{
+public:
+
+  /**
+   * Query whether the attachment is connected to the stage.
+   * @return True if the attachment is connected to the stage.
+   */
+  bool OnStage() const;
+
+  /**
+   * Called by the attached actor, when connected to the Stage.
+   */
+  void Connect();
+
+  /**
+   * Called by the attached actor, when the actor is disconnected from the Stage.
+   */
+  void Disconnect();
+
+protected:
+
+  /**
+   * Construct a new attachment.
+   * @param[in] eventThreadServices Used for messaging to and reading from scene-graph.
+   */
+  ActorAttachment( EventThreadServices& eventThreadServices );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ActorAttachment();
+
+private:
+
+  // Undefined
+  ActorAttachment(const ActorAttachment&);
+
+  // Undefined
+  ActorAttachment& operator=(const ActorAttachment& rhs);
+
+  /**
+   * For use in derived classes, called after ConnectToStage()
+   */
+  virtual void OnStageConnection() = 0;
+
+  /**
+   * For use in derived classes, called after DisconnectFromStage()
+   */
+  virtual void OnStageDisconnection() = 0;
+
+protected:
+  /**
+   * For use in message sending to and property reading from the scene graph
+   * Inlined for speed
+   * @return The EventThreadServices object
+   */
+  inline EventThreadServices& GetEventThreadServices()
+  {
+    return mEventThreadServices;
+  }
+
+  /**
+   * For use in message sending to and property reading from the scene graph
+   * Inlined for speed
+   */
+  inline const EventThreadServices& GetEventThreadServices() const
+  {
+    return mEventThreadServices;
+  }
+
+private:
+  EventThreadServices& mEventThreadServices; ///< Used to send messages to scene-graph; valid until Core destruction
+
+protected:
+  bool mIsOnStage : 1; ///< Flag to identify whether the attachment is on-stage
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_ATTACHMENT_H__
diff --git a/dali/internal/event/actor-attachments/camera-attachment-impl.cpp b/dali/internal/event/actor-attachments/camera-attachment-impl.cpp
new file mode 100644 (file)
index 0000000..aa66cd7
--- /dev/null
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CameraAttachmentPtr CameraAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode )
+{
+  CameraAttachmentPtr attachment( new CameraAttachment( eventThreadServices ) );
+
+  // Transfer object ownership of scene-object to message
+  SceneGraph::CameraAttachment* sceneObject = CreateSceneObject();
+  AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject );
+
+  // Keep raw pointer for message passing
+  attachment->mSceneObject = sceneObject;
+
+  return attachment;
+}
+
+CameraAttachment::CameraAttachment( EventThreadServices& eventThreadServices )
+: ActorAttachment( eventThreadServices ),
+  mSceneObject( NULL ),
+  mType( SceneGraph::CameraAttachment::DEFAULT_TYPE ),
+  mProjectionMode( SceneGraph::CameraAttachment::DEFAULT_MODE ),
+  mInvertYAxis( SceneGraph::CameraAttachment::DEFAULT_INVERT_Y_AXIS ),
+  mFieldOfView( SceneGraph::CameraAttachment::DEFAULT_FIELD_OF_VIEW ),
+  mAspectRatio( SceneGraph::CameraAttachment::DEFAULT_ASPECT_RATIO ),
+  mLeftClippingPlane( SceneGraph::CameraAttachment::DEFAULT_LEFT_CLIPPING_PLANE ),
+  mRightClippingPlane( SceneGraph::CameraAttachment::DEFAULT_RIGHT_CLIPPING_PLANE ),
+  mTopClippingPlane( SceneGraph::CameraAttachment::DEFAULT_TOP_CLIPPING_PLANE ),
+  mBottomClippingPlane( SceneGraph::CameraAttachment::DEFAULT_BOTTOM_CLIPPING_PLANE ),
+  mNearClippingPlane( SceneGraph::CameraAttachment::DEFAULT_NEAR_CLIPPING_PLANE ),
+  mFarClippingPlane( SceneGraph::CameraAttachment::DEFAULT_FAR_CLIPPING_PLANE ),
+  mStereoBias( SceneGraph::CameraAttachment::DEFAULT_STEREO_BIAS ),
+  mTargetPosition( SceneGraph::CameraAttachment::DEFAULT_TARGET_POSITION )
+{
+}
+
+CameraAttachment::~CameraAttachment()
+{
+}
+
+SceneGraph::CameraAttachment* CameraAttachment::CreateSceneObject()
+{
+  return SceneGraph::CameraAttachment::New();
+}
+
+void CameraAttachment::SetType(Dali::Camera::Type type)
+{
+  if( type != mType )
+  {
+    mType = type;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetTypeMessage( GetEventThreadServices(), *mSceneObject, type );
+  }
+}
+
+Dali::Camera::Type CameraAttachment::GetType() const
+{
+  return mType;
+}
+
+void CameraAttachment::SetProjectionMode(Dali::Camera::ProjectionMode projectionMode)
+{
+  if( ! Equals(projectionMode, mProjectionMode) )
+  {
+    mProjectionMode = projectionMode;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetProjectionModeMessage( GetEventThreadServices(), *mSceneObject, projectionMode );
+  }
+}
+
+Dali::Camera::ProjectionMode CameraAttachment::GetProjectionMode() const
+{
+  return mProjectionMode;
+}
+
+void CameraAttachment::SetFieldOfView( float fieldOfView )
+{
+  if( ! Equals(fieldOfView, mFieldOfView) )
+  {
+    mFieldOfView = fieldOfView;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetFieldOfViewMessage( GetEventThreadServices(), *mSceneObject, fieldOfView );
+  }
+}
+
+float CameraAttachment::GetFieldOfView() const
+{
+  return mFieldOfView;
+}
+
+void CameraAttachment::SetAspectRatio( float aspectRatio )
+{
+  if( ! Equals(aspectRatio, mAspectRatio) )
+  {
+    mAspectRatio = aspectRatio;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetAspectRatioMessage( GetEventThreadServices(), *mSceneObject, aspectRatio );
+  }
+}
+
+float CameraAttachment::GetAspectRatio() const
+{
+  return mAspectRatio;
+}
+
+void CameraAttachment::SetStereoBias(const Vector2& stereoBias)
+{
+  if( ! Equals(stereoBias.x, mStereoBias.x ) || ! Equals(stereoBias.y, mStereoBias.y )  )
+  {
+    mStereoBias = stereoBias;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetStereoBiasMessage( GetEventThreadServices(), *mSceneObject, stereoBias );
+  }
+}
+
+Vector2 CameraAttachment::GetStereoBias() const
+{
+  return mStereoBias;
+}
+
+void CameraAttachment::SetLeftClippingPlane( float leftClippingPlane )
+{
+  if( ! Equals(leftClippingPlane, mLeftClippingPlane ) )
+  {
+    mLeftClippingPlane = leftClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetLeftClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, leftClippingPlane );
+  }
+}
+
+float CameraAttachment::GetLeftClippingPlane() const
+{
+  return mLeftClippingPlane;
+}
+
+void CameraAttachment::SetRightClippingPlane( float rightClippingPlane )
+{
+  if( ! Equals(rightClippingPlane, mRightClippingPlane ) )
+  {
+    mRightClippingPlane = rightClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetRightClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, rightClippingPlane );
+  }
+}
+
+float CameraAttachment::GetRightClippingPlane() const
+{
+  return mRightClippingPlane;
+}
+
+void CameraAttachment::SetTopClippingPlane( float topClippingPlane )
+{
+  if( ! Equals(topClippingPlane, mTopClippingPlane ) )
+  {
+    mTopClippingPlane = topClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetTopClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, topClippingPlane );
+  }
+}
+
+float CameraAttachment::GetTopClippingPlane() const
+{
+  return mTopClippingPlane;
+}
+
+void CameraAttachment::SetBottomClippingPlane( float bottomClippingPlane )
+{
+  if( ! Equals(bottomClippingPlane, mBottomClippingPlane ) )
+  {
+    mBottomClippingPlane = bottomClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetBottomClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, bottomClippingPlane );
+  }
+}
+
+float CameraAttachment::GetBottomClippingPlane() const
+{
+  return mBottomClippingPlane;
+}
+
+void CameraAttachment::SetNearClippingPlane( float nearClippingPlane )
+{
+  if( ! Equals(nearClippingPlane, mNearClippingPlane ) )
+  {
+    mNearClippingPlane = nearClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetNearClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, nearClippingPlane );
+  }
+}
+
+float CameraAttachment::GetNearClippingPlane() const
+{
+  return mNearClippingPlane;
+}
+
+void CameraAttachment::SetFarClippingPlane( float farClippingPlane )
+{
+  if( ! Equals( farClippingPlane, mFarClippingPlane ) )
+  {
+    mFarClippingPlane = farClippingPlane;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetFarClippingPlaneMessage( GetEventThreadServices(), *mSceneObject, farClippingPlane );
+  }
+}
+
+float CameraAttachment::GetFarClippingPlane() const
+{
+  return mFarClippingPlane;
+}
+
+void CameraAttachment::SetTargetPosition( Vector3 targetPosition )
+{
+  if( targetPosition != mTargetPosition )
+  {
+    mTargetPosition = targetPosition;
+
+    SetTargetPositionMessage( GetEventThreadServices(),  *mSceneObject, targetPosition );
+  }
+}
+
+Vector3 CameraAttachment::GetTargetPosition()
+{
+  return mTargetPosition;
+}
+
+void CameraAttachment::SetInvertYAxis( bool invertYAxis )
+{
+  if( invertYAxis != mInvertYAxis )
+  {
+    mInvertYAxis = invertYAxis;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetInvertYAxisMessage( GetEventThreadServices(), *mSceneObject, invertYAxis );
+  }
+}
+
+bool CameraAttachment::GetInvertYAxis() const
+{
+  return mInvertYAxis;
+}
+
+const Matrix& CameraAttachment::GetViewMatrix() const
+{
+  const SceneGraph::CameraAttachment& sceneObject = *mSceneObject;
+
+  return sceneObject.GetViewMatrix( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+const Matrix& CameraAttachment::GetProjectionMatrix() const
+{
+  const SceneGraph::CameraAttachment& sceneObject = *mSceneObject;
+
+  return sceneObject.GetProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+const Matrix& CameraAttachment::GetInverseViewProjectionMatrix() const
+{
+  const SceneGraph::CameraAttachment& sceneObject = *mSceneObject;
+
+  return sceneObject.GetInverseViewProjectionMatrix( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+const PropertyInputImpl* CameraAttachment::GetViewMatrixProperty() const
+{
+  DALI_ASSERT_DEBUG( OnStage() );
+
+  const SceneGraph::CameraAttachment& sceneObject = *mSceneObject;
+
+  return sceneObject.GetViewMatrix();
+}
+
+const PropertyInputImpl* CameraAttachment::GetProjectionMatrixProperty() const
+{
+  DALI_ASSERT_DEBUG( OnStage() );
+
+  const SceneGraph::CameraAttachment& sceneObject = *mSceneObject;
+
+  return sceneObject.GetProjectionMatrix();
+}
+
+void CameraAttachment::OnStageConnection()
+{
+  // do nothing
+}
+
+void CameraAttachment::OnStageDisconnection()
+{
+  // do nothing
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actor-attachments/camera-attachment-impl.h b/dali/internal/event/actor-attachments/camera-attachment-impl.h
new file mode 100644 (file)
index 0000000..4e3eedc
--- /dev/null
@@ -0,0 +1,299 @@
+#ifndef __DALI_INTERNAL_CAMERA_ATTACHMENT_H__
+#define __DALI_INTERNAL_CAMERA_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-declarations.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/inherited-property.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+
+class Matrix;
+struct Vector3;
+
+namespace Internal
+{
+
+class Camera;
+
+namespace SceneGraph
+{
+class CameraAttachment;
+class Node;
+}
+
+/**
+ * An attachment for managing the properties of a camera in the scene
+ */
+class CameraAttachment : public ActorAttachment
+{
+public:
+  /**
+   * Create an initialised CameraAttachment.
+   * @param[in] eventThreadServices to use
+   * @param[in] parentNode The node to attach a scene-object to.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static CameraAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode );
+
+  /**
+   * @copydoc Dali::Camera::SetType
+   */
+  void SetType(Dali::Camera::Type type);
+
+  /**
+   * @copydoc Dali::Camera::GetType
+   */
+  Dali::Camera::Type GetType() const;
+
+  /**
+   * Set whether the Y Axis is inverted or not.
+   * Default camera inverts the Y axis to provide a +ve Y down LHS coordinate system
+   * Some cameras may require no inversion.
+   * @param[in] invertYAxis True if inverted, false otherwise
+   */
+  void SetInvertYAxis( bool invertYAxis );
+
+  /**
+   * Get the setting of InvertYAxis
+   * @return True if the Y Axis is inverted.
+   */
+  bool GetInvertYAxis() const;
+
+  /**
+   * @copydoc Dali::Camera::SetProjectionMode
+   */
+  void SetProjectionMode(Dali::Camera::ProjectionMode projectionMode);
+
+  /**
+   * @copydoc Dali::Camera::GetProjectionMode
+   */
+  Dali::Camera::ProjectionMode GetProjectionMode() const;
+
+  /**
+   * @copydoc Dali::Camera::SetFieldOfView
+   */
+  void SetFieldOfView(float fieldOfView);
+
+  /**
+   * @copydoc Dali::Camera::GetFieldOfView
+   */
+  float GetFieldOfView() const;
+
+  /**
+   * @copydoc Dali::Camera::SetAspectRatio
+   */
+  void SetAspectRatio(float aspectRatio);
+
+  /**
+   * @copydoc Dali::Camera::GetAspectRatio
+   */
+  float GetAspectRatio() const;
+
+  /**
+   * @copydoc Dali::Camera::SetLeftClippingPlane * Set stereo bias. The frustum offset for a 3D camera
+   * @param[in] stereoBias The frustum offset for the 3D camera
+   */
+  void SetStereoBias(const Vector2& stereoBias);
+
+  /**
+   * Get stereo bias. The frustum offset for a 3D camera
+   * @return The frustum offset for the 3D camera
+   */
+  Vector2 GetStereoBias() const;
+
+  /**
+   * @copydoc Dali::Camera::SetLeftClippingPlane
+   */
+  void SetLeftClippingPlane(float leftClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetLeftClippingPlane
+   */
+  float GetLeftClippingPlane() const;
+
+  /**
+   * @copydoc Dali::Camera::SetRightClippingPlane
+   */
+  void SetRightClippingPlane(float rightClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetRightClippingPlane
+   */
+  float GetRightClippingPlane() const;
+
+  /**
+   * @copydoc Dali::Camera::SetTopClippingPlane
+   */
+  void SetTopClippingPlane(float topClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetTopClippingPlane
+   */
+  float GetTopClippingPlane() const;
+
+  /**
+   * @copydoc Dali::Camera::SetBottomClippingPlane
+   */
+  void SetBottomClippingPlane(float bottomClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetBottomClippingPlane
+   */
+  float GetBottomClippingPlane() const;
+
+  /**
+   * @copydoc Dali::Camera::SetNearClippingPlane
+   */
+  void SetNearClippingPlane(float nearClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetNearClippingPlane
+   */
+  float GetNearClippingPlane() const;
+
+  /**
+   * @copydoc Dali::Camera::SetFarClippingPlane
+   */
+  void SetFarClippingPlane(float farClippingPlane);
+
+  /**
+   * @copydoc Dali::Camera::GetFarClippingPlane
+   */
+  float GetFarClippingPlane() const;
+
+  /**
+   * Set the (lookAt) target for the camera
+   * @pre The Camera owned by this object must be of the type Camera::LookAtTarget
+   * @param target Position of object we want to look at
+   */
+  void SetTargetPosition(Vector3 target);
+
+  /**
+   * Get the (lookAt) target for the camera
+   * @return the last set target
+   */
+  Vector3 GetTargetPosition();
+
+  /**
+   * Retrieve the view-matrix.
+   * @pre The attachment is on-stage.
+   * @return The view-matrix.
+   */
+  const Matrix& GetViewMatrix() const;
+
+  /**
+   * Retrieve the projection-matrix.
+   * @pre The attachment is on-stage.
+   * @return The projection-matrix.
+   */
+  const Matrix& GetProjectionMatrix() const;
+
+  /**
+   * Returns the inverse view-projection matrix
+   * @pre The attachment is on-stage.
+   * @return The inverse view-projection-matrix.
+   */
+  const Matrix& GetInverseViewProjectionMatrix() const;
+
+  /**
+   * Retrieve the view-matrix property querying interface.
+   * @pre The attachment is on-stage.
+   * @return The view-matrix property querying interface.
+   */
+  const PropertyInputImpl* GetViewMatrixProperty() const;
+
+  /**
+   * Retrieve the projection-matrix property querying interface.
+   * @pre The attachment is on-stage.
+   * @return The projection-matrix property querying interface.
+   */
+  const PropertyInputImpl* GetProjectionMatrixProperty() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+
+private:
+
+  /**
+   * First stage construction of a CameraAttachment.
+   * @param[in] eventThreadServices Used for messaging to and reading from scene-graph.
+   */
+  CameraAttachment( EventThreadServices& eventThreadServices );
+
+  /**
+   * Creates the corresponding scene-graph CameraAttachment.
+   * @return A newly allocated scene object.
+   */
+  static SceneGraph::CameraAttachment* CreateSceneObject();
+
+  /**
+   * @copydoc Dali::Internal::ActorAttachment::OnStageConnection()
+   */
+  virtual void OnStageConnection();
+
+  /**
+   * @copydoc Dali::Internal::ActorAttachment::OnStageDisconnection()
+   */
+  virtual void OnStageDisconnection();
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~CameraAttachment();
+
+private:
+
+  const SceneGraph::CameraAttachment* mSceneObject; ///< Not owned
+
+  Dali::Camera::Type mType;
+  Dali::Camera::ProjectionMode mProjectionMode;
+  bool               mInvertYAxis;
+  float              mFieldOfView;
+  float              mAspectRatio;
+  float              mLeftClippingPlane;
+  float              mRightClippingPlane;
+  float              mTopClippingPlane;
+  float              mBottomClippingPlane;
+  float              mNearClippingPlane;
+  float              mFarClippingPlane;
+  Vector2            mStereoBias;
+  Vector3            mTargetPosition;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CAMERA_ATTACHMENT_H__
diff --git a/dali/internal/event/actor-attachments/image-attachment-impl.cpp b/dali/internal/event/actor-attachments/image-attachment-impl.cpp
new file mode 100644 (file)
index 0000000..4ebe539
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actor-attachments/image-attachment-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ImageAttachmentPtr ImageAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode )
+{
+  ImageAttachmentPtr attachment( new ImageAttachment( eventThreadServices ) );
+
+  // Transfer object ownership of scene-object to message
+  SceneGraph::ImageAttachment* sceneObject = CreateSceneObject();
+  AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject );
+
+  // Keep raw pointer for message passing
+  attachment->mSceneObject = sceneObject;
+
+  return attachment;
+}
+
+ImageAttachment::ImageAttachment( EventThreadServices& eventThreadServices )
+: RenderableAttachment(eventThreadServices),
+  mSceneObject(NULL),
+  mPixelArea(0,0,0,0),
+  mStyle(Dali::ImageActor::STYLE_QUAD),
+  mBorder(0.45,0.45,0.1,0.1),
+  mIsPixelAreaSet(false),
+  mBorderInPixels(false),
+
+
+  mBlendingOptions(),
+  mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
+  mSortModifier( 0.0f ),
+  mCullFaceMode( CullNone ),
+  mBlendingMode( BlendingMode::AUTO ),
+  mShaderEffect()
+{
+  mImageConnectable.Set( NULL, false );
+}
+
+ImageAttachment::~ImageAttachment()
+{
+}
+
+void ImageAttachment::SetImage( ImagePtr& image )
+{
+  bool onStage = OnStage();
+  // keep a reference to Image object
+  mImageConnectable.Set( image, onStage );
+
+  // Wait until the scene-graph attachment is connected, before providing resource ID
+  if ( OnStage() )
+  {
+    unsigned int resourceId = (image) ? image->GetResourceId() : 0u;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+  }
+}
+
+ImagePtr ImageAttachment::GetImage()
+{
+  return mImageConnectable.Get();
+}
+
+void ImageAttachment::SetPixelArea(const PixelArea& pixelArea)
+{
+  // check to see if pixel area is actually different, using rect::operator==
+  if( pixelArea != mPixelArea )
+  {
+    // Cache for public getters
+    mPixelArea = pixelArea;
+    mIsPixelAreaSet = true;
+
+    // sceneObject is being used in a separate thread; queue a message to set
+    SetPixelAreaMessage( GetEventThreadServices(), *mSceneObject, mPixelArea );
+  }
+}
+
+void ImageAttachment::ClearPixelArea()
+{
+  // Cache for public getters
+  mIsPixelAreaSet = false;
+
+  // sceneObject is being used in a separate thread; queue a message to set
+  ClearPixelAreaMessage( GetEventThreadServices(), *mSceneObject );
+}
+
+void ImageAttachment::SetStyle(Style style)
+{
+  // Cache for public getters
+  mStyle = style;
+
+  // sceneObject is being used in a separate thread; queue a message to set
+  SetStyleMessage( GetEventThreadServices(), *mSceneObject, style );
+}
+
+void ImageAttachment::SetNinePatchBorder(const Vector4& border, bool inPixels)
+{
+  // Cache for public getters
+  mBorder = border;
+  mBorderInPixels = inPixels;
+
+  // sceneObject is being used in a separate thread; queue a message to set
+  SetNinePatchBorderMessage( GetEventThreadServices(), *mSceneObject, border, inPixels );
+}
+
+SceneGraph::ImageAttachment* ImageAttachment::CreateSceneObject()
+{
+  return SceneGraph::ImageAttachment::New( 0u );
+}
+
+const SceneGraph::ImageAttachment& ImageAttachment::GetSceneObject() const
+{
+  DALI_ASSERT_DEBUG( mSceneObject != NULL );
+  return *mSceneObject;
+}
+
+void ImageAttachment::SetSortModifier(float modifier)
+{
+  // Cache for actor-side getters
+  mSortModifier = modifier;
+
+  // attachment is being used in a separate thread; queue a message to set the value & base value
+  SetSortModifierMessage( GetEventThreadServices(), GetSceneObject(), modifier );
+}
+
+float ImageAttachment::GetSortModifier() const
+{
+  // mSortModifier is not animatable; this is the most up-to-date value.
+  return mSortModifier;
+}
+
+void ImageAttachment::SetCullFace( CullFaceMode mode )
+{
+  // Cache for actor-side getters
+  mCullFaceMode = mode;
+
+  // attachment is being used in a separate thread; queue a message to set the value
+  SetCullFaceMessage( GetEventThreadServices(), GetSceneObject(), mode );
+}
+
+CullFaceMode ImageAttachment::GetCullFace() const
+{
+  // mCullFaceMode is not animatable; this is the most up-to-date value.
+  return mCullFaceMode;
+}
+
+void ImageAttachment::SetBlendMode( BlendingMode::Type mode )
+{
+  mBlendingMode = mode;
+
+  // attachment is being used in a separate thread; queue a message to set the value
+  SetBlendingModeMessage( GetEventThreadServices(), GetSceneObject(), mode );
+}
+
+BlendingMode::Type ImageAttachment::GetBlendMode() const
+{
+  return mBlendingMode;
+}
+
+void ImageAttachment::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                                         BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
+{
+  // Cache for actor-side getters
+  mBlendingOptions.SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+
+  // attachment is being used in a separate thread; queue a message to set the value
+  SetBlendingOptionsMessage( GetEventThreadServices(), GetSceneObject(), mBlendingOptions.GetBitmask() );
+}
+
+void ImageAttachment::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                                         BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
+{
+  // These are not animatable, the cached values are up-to-date.
+  srcFactorRgb    = mBlendingOptions.GetBlendSrcFactorRgb();
+  destFactorRgb   = mBlendingOptions.GetBlendDestFactorRgb();
+  srcFactorAlpha  = mBlendingOptions.GetBlendSrcFactorAlpha();
+  destFactorAlpha = mBlendingOptions.GetBlendDestFactorAlpha();
+}
+
+void ImageAttachment::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
+{
+  mBlendingOptions.SetBlendEquation( equationRgb, equationAlpha );
+
+  // attachment is being used in a separate thread; queue a message to set the value
+  SetBlendingOptionsMessage( GetEventThreadServices(), GetSceneObject(), mBlendingOptions.GetBitmask() );
+}
+
+void ImageAttachment::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
+{
+  // These are not animatable, the cached values are up-to-date.
+  equationRgb   = mBlendingOptions.GetBlendEquationRgb();
+  equationAlpha = mBlendingOptions.GetBlendEquationAlpha();
+}
+
+void ImageAttachment::SetBlendColor( const Vector4& color )
+{
+  if( mBlendingOptions.SetBlendColor( color ) )
+  {
+    // attachment is being used in a separate thread; queue a message to set the value
+    SetBlendColorMessage( GetEventThreadServices(), GetSceneObject(), color );
+  }
+}
+
+const Vector4& ImageAttachment::GetBlendColor() const
+{
+  const Vector4* optionalColor = mBlendingOptions.GetBlendColor();
+  if( optionalColor )
+  {
+    return *optionalColor;
+  }
+
+  return Vector4::ZERO;
+}
+
+void ImageAttachment::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
+{
+  mSamplerBitfield = ImageSampler::PackBitfield( minFilter, magFilter );
+
+  SetSamplerMessage( GetEventThreadServices(), GetSceneObject(), mSamplerBitfield );
+}
+
+void ImageAttachment::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
+{
+  minFilter = ImageSampler::GetMinifyFilterMode( mSamplerBitfield );
+  magFilter = ImageSampler::GetMagnifyFilterMode( mSamplerBitfield );
+}
+
+
+void ImageAttachment::SetShaderEffect(ShaderEffect& effect)
+{
+  if ( OnStage() )
+  {
+    if ( mShaderEffect )
+    {
+      mShaderEffect->Disconnect();
+    }
+
+    mShaderEffect.Reset( &effect );
+
+    const SceneGraph::Shader& shader = dynamic_cast<const SceneGraph::Shader&>( *mShaderEffect->GetSceneObject() );
+
+    ApplyShaderMessage( GetEventThreadServices(), GetSceneObject(), shader );
+
+    mShaderEffect->Connect();
+  }
+  else
+  {
+    mShaderEffect = ShaderEffectPtr(&effect);
+  }
+  // Effects can only be applied when the Node is connected to scene-graph
+}
+
+ShaderEffectPtr ImageAttachment::GetShaderEffect() const
+{
+  return mShaderEffect;
+}
+
+void ImageAttachment::RemoveShaderEffect()
+{
+  if ( OnStage() )
+  {
+    RemoveShaderMessage( GetEventThreadServices(), GetSceneObject() );
+
+    // Notify shader effect
+    if (mShaderEffect)
+    {
+      mShaderEffect->Disconnect();
+    }
+  }
+
+  mShaderEffect.Reset();
+}
+
+
+void ImageAttachment::OnStageConnection2()
+{
+  if ( mShaderEffect )
+  {
+    const SceneGraph::Shader& shader = dynamic_cast<const SceneGraph::Shader&>( *mShaderEffect->GetSceneObject() );
+
+    ApplyShaderMessage( GetEventThreadServices(), GetSceneObject(), shader );
+
+    // Notify shader effect
+    mShaderEffect->Connect();
+  }
+
+  mImageConnectable.OnStageConnect();
+
+  // Provide resource ID when scene-graph attachment is connected
+  ImagePtr image = mImageConnectable.Get();
+  unsigned int resourceId = (image) ? image->GetResourceId() : 0u;
+  if ( 0u != resourceId )
+  {
+    SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+  }
+}
+
+void ImageAttachment::OnStageDisconnection2()
+{
+  // Notify shader effect
+  if ( mShaderEffect )
+  {
+    mShaderEffect->Disconnect();
+  }
+
+  // Remove resource ID when scene-graph attachment is disconnected
+  SetTextureIdMessage( GetEventThreadServices(), *mSceneObject, 0u );
+
+  mImageConnectable.OnStageDisconnect();
+}
+
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actor-attachments/image-attachment-impl.h b/dali/internal/event/actor-attachments/image-attachment-impl.h
new file mode 100644 (file)
index 0000000..0d7a7a0
--- /dev/null
@@ -0,0 +1,297 @@
+#ifndef __DALI_INTERNAL_IMAGE_ATTACHMENT_H__
+#define __DALI_INTERNAL_IMAGE_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/public-api/actors/blending.h>
+#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/internal/common/blending-options.h>
+#include <dali/internal/common/image-sampler.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-declarations.h>
+#include <dali/internal/event/actor-attachments/renderable-attachment-impl.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/image-connector.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class ImageAttachment;
+class Node;
+}
+
+/**
+ * An attachment for rendering images in various ways.
+ */
+class ImageAttachment : public RenderableAttachment
+{
+public:
+
+  typedef Dali::ImageActor::Style Style;
+  typedef Dali::ImageActor::PixelArea PixelArea;
+
+  /**
+   * Create a new ImageAttachment.
+   * @param[in] eventThreadServices to use
+   * @param[in] parentNode The node to attach a scene-object to.
+   * @return A smart-pointer to the newly allocated ImageAttachment.
+   */
+  static ImageAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode );
+
+  /**
+   * Sets image rendered by the attachment.
+   * @param [in] image A pointer to the image to display or NULL to clear. Reference to avoid unnecessary increment/decrement reference count.
+   */
+  void SetImage( ImagePtr& image );
+
+  /**
+   * Retrieve the image rendered by the attachment.
+   * @return The image or an uninitialized image in case the ImageActor was cleared.
+   */
+  ImagePtr GetImage();
+
+  /**
+   * Set a region of the image to display, in pixels.
+   * @param [in] pixelArea The area of the image to display.
+   * This in pixels, relative to the top-left (0,0) of the image.
+   */
+  void SetPixelArea(const PixelArea& pixelArea);
+
+  /**
+   * Retrieve the region of the image to display, in pixels.
+   * @return The pixel area, or a default-constructed area if none was set.
+   */
+  const PixelArea& GetPixelArea() const
+  {
+    // This is not animatable; the cached value is up-to-date.
+    return mPixelArea;
+  }
+
+  /**
+   * Query whether a pixel area has been set.
+   * @return True if a pixel area has been set.
+   */
+  bool IsPixelAreaSet() const
+  {
+    // This is not animatable; the cached value is up-to-date.
+    return mIsPixelAreaSet;
+  }
+
+  /**
+   * Remove any pixel areas specified with SetPixelArea; the entire image will be displayed.
+   * @pre image must be initialized.
+   */
+  void ClearPixelArea();
+
+  /**
+   * Set how the ImageAttachment is rendered; the default is STYLE_QUAD.
+   * @param [in] style The new style.
+   */
+  void SetStyle(Style style);
+
+  /**
+   * Query how the image is rendered.
+   * @return The rendering style.
+   */
+  Style GetStyle()
+  {
+    // This is not animatable; the cached value is up-to-date.
+    return mStyle;
+  }
+
+  /**
+   * @copydoc Dali::ImageActor::SetNinePatchBorder
+   */
+  void SetNinePatchBorder(const Vector4& border, bool inPixels);
+
+  /**
+   * @copydoc Dali::ImageActor::GetNinePatchBorder
+   */
+  Vector4 GetNinePatchBorder()
+  {
+    // This is not animatable; the cached value is up-to-date.
+    return mBorder;
+  }
+
+
+  /**
+   * Set the depth-sort modifier for the renderable.
+   * This modifies the back-to-front distance calculation, when rendering with transparency.
+   * This is useful for ordering transparent objects that are positioned close to each other.
+   * @param[in] modifier The depth-sort modifier.
+   */
+  void SetSortModifier(float modifier);
+
+  /**
+   * From Renderable; Retrieve the depth-sort modifier for the renderable.
+   * @return The depth-sort modifier.
+   */
+  float GetSortModifier() const;
+
+  /**
+   * Set the face-culling mode for this attachment.
+   * @param[in] mode The culling mode.
+   */
+  void SetCullFace(CullFaceMode mode);
+
+  /**
+   * Retrieve the face-culling mode for this attachment.
+   * @return mode The culling mode.
+   */
+  CullFaceMode GetCullFace() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendMode()
+   */
+  void SetBlendMode( BlendingMode::Type mode );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendMode()
+   */
+  BlendingMode::Type GetBlendMode() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  void GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendEquation()
+   */
+  void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendColor()
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendColor()
+   */
+  const Vector4& GetBlendColor() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetFilterMode()
+   */
+  void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetFilterMode()
+   */
+  void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetShaderEffect
+   */
+  void SetShaderEffect(ShaderEffect& effect);
+
+  /**
+   * @copydoc Dali::RenderableActor::GetShaderEffect
+   */
+  ShaderEffectPtr GetShaderEffect() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::RemoveShaderEffect
+   */
+  void RemoveShaderEffect();
+
+private:
+
+  /**
+   * First stage construction of a ImageAttachment.
+   * @param[in] eventThreadServices Used for messaging to and reading from scene-graph.
+   */
+  ImageAttachment( EventThreadServices& eventThreadServices );
+
+  /**
+   * Creates the corresponding scene-graph ImageAttachment.
+   * @return A newly allocated scene object.
+   */
+  static SceneGraph::ImageAttachment* CreateSceneObject();
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::OnStageConnection2()
+   */
+  virtual void OnStageConnection2();
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::OnStageDisconnection2()
+   */
+  virtual void OnStageDisconnection2();
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::GetSceneObject()
+   */
+  const SceneGraph::ImageAttachment& GetSceneObject() const;
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ImageAttachment();
+
+private:
+
+  const SceneGraph::ImageAttachment* mSceneObject; ///< Not owned
+
+  ImageConnector mImageConnectable; ///< Manages the image displayed by the attachment
+
+  // Cached for public getters
+
+  PixelArea mPixelArea;
+
+  Style mStyle;
+  Vector4 mBorder;
+
+  bool mIsPixelAreaSet : 1;
+  bool mBorderInPixels : 1;
+
+  BlendingOptions    mBlendingOptions;
+  unsigned int       mSamplerBitfield;
+  float              mSortModifier;
+  CullFaceMode       mCullFaceMode:3;  ///< cullface mode, 3 bits enough for 4 values
+  BlendingMode::Type mBlendingMode:2;  ///< blending mode, 2 bits enough for 3 values
+
+  ShaderEffectPtr    mShaderEffect;    ///< Optional referenced shader effect
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_ATTACHMENT_H__
diff --git a/dali/internal/event/actor-attachments/renderable-attachment-impl.cpp b/dali/internal/event/actor-attachments/renderable-attachment-impl.cpp
new file mode 100644 (file)
index 0000000..9902e82
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actor-attachments/renderable-attachment-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+
+using Dali::Internal::SceneGraph::Shader;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+RenderableAttachment::RenderableAttachment( EventThreadServices& eventThreadServices )
+: ActorAttachment( eventThreadServices )
+{
+}
+
+RenderableAttachment::~RenderableAttachment()
+{
+}
+
+void RenderableAttachment::OnStageConnection()
+{
+  // For derived classes
+  OnStageConnection2();
+}
+
+void RenderableAttachment::OnStageDisconnection()
+{
+  // For derived classes
+  OnStageDisconnection2();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actor-attachments/renderable-attachment-impl.h b/dali/internal/event/actor-attachments/renderable-attachment-impl.h
new file mode 100644 (file)
index 0000000..87d51d9
--- /dev/null
@@ -0,0 +1,99 @@
+#ifndef __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__
+#define __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderableAttachment;
+}
+
+/**
+ * An base class for renderable actor attachments
+ */
+class RenderableAttachment : public ActorAttachment
+{
+public:
+
+
+
+protected:
+
+  /**
+   * Protected constructor; only base classes are instantiatable.
+   * @param[in] eventThreadServices Used for messaging to and reading from scene-graph.
+   */
+  RenderableAttachment( EventThreadServices& eventThreadServices );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~RenderableAttachment();
+
+private:
+
+  // Undefined
+  RenderableAttachment(const RenderableAttachment&);
+
+  // Undefined
+  RenderableAttachment& operator=(const RenderableAttachment& rhs);
+
+  /**
+   * Helper for getting the scene-graph renderable attachment.
+   * @return The scene object.
+   */
+  const SceneGraph::RenderableAttachment& GetSceneAttachment() const;
+
+  /**
+   * @copydoc Dali::Internal::ActorAttachment::OnStageConnection()
+   */
+  virtual void OnStageConnection();
+
+  /**
+   * @copydoc Dali::Internal::ActorAttachment::OnStageDisconnection()
+   */
+  virtual void OnStageDisconnection();
+
+  /**
+   * For derived classes, chained from OnStageConnection()
+   */
+  virtual void OnStageConnection2() = 0;
+
+  /**
+   * For derived classes, chained from OnStageDisconnection()
+   */
+  virtual void OnStageDisconnection2() = 0;
+
+private: // Data, cached for actor-thread getters
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RENDERABLE_ATTACHMENT_H__
diff --git a/dali/internal/event/actor-attachments/renderer-attachment-impl.cpp b/dali/internal/event/actor-attachments/renderer-attachment-impl.cpp
new file mode 100644 (file)
index 0000000..56ee7ca
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actor-attachments/renderer-attachment-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+RendererAttachmentPtr RendererAttachment::New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer )
+{
+  RendererAttachmentPtr attachment( new RendererAttachment( eventThreadServices ) );
+
+  if( attachment )
+  {
+    attachment->Initialize( eventThreadServices, parentNode, renderer );
+  }
+  return attachment;
+}
+
+void RendererAttachment::Initialize( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer )
+{
+  SceneGraph::RendererAttachment* sceneObject = renderer.GetRendererSceneObject();
+
+  // Takes ownership of scene object
+  AttachToNodeMessage( eventThreadServices.GetUpdateManager(), parentNode, sceneObject );
+
+  // Connect to renderer
+  mRendererConnector.Set( renderer, false );
+
+  // Keep raw pointer for message passing
+  mSceneObject = sceneObject;
+}
+
+RendererAttachment::RendererAttachment( EventThreadServices& eventThreadServices )
+: RenderableAttachment(eventThreadServices),
+  mSceneObject(NULL)
+{
+}
+
+RendererAttachment::~RendererAttachment()
+{
+}
+
+const SceneGraph::RendererAttachment& RendererAttachment::GetSceneObject() const
+{
+  DALI_ASSERT_DEBUG( mSceneObject != NULL );
+  return *mSceneObject;
+}
+
+void RendererAttachment::OnStageConnection2()
+{
+  mRendererConnector.OnStageConnect();
+}
+
+void RendererAttachment::OnStageDisconnection2()
+{
+  mRendererConnector.OnStageDisconnect();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actor-attachments/renderer-attachment-impl.h b/dali/internal/event/actor-attachments/renderer-attachment-impl.h
new file mode 100644 (file)
index 0000000..a61be66
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef DALI_INTERNAL_RENDERER_ATTACHMENT_H
+#define DALI_INTERNAL_RENDERER_ATTACHMENT_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actor-attachments/renderable-attachment-impl.h>
+#include <dali/internal/event/common/object-connector.h>
+#include <dali/internal/event/rendering/renderer-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class Node;
+class RendererAttachment;
+}
+
+class RendererAttachment;
+typedef IntrusivePtr<RendererAttachment>  RendererAttachmentPtr;
+
+/**
+ * An attachment for rendering renderers.
+ *
+ * Currently, the Renderer object creates the SceneGraph::RendererAttachment object, not this. It is attached
+ * here as needed.
+ */
+class RendererAttachment : public RenderableAttachment
+{
+public:
+
+  /**
+   * Create a new RendererAttachment.
+   * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph
+   * @param[in] parentNode The node to attach a scene-object to.
+   * @poaram[in] renderer The renderer for this attachment
+   * @return A smart-pointer to the newly allocated RendererAttachment.
+   */
+  static RendererAttachmentPtr New( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer );
+
+
+  /**
+   * Second stage initialization
+   *
+   * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph
+   * @param[in] parentNode The node to attach a scene-object to.
+   * @poaram[in] renderer The renderer for this attachment
+   */
+  void Initialize( EventThreadServices& eventThreadServices, const SceneGraph::Node& parentNode, Renderer& renderer );
+
+  /**
+   * Get the renderer
+   *
+   * @return The renderer
+   */
+  Renderer& GetRenderer()
+  {
+    return *mRendererConnector.Get();
+  }
+
+private:
+
+  /**
+   * First stage construction of a RendererAttachment.
+   * @param[in] eventThreadServices Used for messaging to and reading from the SceneGraph
+   */
+  RendererAttachment( EventThreadServices& eventThreadServices );
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::GetSceneObject()
+   */
+  virtual const SceneGraph::RendererAttachment& GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::OnStageConnection2()
+   */
+  virtual void OnStageConnection2();
+
+  /**
+   * @copydoc Dali::Internal::RenderableAttachment::OnStageDisconnection2()
+   */
+  virtual void OnStageDisconnection2();
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~RendererAttachment();
+
+private:
+  const SceneGraph::RendererAttachment* mSceneObject; ///< Not owned
+
+  ObjectConnector<Renderer> mRendererConnector;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_RENDERER_ATTACHMENT_H
diff --git a/dali/internal/event/actors/actor-declarations.h b/dali/internal/event/actors/actor-declarations.h
new file mode 100644 (file)
index 0000000..a4b1e10
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef __DALI_INTERNAL_ACTOR_DECLARATIONS_H__
+#define __DALI_INTERNAL_ACTOR_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Actor;
+class CameraActor;
+class CustomActor;
+class ImageActor;
+class Layer;
+
+typedef IntrusivePtr<Actor>       ActorPtr;
+typedef IntrusivePtr<CameraActor> CameraActorPtr;
+typedef IntrusivePtr<CustomActor> CustomActorPtr;
+typedef IntrusivePtr<ImageActor>  ImageActorPtr;
+typedef IntrusivePtr<Layer>       LayerPtr;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_DECLARATIONS_H__
diff --git a/dali/internal/event/actors/actor-impl.cpp b/dali/internal/event/actors/actor-impl.cpp
new file mode 100644 (file)
index 0000000..dca7ba4
--- /dev/null
@@ -0,0 +1,4113 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/actor-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cmath>
+#include <algorithm>
+#include <cfloat>
+
+// INTERNAL INCLUDES
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/scripting/scripting.h>
+
+#include <dali/internal/common/internal-constants.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/type-info-impl.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+#include <dali/internal/event/actor-attachments/renderer-attachment-impl.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/common/projection.h>
+#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/nodes/node-messages.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+#include <dali/internal/update/animation/scene-graph-constraint.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
+#include <dali/internal/common/message.h>
+#include <dali/integration-api/debug.h>
+
+using Dali::Internal::SceneGraph::Node;
+using Dali::Internal::SceneGraph::AnimatableProperty;
+using Dali::Internal::SceneGraph::PropertyBase;
+
+namespace Dali
+{
+namespace ResizePolicy
+{
+
+namespace
+{
+DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
+DALI_ENUM_TO_STRING( FIXED )
+DALI_ENUM_TO_STRING( USE_NATURAL_SIZE )
+DALI_ENUM_TO_STRING( FILL_TO_PARENT )
+DALI_ENUM_TO_STRING( SIZE_RELATIVE_TO_PARENT )
+DALI_ENUM_TO_STRING( SIZE_FIXED_OFFSET_FROM_PARENT )
+DALI_ENUM_TO_STRING( FIT_TO_CHILDREN )
+DALI_ENUM_TO_STRING( DIMENSION_DEPENDENCY )
+DALI_ENUM_TO_STRING( USE_ASSIGNED_SIZE )
+DALI_ENUM_TO_STRING_TABLE_END( Type )
+
+} // unnamed namespace
+} // ResizePolicy
+
+namespace SizeScalePolicy
+{
+namespace
+{
+// Enumeration to / from string conversion tables
+DALI_ENUM_TO_STRING_TABLE_BEGIN( Type )
+DALI_ENUM_TO_STRING( USE_SIZE_SET )
+DALI_ENUM_TO_STRING( FIT_WITH_ASPECT_RATIO )
+DALI_ENUM_TO_STRING( FILL_WITH_ASPECT_RATIO )
+DALI_ENUM_TO_STRING_TABLE_END( Type )
+} // unnamed namespace
+} // SizeScalePolicy
+
+namespace Internal
+{
+
+unsigned int Actor::mActorCounter = 0;
+
+namespace
+{
+/// Using a function because of library initialisation order. Vector3::ONE may not have been initialised yet.
+inline const Vector3& GetDefaultSizeModeFactor()
+{
+  return Vector3::ONE;
+}
+
+/// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
+inline const Vector2& GetDefaultPreferredSize()
+{
+  return Vector2::ZERO;
+}
+
+/// Using a function because of library initialisation order. Vector2::ZERO may not have been initialised yet.
+inline const Vector2& GetDefaultDimensionPadding()
+{
+  return Vector2::ZERO;
+}
+
+const SizeScalePolicy::Type DEFAULT_SIZE_SCALE_POLICY = SizeScalePolicy::USE_SIZE_SET;
+
+} // unnamed namespace
+
+/**
+ * Struct to collect relayout variables
+ */
+struct Actor::RelayoutData
+{
+  RelayoutData()
+    : sizeModeFactor( GetDefaultSizeModeFactor() ), preferredSize( GetDefaultPreferredSize() ), sizeSetPolicy( DEFAULT_SIZE_SCALE_POLICY ), relayoutEnabled( false ), insideRelayout( false )
+  {
+    // Set size negotiation defaults
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      resizePolicies[ i ] = ResizePolicy::DEFAULT;
+      negotiatedDimensions[ i ] = 0.0f;
+      dimensionNegotiated[ i ] = false;
+      dimensionDirty[ i ] = false;
+      dimensionDependencies[ i ] = Dimension::ALL_DIMENSIONS;
+      dimensionPadding[ i ] = GetDefaultDimensionPadding();
+      minimumSize[ i ] = 0.0f;
+      maximumSize[ i ] = FLT_MAX;
+    }
+  }
+
+  ResizePolicy::Type resizePolicies[ Dimension::DIMENSION_COUNT ];      ///< Resize policies
+
+  Dimension::Type dimensionDependencies[ Dimension::DIMENSION_COUNT ];  ///< A list of dimension dependencies
+
+  Vector2 dimensionPadding[ Dimension::DIMENSION_COUNT ];         ///< Padding for each dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
+
+  float negotiatedDimensions[ Dimension::DIMENSION_COUNT ];       ///< Storage for when a dimension is negotiated but before set on actor
+
+  float minimumSize[ Dimension::DIMENSION_COUNT ];                ///< The minimum size an actor can be
+  float maximumSize[ Dimension::DIMENSION_COUNT ];                ///< The maximum size an actor can be
+
+  bool dimensionNegotiated[ Dimension::DIMENSION_COUNT ];         ///< Has the dimension been negotiated
+  bool dimensionDirty[ Dimension::DIMENSION_COUNT ];              ///< Flags indicating whether the layout dimension is dirty or not
+
+  Vector3 sizeModeFactor;                              ///< Factor of size used for certain SizeModes
+
+  Vector2 preferredSize;                               ///< The preferred size of the actor
+
+  SizeScalePolicy::Type sizeSetPolicy :3;            ///< Policy to apply when setting size. Enough room for the enum
+
+  bool relayoutEnabled :1;                   ///< Flag to specify if this actor should be included in size negotiation or not (defaults to true)
+  bool insideRelayout :1;                    ///< Locking flag to prevent recursive relayouts on size set
+};
+
+namespace // unnamed namespace
+{
+
+// Properties
+
+/**
+ * We want to discourage the use of property strings (minimize string comparisons),
+ * particularly for the default properties.
+ *              Name                Type   writable animatable constraint-input  enum for index-checking
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "parent-origin",     VECTOR3,  true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN )
+DALI_PROPERTY( "parent-origin-x",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_X )
+DALI_PROPERTY( "parent-origin-y",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Y )
+DALI_PROPERTY( "parent-origin-z",   FLOAT,    true,  false, true,  Dali::Actor::Property::PARENT_ORIGIN_Z )
+DALI_PROPERTY( "anchor-point",      VECTOR3,  true,  false, true,  Dali::Actor::Property::ANCHOR_POINT )
+DALI_PROPERTY( "anchor-point-x",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_X )
+DALI_PROPERTY( "anchor-point-y",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Y )
+DALI_PROPERTY( "anchor-point-z",    FLOAT,    true,  false, true,  Dali::Actor::Property::ANCHOR_POINT_Z )
+DALI_PROPERTY( "size",              VECTOR3,  true,  true,  true,  Dali::Actor::Property::SIZE )
+DALI_PROPERTY( "size-width",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_WIDTH )
+DALI_PROPERTY( "size-height",       FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_HEIGHT )
+DALI_PROPERTY( "size-depth",        FLOAT,    true,  true,  true,  Dali::Actor::Property::SIZE_DEPTH )
+DALI_PROPERTY( "position",          VECTOR3,  true,  true,  true,  Dali::Actor::Property::POSITION )
+DALI_PROPERTY( "position-x",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_X )
+DALI_PROPERTY( "position-y",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Y )
+DALI_PROPERTY( "position-z",        FLOAT,    true,  true,  true,  Dali::Actor::Property::POSITION_Z )
+DALI_PROPERTY( "world-position",    VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_POSITION )
+DALI_PROPERTY( "world-position-x",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_X )
+DALI_PROPERTY( "world-position-y",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Y )
+DALI_PROPERTY( "world-position-z",  FLOAT,    false, false, true,  Dali::Actor::Property::WORLD_POSITION_Z )
+DALI_PROPERTY( "orientation",       ROTATION, true,  true,  true,  Dali::Actor::Property::ORIENTATION )
+DALI_PROPERTY( "world-orientation", ROTATION, false, false, true,  Dali::Actor::Property::WORLD_ORIENTATION )
+DALI_PROPERTY( "scale",             VECTOR3,  true,  true,  true,  Dali::Actor::Property::SCALE )
+DALI_PROPERTY( "scale-x",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_X )
+DALI_PROPERTY( "scale-y",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Y )
+DALI_PROPERTY( "scale-z",           FLOAT,    true,  true,  true,  Dali::Actor::Property::SCALE_Z )
+DALI_PROPERTY( "world-scale",       VECTOR3,  false, false, true,  Dali::Actor::Property::WORLD_SCALE )
+DALI_PROPERTY( "visible",           BOOLEAN,  true,  true,  true,  Dali::Actor::Property::VISIBLE )
+DALI_PROPERTY( "color",             VECTOR4,  true,  true,  true,  Dali::Actor::Property::COLOR )
+DALI_PROPERTY( "color-red",         FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_RED )
+DALI_PROPERTY( "color-green",       FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_GREEN )
+DALI_PROPERTY( "color-blue",        FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_BLUE )
+DALI_PROPERTY( "color-alpha",       FLOAT,    true,  true,  true,  Dali::Actor::Property::COLOR_ALPHA )
+DALI_PROPERTY( "world-color",       VECTOR4,  false, false, true,  Dali::Actor::Property::WORLD_COLOR )
+DALI_PROPERTY( "world-matrix",      MATRIX,   false, false, true,  Dali::Actor::Property::WORLD_MATRIX )
+DALI_PROPERTY( "name",              STRING,   true,  false, false, Dali::Actor::Property::NAME )
+DALI_PROPERTY( "sensitive",         BOOLEAN,  true,  false, false, Dali::Actor::Property::SENSITIVE )
+DALI_PROPERTY( "leave-required",    BOOLEAN,  true,  false, false, Dali::Actor::Property::LEAVE_REQUIRED )
+DALI_PROPERTY( "inherit-orientation",BOOLEAN, true,  false, false, Dali::Actor::Property::INHERIT_ORIENTATION )
+DALI_PROPERTY( "inherit-scale",     BOOLEAN,  true,  false, false, Dali::Actor::Property::INHERIT_SCALE )
+DALI_PROPERTY( "color-mode",        STRING,   true,  false, false, Dali::Actor::Property::COLOR_MODE )
+DALI_PROPERTY( "position-inheritance",STRING, true,  false, false, Dali::Actor::Property::POSITION_INHERITANCE )
+DALI_PROPERTY( "draw-mode",         STRING,   true,  false, false, Dali::Actor::Property::DRAW_MODE )
+DALI_PROPERTY( "size-mode-factor",  VECTOR3,  true,  false, false, Dali::Actor::Property::SIZE_MODE_FACTOR )
+DALI_PROPERTY( "width-resize-policy",STRING,  true,  false, false, Dali::Actor::Property::WIDTH_RESIZE_POLICY )
+DALI_PROPERTY( "height-resize-policy",STRING, true,  false, false, Dali::Actor::Property::HEIGHT_RESIZE_POLICY )
+DALI_PROPERTY( "size-scale-policy", STRING,   true,  false, false, Dali::Actor::Property::SIZE_SCALE_POLICY )
+DALI_PROPERTY( "width-for-height",  BOOLEAN,  true,  false, false, Dali::Actor::Property::WIDTH_FOR_HEIGHT )
+DALI_PROPERTY( "height-for-width",  BOOLEAN,  true,  false, false, Dali::Actor::Property::HEIGHT_FOR_WIDTH )
+DALI_PROPERTY( "padding",           VECTOR4,  true,  false, false, Dali::Actor::Property::PADDING )
+DALI_PROPERTY( "minimum-size",      VECTOR2,  true,  false, false, Dali::Actor::Property::MINIMUM_SIZE )
+DALI_PROPERTY( "maximum-size",      VECTOR2,  true,  false, false, Dali::Actor::Property::MAXIMUM_SIZE )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+// Signals
+
+const char* const SIGNAL_TOUCHED = "touched";
+const char* const SIGNAL_HOVERED = "hovered";
+const char* const SIGNAL_WHEEL_EVENT = "wheel-event";
+const char* const SIGNAL_ON_STAGE = "on-stage";
+const char* const SIGNAL_OFF_STAGE = "off-stage";
+
+// Actions
+
+const char* const ACTION_SHOW = "show";
+const char* const ACTION_HIDE = "hide";
+
+BaseHandle CreateActor()
+{
+  return Dali::Actor::New();
+}
+
+TypeRegistration mType( typeid(Dali::Actor), typeid(Dali::Handle), CreateActor );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_TOUCHED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector2( mType, SIGNAL_HOVERED, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector3( mType, SIGNAL_ON_STAGE, &Actor::DoConnectSignal );
+SignalConnectorType signalConnector4( mType, SIGNAL_OFF_STAGE, &Actor::DoConnectSignal );
+
+TypeAction a1( mType, ACTION_SHOW, &Actor::DoAction );
+TypeAction a2( mType, ACTION_HIDE, &Actor::DoAction );
+
+/**
+ * @brief Extract a given dimension from a Vector2
+ *
+ * @param[in] values The values to extract from
+ * @param[in] dimension The dimension to extract
+ * @return Return the value for the dimension
+ */
+float GetDimensionValue( const Vector2& values, Dimension::Type dimension )
+{
+  switch( dimension )
+  {
+    case Dimension::WIDTH:
+    {
+      return values.width;
+    }
+    case Dimension::HEIGHT:
+    {
+      return values.height;
+    }
+    default:
+    {
+      break;
+    }
+  }
+  return 0.0f;
+}
+
+/**
+ * @brief Extract a given dimension from a Vector3
+ *
+ * @param[in] values The values to extract from
+ * @param[in] dimension The dimension to extract
+ * @return Return the value for the dimension
+ */
+float GetDimensionValue( const Vector3& values, Dimension::Type dimension )
+{
+  return GetDimensionValue( values.GetVectorXY(), dimension );
+}
+
+
+} // unnamed namespace
+
+ActorPtr Actor::New()
+{
+  ActorPtr actor( new Actor( BASIC ) );
+
+  // Second-phase construction
+  actor->Initialize();
+
+  return actor;
+}
+
+const std::string& Actor::GetName() const
+{
+  return mName;
+}
+
+void Actor::SetName( const std::string& name )
+{
+  mName = name;
+
+  if( NULL != mNode )
+  {
+    // ATTENTION: string for debug purposes is not thread safe.
+    DALI_LOG_SET_OBJECT_STRING( const_cast< SceneGraph::Node* >( mNode ), name );
+  }
+}
+
+unsigned int Actor::GetId() const
+{
+  return mId;
+}
+
+void Actor::Attach( ActorAttachment& attachment )
+{
+  DALI_ASSERT_DEBUG( !mAttachment && "An Actor can only have one attachment" );
+
+  if( OnStage() )
+  {
+    attachment.Connect();
+  }
+
+  mAttachment = ActorAttachmentPtr( &attachment );
+}
+
+ActorAttachmentPtr Actor::GetAttachment()
+{
+  return mAttachment;
+}
+
+bool Actor::OnStage() const
+{
+  return mIsOnStage;
+}
+
+Dali::Layer Actor::GetLayer()
+{
+  Dali::Layer layer;
+
+  // Short-circuit for Layer derived actors
+  if( mIsLayer )
+  {
+    layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( this ) ); // static cast as we trust the flag
+  }
+
+  // Find the immediate Layer parent
+  for( Actor* parent = mParent; !layer && parent != NULL; parent = parent->GetParent() )
+  {
+    if( parent->IsLayer() )
+    {
+      layer = Dali::Layer( static_cast< Dali::Internal::Layer* >( parent ) ); // static cast as we trust the flag
+    }
+  }
+
+  return layer;
+}
+
+void Actor::Add( Actor& child )
+{
+  DALI_ASSERT_ALWAYS( this != &child && "Cannot add actor to itself" );
+  DALI_ASSERT_ALWAYS( !child.IsRoot() && "Cannot add root actor" );
+
+  if( !mChildren )
+  {
+    mChildren = new ActorContainer;
+  }
+
+  Actor* const oldParent( child.mParent );
+
+  // child might already be ours
+  if( this != oldParent )
+  {
+    // if we already have parent, unparent us first
+    if( oldParent )
+    {
+      oldParent->Remove( child ); // This causes OnChildRemove callback
+
+      // Old parent may need to readjust to missing child
+      if( oldParent->RelayoutDependentOnChildren() )
+      {
+        oldParent->RelayoutRequest();
+      }
+    }
+
+    // Guard against Add() during previous OnChildRemove callback
+    if( !child.mParent )
+    {
+      // Do this first, since user callbacks from within SetParent() may need to remove child
+      mChildren->push_back( ActorPtr( &child ) );
+
+      // SetParent asserts that child can be added
+      child.SetParent( this );
+
+      // Notification for derived classes
+      OnChildAdd( child );
+
+      // Only put in a relayout request if there is a suitable dependency
+      if( RelayoutDependentOnChildren() )
+      {
+        RelayoutRequest();
+      }
+    }
+  }
+}
+
+void Actor::Remove( Actor& child )
+{
+  if( (this == &child) || (!mChildren) )
+  {
+    // no children or removing itself
+    return;
+  }
+
+  ActorPtr removed;
+
+  // Find the child in mChildren, and unparent it
+  ActorIter end = mChildren->end();
+  for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
+  {
+    ActorPtr actor = (*iter);
+
+    if( actor.Get() == &child )
+    {
+      // Keep handle for OnChildRemove notification
+      removed = actor;
+
+      // Do this first, since user callbacks from within SetParent() may need to add the child
+      mChildren->erase( iter );
+
+      DALI_ASSERT_DEBUG( actor->GetParent() == this );
+      actor->SetParent( NULL );
+
+      break;
+    }
+  }
+
+  if( removed )
+  {
+    // Notification for derived classes
+    OnChildRemove( *(removed.Get()) );
+
+    // Only put in a relayout request if there is a suitable dependency
+    if( RelayoutDependentOnChildren() )
+    {
+      RelayoutRequest();
+    }
+  }
+}
+
+void Actor::Unparent()
+{
+  if( mParent )
+  {
+    // Remove this actor from the parent. The remove will put a relayout request in for
+    // the parent if required
+    mParent->Remove( *this );
+    // mParent is now NULL!
+  }
+}
+
+unsigned int Actor::GetChildCount() const
+{
+  return ( NULL != mChildren ) ? mChildren->size() : 0;
+}
+
+ActorPtr Actor::GetChildAt( unsigned int index ) const
+{
+  DALI_ASSERT_ALWAYS( index < GetChildCount() );
+
+  return ( ( mChildren ) ? ( *mChildren )[ index ] : ActorPtr() );
+}
+
+ActorPtr Actor::FindChildByName( const std::string& actorName )
+{
+  ActorPtr child = 0;
+  if( actorName == mName )
+  {
+    child = this;
+  }
+  else if( mChildren )
+  {
+    ActorIter end = mChildren->end();
+    for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
+    {
+      child = (*iter)->FindChildByName( actorName );
+
+      if( child )
+      {
+        break;
+      }
+    }
+  }
+  return child;
+}
+
+ActorPtr Actor::FindChildById( const unsigned int id )
+{
+  ActorPtr child = 0;
+  if( id == mId )
+  {
+    child = this;
+  }
+  else if( mChildren )
+  {
+    ActorIter end = mChildren->end();
+    for( ActorIter iter = mChildren->begin(); iter != end; ++iter )
+    {
+      child = (*iter)->FindChildById( id );
+
+      if( child )
+      {
+        break;
+      }
+    }
+  }
+  return child;
+}
+
+void Actor::SetParentOrigin( const Vector3& origin )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SetParentOriginMessage( GetEventThreadServices(), *mNode, origin );
+  }
+
+  // Cache for event-thread access
+  if( !mParentOrigin )
+  {
+    // not allocated, check if different from default
+    if( ParentOrigin::DEFAULT != origin )
+    {
+      mParentOrigin = new Vector3( origin );
+    }
+  }
+  else
+  {
+    // check if different from current costs more than just set
+    *mParentOrigin = origin;
+  }
+}
+
+void Actor::SetParentOriginX( float x )
+{
+  const Vector3& current = GetCurrentParentOrigin();
+
+  SetParentOrigin( Vector3( x, current.y, current.z ) );
+}
+
+void Actor::SetParentOriginY( float y )
+{
+  const Vector3& current = GetCurrentParentOrigin();
+
+  SetParentOrigin( Vector3( current.x, y, current.z ) );
+}
+
+void Actor::SetParentOriginZ( float z )
+{
+  const Vector3& current = GetCurrentParentOrigin();
+
+  SetParentOrigin( Vector3( current.x, current.y, z ) );
+}
+
+const Vector3& Actor::GetCurrentParentOrigin() const
+{
+  // Cached for event-thread access
+  return ( mParentOrigin ) ? *mParentOrigin : ParentOrigin::DEFAULT;
+}
+
+void Actor::SetAnchorPoint( const Vector3& anchor )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SetAnchorPointMessage( GetEventThreadServices(), *mNode, anchor );
+  }
+
+  // Cache for event-thread access
+  if( !mAnchorPoint )
+  {
+    // not allocated, check if different from default
+    if( AnchorPoint::DEFAULT != anchor )
+    {
+      mAnchorPoint = new Vector3( anchor );
+    }
+  }
+  else
+  {
+    // check if different from current costs more than just set
+    *mAnchorPoint = anchor;
+  }
+}
+
+void Actor::SetAnchorPointX( float x )
+{
+  const Vector3& current = GetCurrentAnchorPoint();
+
+  SetAnchorPoint( Vector3( x, current.y, current.z ) );
+}
+
+void Actor::SetAnchorPointY( float y )
+{
+  const Vector3& current = GetCurrentAnchorPoint();
+
+  SetAnchorPoint( Vector3( current.x, y, current.z ) );
+}
+
+void Actor::SetAnchorPointZ( float z )
+{
+  const Vector3& current = GetCurrentAnchorPoint();
+
+  SetAnchorPoint( Vector3( current.x, current.y, z ) );
+}
+
+const Vector3& Actor::GetCurrentAnchorPoint() const
+{
+  // Cached for event-thread access
+  return ( mAnchorPoint ) ? *mAnchorPoint : AnchorPoint::DEFAULT;
+}
+
+void Actor::SetPosition( float x, float y )
+{
+  SetPosition( Vector3( x, y, 0.0f ) );
+}
+
+void Actor::SetPosition( float x, float y, float z )
+{
+  SetPosition( Vector3( x, y, z ) );
+}
+
+void Actor::SetPosition( const Vector3& position )
+{
+  mTargetPosition = position;
+
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::Bake, position );
+  }
+}
+
+void Actor::SetX( float x )
+{
+  mTargetPosition.x = x;
+
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeX, x );
+  }
+}
+
+void Actor::SetY( float y )
+{
+  mTargetPosition.y = y;
+
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeY, y );
+  }
+}
+
+void Actor::SetZ( float z )
+{
+  mTargetPosition.z = z;
+
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeZ, z );
+  }
+}
+
+void Actor::TranslateBy( const Vector3& distance )
+{
+  mTargetPosition += distance;
+
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mPosition, &AnimatableProperty<Vector3>::BakeRelative, distance );
+  }
+}
+
+const Vector3& Actor::GetCurrentPosition() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetPosition(GetEventThreadServices().GetEventBufferIndex());
+  }
+
+  return Vector3::ZERO;
+}
+
+const Vector3& Actor::GetTargetPosition() const
+{
+  return mTargetPosition;
+}
+
+const Vector3& Actor::GetCurrentWorldPosition() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return Vector3::ZERO;
+}
+
+void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
+{
+  // this flag is not animatable so keep the value
+  mPositionInheritanceMode = mode;
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value
+    SetPositionInheritanceModeMessage( GetEventThreadServices(), *mNode, mode );
+  }
+}
+
+PositionInheritanceMode Actor::GetPositionInheritanceMode() const
+{
+  // Cached for event-thread access
+  return mPositionInheritanceMode;
+}
+
+void Actor::SetOrientation( const Radian& angle, const Vector3& axis )
+{
+  Vector3 normalizedAxis( axis.x, axis.y, axis.z );
+  normalizedAxis.Normalize();
+
+  Quaternion orientation( angle, normalizedAxis );
+
+  SetOrientation( orientation );
+}
+
+void Actor::SetOrientation( const Quaternion& orientation )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::Bake, orientation );
+  }
+}
+
+void Actor::RotateBy( const Radian& angle, const Vector3& axis )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, Quaternion(angle, axis) );
+  }
+}
+
+void Actor::RotateBy( const Quaternion& relativeRotation )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, &mNode->mOrientation, &AnimatableProperty<Quaternion>::BakeRelative, relativeRotation );
+  }
+}
+
+const Quaternion& Actor::GetCurrentOrientation() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetOrientation(GetEventThreadServices().GetEventBufferIndex());
+  }
+
+  return Quaternion::IDENTITY;
+}
+
+const Quaternion& Actor::GetCurrentWorldOrientation() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetWorldOrientation( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return Quaternion::IDENTITY;
+}
+
+void Actor::SetScale( float scale )
+{
+  SetScale( Vector3( scale, scale, scale ) );
+}
+
+void Actor::SetScale( float x, float y, float z )
+{
+  SetScale( Vector3( x, y, z ) );
+}
+
+void Actor::SetScale( const Vector3& scale )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::Bake, scale );
+  }
+}
+
+void Actor::SetScaleX( float x )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeX, x );
+  }
+}
+
+void Actor::SetScaleY( float y )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeY, y );
+  }
+}
+
+void Actor::SetScaleZ( float z )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeZ, z );
+  }
+}
+
+void Actor::ScaleBy(const Vector3& relativeScale)
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mScale, &AnimatableProperty<Vector3>::BakeRelativeMultiply, relativeScale );
+  }
+}
+
+const Vector3& Actor::GetCurrentScale() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetScale(GetEventThreadServices().GetEventBufferIndex());
+  }
+
+  return Vector3::ONE;
+}
+
+const Vector3& Actor::GetCurrentWorldScale() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetWorldScale( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return Vector3::ONE;
+}
+
+void Actor::SetInheritScale( bool inherit )
+{
+  // non animateable so keep local copy
+  mInheritScale = inherit;
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value
+    SetInheritScaleMessage( GetEventThreadServices(), *mNode, inherit );
+  }
+}
+
+bool Actor::IsScaleInherited() const
+{
+  return mInheritScale;
+}
+
+Matrix Actor::GetCurrentWorldMatrix() const
+{
+  if( NULL != mNode )
+  {
+    // World matrix is no longer updated unless there is something observing the node.
+    // Need to calculate it from node's world position, orientation and scale:
+    BufferIndex updateBufferIndex = GetEventThreadServices().GetEventBufferIndex();
+    Matrix worldMatrix(false);
+    worldMatrix.SetTransformComponents( mNode->GetWorldScale( updateBufferIndex ),
+                                        mNode->GetWorldOrientation( updateBufferIndex ),
+                                        mNode->GetWorldPosition( updateBufferIndex ) );
+    return worldMatrix;
+  }
+
+  return Matrix::IDENTITY;
+}
+
+void Actor::SetVisible( bool visible )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, &mNode->mVisible, &AnimatableProperty<bool>::Bake, visible );
+  }
+}
+
+bool Actor::IsVisible() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->IsVisible( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return true;
+}
+
+void Actor::SetOpacity( float opacity )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeW, opacity );
+  }
+}
+
+float Actor::GetCurrentOpacity() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetOpacity(GetEventThreadServices().GetEventBufferIndex());
+  }
+
+  return 1.0f;
+}
+
+const Vector4& Actor::GetCurrentWorldColor() const
+{
+  if( NULL != mNode )
+  {
+    return mNode->GetWorldColor( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return Color::WHITE;
+}
+
+void Actor::SetColor( const Vector4& color )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::Bake, color );
+  }
+}
+
+void Actor::SetColorRed( float red )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeX, red );
+  }
+}
+
+void Actor::SetColorGreen( float green )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeY, green );
+  }
+}
+
+void Actor::SetColorBlue( float blue )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, &mNode->mColor, &AnimatableProperty<Vector4>::BakeZ, blue );
+  }
+}
+
+const Vector4& Actor::GetCurrentColor() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetColor(GetEventThreadServices().GetEventBufferIndex());
+  }
+
+  return Color::WHITE;
+}
+
+void Actor::SetInheritOrientation( bool inherit )
+{
+  // non animateable so keep local copy
+  mInheritOrientation = inherit;
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value
+    SetInheritOrientationMessage( GetEventThreadServices(), *mNode, inherit );
+  }
+}
+
+bool Actor::IsOrientationInherited() const
+{
+  return mInheritOrientation;
+}
+
+void Actor::SetSizeModeFactor( const Vector3& factor )
+{
+  EnsureRelayoutData();
+
+  mRelayoutData->sizeModeFactor = factor;
+}
+
+const Vector3& Actor::GetSizeModeFactor() const
+{
+  if ( mRelayoutData )
+  {
+    return mRelayoutData->sizeModeFactor;
+  }
+
+  return GetDefaultSizeModeFactor();
+}
+
+void Actor::SetColorMode( ColorMode colorMode )
+{
+  // non animateable so keep local copy
+  mColorMode = colorMode;
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value
+    SetColorModeMessage( GetEventThreadServices(), *mNode, colorMode );
+  }
+}
+
+ColorMode Actor::GetColorMode() const
+{
+  // we have cached copy
+  return mColorMode;
+}
+
+void Actor::SetSize( float width, float height )
+{
+  SetSize( Vector2( width, height ) );
+}
+
+void Actor::SetSize( float width, float height, float depth )
+{
+  SetSize( Vector3( width, height, depth ) );
+}
+
+void Actor::SetSize( const Vector2& size )
+{
+  SetSize( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
+}
+
+void Actor::SetSizeInternal( const Vector2& size )
+{
+  SetSizeInternal( Vector3( size.width, size.height, CalculateSizeZ( size ) ) );
+}
+
+float Actor::CalculateSizeZ( const Vector2& size ) const
+{
+  return std::min( size.width, size.height );
+}
+
+void Actor::SetSize( const Vector3& size )
+{
+  if( IsRelayoutEnabled() && !mRelayoutData->insideRelayout )
+  {
+    SetPreferredSize( size.GetVectorXY() );
+  }
+  else
+  {
+    SetSizeInternal( size );
+  }
+}
+
+void Actor::SetSizeInternal( const Vector3& size )
+{
+  // dont allow recursive loop
+  DALI_ASSERT_ALWAYS( !mInsideOnSizeSet && "Cannot call SetSize from OnSizeSet" );
+  // check that we have a node AND the new size width, height or depth is at least a little bit different from the old one
+  if( ( NULL != mNode )&&
+      ( ( fabsf( mTargetSize.width - size.width  ) > Math::MACHINE_EPSILON_1 )||
+        ( fabsf( mTargetSize.height- size.height ) > Math::MACHINE_EPSILON_1 )||
+        ( fabsf( mTargetSize.depth - size.depth  ) > Math::MACHINE_EPSILON_1 ) ) )
+  {
+    mTargetSize = size;
+
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::Bake, mTargetSize );
+
+    // Notification for derived classes
+    mInsideOnSizeSet = true;
+    OnSizeSet( mTargetSize );
+    mInsideOnSizeSet = false;
+
+    // Raise a relayout request if the flag is not locked
+    if( mRelayoutData && !mRelayoutData->insideRelayout )
+    {
+      RelayoutRequest();
+    }
+  }
+}
+
+void Actor::NotifySizeAnimation( Animation& animation, const Vector3& targetSize )
+{
+  mTargetSize = targetSize;
+
+  // Notify deriving classes
+  OnSizeAnimation( animation, mTargetSize );
+}
+
+void Actor::NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property )
+{
+  if ( Dali::Actor::Property::SIZE_WIDTH == property )
+  {
+    mTargetSize.width = targetSize;
+  }
+  else if ( Dali::Actor::Property::SIZE_HEIGHT == property )
+  {
+    mTargetSize.height = targetSize;
+  }
+  // Notify deriving classes
+  OnSizeAnimation( animation, mTargetSize );
+}
+
+void Actor::SetWidth( float width )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeX, width );
+  }
+}
+
+void Actor::SetHeight( float height )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeY, height );
+  }
+}
+
+void Actor::SetDepth( float depth )
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value & base value
+    SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, &mNode->mSize, &AnimatableProperty<Vector3>::BakeZ, depth );
+  }
+}
+
+const Vector3& Actor::GetTargetSize() const
+{
+  return mTargetSize;
+}
+
+const Vector3& Actor::GetCurrentSize() const
+{
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; copy the value from the previous update
+    return mNode->GetSize( GetEventThreadServices().GetEventBufferIndex() );
+  }
+
+  return Vector3::ZERO;
+}
+
+Vector3 Actor::GetNaturalSize() const
+{
+  // It is up to deriving classes to return the appropriate natural size
+  return Vector3( 0.0f, 0.0f, 0.0f );
+}
+
+void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->resizePolicies[ i ] = policy;
+    }
+  }
+
+  if( policy == ResizePolicy::DIMENSION_DEPENDENCY )
+  {
+    if( dimension & Dimension::WIDTH )
+    {
+      SetDimensionDependency( Dimension::WIDTH, Dimension::HEIGHT );
+    }
+
+    if( dimension & Dimension::HEIGHT )
+    {
+      SetDimensionDependency( Dimension::HEIGHT, Dimension::WIDTH );
+    }
+  }
+
+  // If calling SetResizePolicy, assume we want relayout enabled
+  SetRelayoutEnabled( true );
+
+  OnSetResizePolicy( policy, dimension );
+
+  // Trigger relayout on this control
+  RelayoutRequest();
+}
+
+ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    // If more than one dimension is requested, just return the first one found
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( ( dimension & ( 1 << i ) ) )
+      {
+        return mRelayoutData->resizePolicies[ i ];
+      }
+    }
+  }
+
+  return ResizePolicy::DEFAULT;
+}
+
+void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
+{
+  EnsureRelayoutData();
+
+  mRelayoutData->sizeSetPolicy = policy;
+}
+
+SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
+{
+  if ( mRelayoutData )
+  {
+    return mRelayoutData->sizeSetPolicy;
+  }
+
+  return DEFAULT_SIZE_SCALE_POLICY;
+}
+
+void Actor::SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->dimensionDependencies[ i ] = dependency;
+    }
+  }
+}
+
+Dimension::Type Actor::GetDimensionDependency( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    // If more than one dimension is requested, just return the first one found
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( ( dimension & ( 1 << i ) ) )
+      {
+        return mRelayoutData->dimensionDependencies[ i ];
+      }
+    }
+  }
+
+  return Dimension::ALL_DIMENSIONS;   // Default
+}
+
+void Actor::SetRelayoutEnabled( bool relayoutEnabled )
+{
+  // If relayout data has not been allocated yet and the client is requesting
+  // to disable it, do nothing
+  if( mRelayoutData || relayoutEnabled )
+  {
+    EnsureRelayoutData();
+
+    mRelayoutData->relayoutEnabled = relayoutEnabled;
+  }
+}
+
+bool Actor::IsRelayoutEnabled() const
+{
+  // Assume that if relayout data has not been allocated yet then
+  // relayout is disabled
+  return mRelayoutData && mRelayoutData->relayoutEnabled;
+}
+
+void Actor::SetLayoutDirty( bool dirty, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->dimensionDirty[ i ] = dirty;
+    }
+  }
+}
+
+bool Actor::IsLayoutDirty( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionDirty[ i ] )
+      {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool Actor::RelayoutPossible( Dimension::Type dimension ) const
+{
+  return mRelayoutData && mRelayoutData->relayoutEnabled && !IsLayoutDirty( dimension );
+}
+
+bool Actor::RelayoutRequired( Dimension::Type dimension ) const
+{
+  return mRelayoutData && mRelayoutData->relayoutEnabled && IsLayoutDirty( dimension );
+}
+
+unsigned int Actor::AddRenderer( Renderer& renderer )
+{
+  //TODO: MESH_REWORK : Add support for multiple renderers
+  if ( ! mAttachment )
+  {
+    mAttachment = RendererAttachment::New( GetEventThreadServices(), *mNode, renderer );
+    if( mIsOnStage )
+    {
+      mAttachment->Connect();
+    }
+  }
+
+  return 0;
+}
+
+unsigned int Actor::GetRendererCount() const
+{
+  //TODO: MESH_REWORK : Add support for multiple renderers
+  RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
+  return attachment ? 1u : 0u;
+}
+
+Renderer& Actor::GetRendererAt( unsigned int index )
+{
+  //TODO: MESH_REWORK : Add support for multiple renderers
+  DALI_ASSERT_DEBUG( index == 0 && "Only one renderer is supported." );
+
+  //TODO: MESH_REWORK : Temporary code
+  RendererAttachment* attachment = dynamic_cast<RendererAttachment*>(mAttachment.Get());
+  DALI_ASSERT_ALWAYS( attachment && "Actor doesn't have a renderer" );
+
+  return attachment->GetRenderer();
+}
+
+void Actor::RemoveRenderer( Renderer& renderer )
+{
+  //TODO: MESH_REWORK : Add support for multiple renderers
+  mAttachment = NULL;
+}
+
+void Actor::RemoveRenderer( unsigned int index )
+{
+  //TODO: MESH_REWORK : Add support for multiple renderers
+  mAttachment = NULL;
+}
+
+void Actor::SetOverlay( bool enable )
+{
+  // Setting STENCIL will override OVERLAY_2D
+  if( DrawMode::STENCIL != mDrawMode )
+  {
+    SetDrawMode( enable ? DrawMode::OVERLAY_2D : DrawMode::NORMAL );
+  }
+}
+
+bool Actor::IsOverlay() const
+{
+  return ( DrawMode::OVERLAY_2D == mDrawMode );
+}
+
+void Actor::SetDrawMode( DrawMode::Type drawMode )
+{
+  // this flag is not animatable so keep the value
+  mDrawMode = drawMode;
+  if( NULL != mNode )
+  {
+    // mNode is being used in a separate thread; queue a message to set the value
+    SetDrawModeMessage( GetEventThreadServices(), *mNode, drawMode );
+  }
+}
+
+DrawMode::Type Actor::GetDrawMode() const
+{
+  return mDrawMode;
+}
+
+bool Actor::ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const
+{
+  // only valid when on-stage
+  StagePtr stage = Stage::GetCurrent();
+  if( stage && OnStage() )
+  {
+    const RenderTaskList& taskList = stage->GetRenderTaskList();
+
+    Vector2 converted( screenX, screenY );
+
+    // do a reverse traversal of all lists (as the default onscreen one is typically the last one)
+    const int taskCount = taskList.GetTaskCount();
+    for( int i = taskCount - 1; i >= 0; --i )
+    {
+      Dali::RenderTask task = taskList.GetTask( i );
+      if( ScreenToLocal( Dali::GetImplementation( task ), localX, localY, screenX, screenY ) )
+      {
+        // found a task where this conversion was ok so return
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+bool Actor::ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const
+{
+  bool retval = false;
+  // only valid when on-stage
+  if( OnStage() )
+  {
+    CameraActor* camera = renderTask.GetCameraActor();
+    if( camera )
+    {
+      Viewport viewport;
+      renderTask.GetViewport( viewport );
+
+      // need to translate coordinates to render tasks coordinate space
+      Vector2 converted( screenX, screenY );
+      if( renderTask.TranslateCoordinates( converted ) )
+      {
+        retval = ScreenToLocal( camera->GetViewMatrix(), camera->GetProjectionMatrix(), viewport, localX, localY, converted.x, converted.y );
+      }
+    }
+  }
+  return retval;
+}
+
+bool Actor::ScreenToLocal( const Matrix& viewMatrix, const Matrix& projectionMatrix, const Viewport& viewport, float& localX, float& localY, float screenX, float screenY ) const
+{
+  // Early-out if mNode is NULL
+  if( !OnStage() )
+  {
+    return false;
+  }
+
+  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
+
+  // Calculate the ModelView matrix
+  Matrix modelView( false/*don't init*/);
+  // need to use the components as world matrix is only updated for actors that need it
+  modelView.SetTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
+  Matrix::Multiply( modelView, modelView, viewMatrix );
+
+  // Calculate the inverted ModelViewProjection matrix; this will be used for 2 unprojects
+  Matrix invertedMvp( false/*don't init*/);
+  Matrix::Multiply( invertedMvp, modelView, projectionMatrix );
+  bool success = invertedMvp.Invert();
+
+  // Convert to GL coordinates
+  Vector4 screenPos( screenX - viewport.x, viewport.height - ( screenY - viewport.y ), 0.f, 1.f );
+
+  Vector4 nearPos;
+  if( success )
+  {
+    success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, nearPos );
+  }
+
+  Vector4 farPos;
+  if( success )
+  {
+    screenPos.z = 1.0f;
+    success = Unproject( screenPos, invertedMvp, viewport.width, viewport.height, farPos );
+  }
+
+  if( success )
+  {
+    Vector4 local;
+    if( XyPlaneIntersect( nearPos, farPos, local ) )
+    {
+      Vector3 size = GetCurrentSize();
+      localX = local.x + size.x * 0.5f;
+      localY = local.y + size.y * 0.5f;
+    }
+    else
+    {
+      success = false;
+    }
+  }
+
+  return success;
+}
+
+bool Actor::RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const
+{
+  /*
+   http://wiki.cgsociety.org/index.php/Ray_Sphere_Intersection
+
+   Mathematical Formulation
+
+   Given the above mentioned sphere, a point 'p' lies on the surface of the sphere if
+
+   ( p - c ) dot ( p - c ) = r^2
+
+   Given a ray with a point of origin 'o', and a direction vector 'd':
+
+   ray(t) = o + td, t >= 0
+
+   we can find the t at which the ray intersects the sphere by setting ray(t) equal to 'p'
+
+   (o + td - c ) dot ( o + td - c ) = r^2
+
+   To solve for t we first expand the above into a more recognisable quadratic equation form
+
+   ( d dot d )t^2 + 2( o - c ) dot dt + ( o - c ) dot ( o - c ) - r^2 = 0
+
+   or
+
+   At2 + Bt + C = 0
+
+   where
+
+   A = d dot d
+   B = 2( o - c ) dot d
+   C = ( o - c ) dot ( o - c ) - r^2
+
+   which can be solved using a standard quadratic formula.
+
+   Note that in the absence of positive, real, roots, the ray does not intersect the sphere.
+
+   Practical Simplification
+
+   In a renderer, we often differentiate between world space and object space. In the object space
+   of a sphere it is centred at origin, meaning that if we first transform the ray from world space
+   into object space, the mathematical solution presented above can be simplified significantly.
+
+   If a sphere is centred at origin, a point 'p' lies on a sphere of radius r2 if
+
+   p dot p = r^2
+
+   and we can find the t at which the (transformed) ray intersects the sphere by
+
+   ( o + td ) dot ( o + td ) = r^2
+
+   According to the reasoning above, we expand the above quadratic equation into the general form
+
+   At2 + Bt + C = 0
+
+   which now has coefficients:
+
+   A = d dot d
+   B = 2( d dot o )
+   C = o dot o - r^2
+   */
+
+  // Early out if mNode is NULL
+  if( !mNode )
+  {
+    return false;
+  }
+
+  BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
+
+  // Transforms the ray to the local reference system. As the test is against a sphere, only the translation and scale are needed.
+  const Vector3& translation( mNode->GetWorldPosition( bufferIndex ) );
+  Vector3 rayOriginLocal( rayOrigin.x - translation.x, rayOrigin.y - translation.y, rayOrigin.z - translation.z );
+
+  // Compute the radius is not needed, square radius it's enough.
+  const Vector3& size( mNode->GetSize( bufferIndex ) );
+
+  // Scale the sphere.
+  const Vector3& scale( mNode->GetWorldScale( bufferIndex ) );
+
+  const float width = size.width * scale.width;
+  const float height = size.height * scale.height;
+
+  float squareSphereRadius = 0.5f * ( width * width + height * height );
+
+  float a = rayDir.Dot( rayDir );                                       // a
+  float b2 = rayDir.Dot( rayOriginLocal );                              // b/2
+  float c = rayOriginLocal.Dot( rayOriginLocal ) - squareSphereRadius;  // c
+
+  return ( b2 * b2 - a * c ) >= 0.f;
+}
+
+bool Actor::RayActorTest( const Vector4& rayOrigin, const Vector4& rayDir, Vector4& hitPointLocal, float& distance ) const
+{
+  bool hit = false;
+
+  if( OnStage() &&
+  NULL != mNode )
+  {
+    // Transforms the ray to the local reference system.
+    // Calculate the inverse of Model matrix
+    Matrix invModelMatrix( false/*don't init*/);
+
+    BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
+    // need to use the components as world matrix is only updated for actors that need it
+    invModelMatrix.SetInverseTransformComponents( mNode->GetWorldScale( bufferIndex ), mNode->GetWorldOrientation( bufferIndex ), mNode->GetWorldPosition( bufferIndex ) );
+
+    Vector4 rayOriginLocal( invModelMatrix * rayOrigin );
+    Vector4 rayDirLocal( invModelMatrix * rayDir - invModelMatrix.GetTranslation() );
+
+    // Test with the actor's XY plane (Normal = 0 0 1 1).
+
+    float a = -rayOriginLocal.z;
+    float b = rayDirLocal.z;
+
+    if( fabsf( b ) > Math::MACHINE_EPSILON_1 )
+    {
+      // Ray travels distance * rayDirLocal to intersect with plane.
+      distance = a / b;
+
+      const Vector3& size = mNode->GetSize( bufferIndex );
+
+      hitPointLocal.x = rayOriginLocal.x + rayDirLocal.x * distance + size.x * 0.5f;
+      hitPointLocal.y = rayOriginLocal.y + rayDirLocal.y * distance + size.y * 0.5f;
+
+      // Test with the actor's geometry.
+      hit = ( hitPointLocal.x >= 0.f ) && ( hitPointLocal.x <= size.x ) && ( hitPointLocal.y >= 0.f ) && ( hitPointLocal.y <= size.y );
+    }
+  }
+
+  return hit;
+}
+
+void Actor::SetLeaveRequired( bool required )
+{
+  mLeaveRequired = required;
+}
+
+bool Actor::GetLeaveRequired() const
+{
+  return mLeaveRequired;
+}
+
+void Actor::SetKeyboardFocusable( bool focusable )
+{
+  mKeyboardFocusable = focusable;
+}
+
+bool Actor::IsKeyboardFocusable() const
+{
+  return mKeyboardFocusable;
+}
+
+bool Actor::GetTouchRequired() const
+{
+  return !mTouchedSignal.Empty() || mDerivedRequiresTouch;
+}
+
+bool Actor::GetHoverRequired() const
+{
+  return !mHoveredSignal.Empty() || mDerivedRequiresHover;
+}
+
+bool Actor::GetWheelEventRequired() const
+{
+  return !mWheelEventSignal.Empty() || mDerivedRequiresWheelEvent;
+}
+
+bool Actor::IsHittable() const
+{
+  return IsSensitive() && IsVisible() && ( GetCurrentWorldColor().a > FULLY_TRANSPARENT ) && IsNodeConnected();
+}
+
+ActorGestureData& Actor::GetGestureData()
+{
+  // Likely scenario is that once gesture-data is created for this actor, the actor will require
+  // that gesture for its entire life-time so no need to destroy it until the actor is destroyed
+  if( NULL == mGestureData )
+  {
+    mGestureData = new ActorGestureData;
+  }
+  return *mGestureData;
+}
+
+bool Actor::IsGestureRequred( Gesture::Type type ) const
+{
+  return mGestureData && mGestureData->IsGestureRequred( type );
+}
+
+bool Actor::EmitTouchEventSignal( const TouchEvent& event )
+{
+  bool consumed = false;
+
+  if( !mTouchedSignal.Empty() )
+  {
+    Dali::Actor handle( this );
+    consumed = mTouchedSignal.Emit( handle, event );
+  }
+
+  if( !consumed )
+  {
+    // Notification for derived classes
+    consumed = OnTouchEvent( event );
+  }
+
+  return consumed;
+}
+
+bool Actor::EmitHoverEventSignal( const HoverEvent& event )
+{
+  bool consumed = false;
+
+  if( !mHoveredSignal.Empty() )
+  {
+    Dali::Actor handle( this );
+    consumed = mHoveredSignal.Emit( handle, event );
+  }
+
+  if( !consumed )
+  {
+    // Notification for derived classes
+    consumed = OnHoverEvent( event );
+  }
+
+  return consumed;
+}
+
+bool Actor::EmitWheelEventSignal( const WheelEvent& event )
+{
+  bool consumed = false;
+
+  if( !mWheelEventSignal.Empty() )
+  {
+    Dali::Actor handle( this );
+    consumed = mWheelEventSignal.Emit( handle, event );
+  }
+
+  if( !consumed )
+  {
+    // Notification for derived classes
+    consumed = OnWheelEvent( event );
+  }
+
+  return consumed;
+}
+
+Dali::Actor::TouchSignalType& Actor::TouchedSignal()
+{
+  return mTouchedSignal;
+}
+
+Dali::Actor::HoverSignalType& Actor::HoveredSignal()
+{
+  return mHoveredSignal;
+}
+
+Dali::Actor::WheelEventSignalType& Actor::WheelEventSignal()
+{
+  return mWheelEventSignal;
+}
+
+Dali::Actor::OnStageSignalType& Actor::OnStageSignal()
+{
+  return mOnStageSignal;
+}
+
+Dali::Actor::OffStageSignalType& Actor::OffStageSignal()
+{
+  return mOffStageSignal;
+}
+
+Dali::Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
+{
+  return mOnRelayoutSignal;
+}
+
+bool Actor::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  Actor* actor = dynamic_cast< Actor* >( object );
+
+  if( 0 == signalName.compare( SIGNAL_TOUCHED ) )
+  {
+    actor->TouchedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_HOVERED ) )
+  {
+    actor->HoveredSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_WHEEL_EVENT ) )
+  {
+    actor->WheelEventSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_ON_STAGE ) )
+  {
+    actor->OnStageSignal().Connect( tracker, functor );
+  }
+  else if( 0 == signalName.compare( SIGNAL_OFF_STAGE ) )
+  {
+    actor->OffStageSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+Actor::Actor( DerivedType derivedType )
+: mParent( NULL ),
+  mChildren( NULL ),
+  mNode( NULL ),
+  mParentOrigin( NULL ),
+  mAnchorPoint( NULL ),
+  mRelayoutData( NULL ),
+  mGestureData( NULL ),
+  mAttachment(),
+  mTargetSize( 0.0f, 0.0f, 0.0f ),
+  mName(),
+  mId( ++mActorCounter ), // actor ID is initialised to start from 1, and 0 is reserved
+  mDepth( 0u ),
+  mIsRoot( ROOT_LAYER == derivedType ),
+  mIsRenderable( RENDERABLE == derivedType ),
+  mIsLayer( LAYER == derivedType || ROOT_LAYER == derivedType ),
+  mIsOnStage( false ),
+  mSensitive( true ),
+  mLeaveRequired( false ),
+  mKeyboardFocusable( false ),
+  mDerivedRequiresTouch( false ),
+  mDerivedRequiresHover( false ),
+  mDerivedRequiresWheelEvent( false ),
+  mOnStageSignalled( false ),
+  mInsideOnSizeSet( false ),
+  mInheritOrientation( true ),
+  mInheritScale( true ),
+  mDrawMode( DrawMode::NORMAL ),
+  mPositionInheritanceMode( Node::DEFAULT_POSITION_INHERITANCE_MODE ),
+  mColorMode( Node::DEFAULT_COLOR_MODE )
+{
+}
+
+void Actor::Initialize()
+{
+  // Node creation
+  SceneGraph::Node* node = CreateNode();
+
+  AddNodeMessage( GetEventThreadServices().GetUpdateManager(), *node ); // Pass ownership to scene-graph
+  mNode = node; // Keep raw-pointer to Node
+
+  OnInitialize();
+
+  GetEventThreadServices().RegisterObject( this );
+}
+
+Actor::~Actor()
+{
+  // Remove mParent pointers from children even if we're destroying core,
+  // to guard against GetParent() & Unparent() calls from CustomActor destructors.
+  if( mChildren )
+  {
+    ActorConstIter endIter = mChildren->end();
+    for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
+    {
+      (*iter)->SetParent( NULL );
+    }
+  }
+  delete mChildren;
+
+  // Guard to allow handle destruction after Core has been destroyed
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    if( NULL != mNode )
+    {
+      DestroyNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
+      mNode = NULL; // Node is about to be destroyed
+    }
+
+    GetEventThreadServices().UnregisterObject( this );
+  }
+
+  // Cleanup optional gesture data
+  delete mGestureData;
+
+  // Cleanup optional parent origin and anchor
+  delete mParentOrigin;
+  delete mAnchorPoint;
+
+  // Delete optional relayout data
+  if( mRelayoutData )
+  {
+    delete mRelayoutData;
+  }
+}
+
+void Actor::ConnectToStage( unsigned int parentDepth, int index )
+{
+  // This container is used instead of walking the Actor hierachy.
+  // It protects us when the Actor hierachy is modified during OnStageConnectionExternal callbacks.
+  ActorContainer connectionList;
+
+
+  // This stage is atomic i.e. not interrupted by user callbacks
+  RecursiveConnectToStage( connectionList, parentDepth+1, index );
+
+  // Notify applications about the newly connected actors.
+  const ActorIter endIter = connectionList.end();
+  for( ActorIter iter = connectionList.begin(); iter != endIter; ++iter )
+  {
+    (*iter)->NotifyStageConnection();
+  }
+
+  RelayoutRequest();
+}
+
+void Actor::RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index )
+{
+  DALI_ASSERT_ALWAYS( !OnStage() );
+
+  mIsOnStage = true;
+  mDepth = depth;
+
+  ConnectToSceneGraph( index );
+
+  // Notification for internal derived classes
+  OnStageConnectionInternal();
+
+  // This stage is atomic; avoid emitting callbacks until all Actors are connected
+  connectionList.push_back( ActorPtr( this ) );
+
+  // Recursively connect children
+  if( mChildren )
+  {
+    ActorConstIter endIter = mChildren->end();
+    for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
+    {
+      (*iter)->RecursiveConnectToStage( connectionList, depth+1 );
+    }
+  }
+}
+
+/**
+ * This method is called when the Actor is connected to the Stage.
+ * The parent must have added its Node to the scene-graph.
+ * The child must connect its Node to the parent's Node.
+ * This is resursive; the child calls ConnectToStage() for its children.
+ */
+void Actor::ConnectToSceneGraph( int index )
+{
+  DALI_ASSERT_DEBUG( mNode != NULL); DALI_ASSERT_DEBUG( mParent != NULL); DALI_ASSERT_DEBUG( mParent->mNode != NULL );
+
+  if( NULL != mNode )
+  {
+    // Reparent Node in next Update
+    ConnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *(mParent->mNode), *mNode, index );
+  }
+
+  // Notify attachment
+  if( mAttachment )
+  {
+    mAttachment->Connect();
+  }
+
+  // Request relayout on all actors that are added to the scenegraph
+  RelayoutRequest();
+
+  // Notification for Object::Observers
+  OnSceneObjectAdd();
+}
+
+void Actor::NotifyStageConnection()
+{
+  // Actors can be removed (in a callback), before the on-stage stage is reported.
+  // The actor may also have been reparented, in which case mOnStageSignalled will be true.
+  if( OnStage() && !mOnStageSignalled )
+  {
+    // Notification for external (CustomActor) derived classes
+    OnStageConnectionExternal( mDepth );
+
+    if( !mOnStageSignal.Empty() )
+    {
+      Dali::Actor handle( this );
+      mOnStageSignal.Emit( handle );
+    }
+
+    // Guard against Remove during callbacks
+    if( OnStage() )
+    {
+      mOnStageSignalled = true; // signal required next time Actor is removed
+    }
+  }
+}
+
+void Actor::DisconnectFromStage()
+{
+  // This container is used instead of walking the Actor hierachy.
+  // It protects us when the Actor hierachy is modified during OnStageDisconnectionExternal callbacks.
+  ActorContainer disconnectionList;
+
+  // This stage is atomic i.e. not interrupted by user callbacks
+  RecursiveDisconnectFromStage( disconnectionList );
+
+  // Notify applications about the newly disconnected actors.
+  const ActorIter endIter = disconnectionList.end();
+  for( ActorIter iter = disconnectionList.begin(); iter != endIter; ++iter )
+  {
+    (*iter)->NotifyStageDisconnection();
+  }
+}
+
+void Actor::RecursiveDisconnectFromStage( ActorContainer& disconnectionList )
+{
+  DALI_ASSERT_ALWAYS( OnStage() );
+
+  // Recursively disconnect children
+  if( mChildren )
+  {
+    ActorConstIter endIter = mChildren->end();
+    for( ActorIter iter = mChildren->begin(); iter != endIter; ++iter )
+    {
+      (*iter)->RecursiveDisconnectFromStage( disconnectionList );
+    }
+  }
+
+  // This stage is atomic; avoid emitting callbacks until all Actors are disconnected
+  disconnectionList.push_back( ActorPtr( this ) );
+
+  // Notification for internal derived classes
+  OnStageDisconnectionInternal();
+
+  DisconnectFromSceneGraph();
+
+  mIsOnStage = false;
+}
+
+/**
+ * This method is called by an actor or its parent, before a node removal message is sent.
+ * This is recursive; the child calls DisconnectFromStage() for its children.
+ */
+void Actor::DisconnectFromSceneGraph()
+{
+  // Notification for Object::Observers
+  OnSceneObjectRemove();
+
+  // Notify attachment
+  if( mAttachment )
+  {
+    mAttachment->Disconnect();
+  }
+}
+
+void Actor::NotifyStageDisconnection()
+{
+  // Actors can be added (in a callback), before the off-stage state is reported.
+  // Also if the actor was added & removed before mOnStageSignalled was set, then we don't notify here.
+  // only do this step if there is a stage, i.e. Core is not being shut down
+  if ( EventThreadServices::IsCoreRunning() && !OnStage() && mOnStageSignalled )
+  {
+    // Notification for external (CustomeActor) derived classes
+    OnStageDisconnectionExternal();
+
+    if( !mOffStageSignal.Empty() )
+    {
+      Dali::Actor handle( this );
+      mOffStageSignal.Emit( handle );
+    }
+
+    // Guard against Add during callbacks
+    if( !OnStage() )
+    {
+      mOnStageSignalled = false; // signal required next time Actor is added
+    }
+  }
+}
+
+bool Actor::IsNodeConnected() const
+{
+  bool connected( false );
+
+  if( OnStage() && ( NULL != mNode ) )
+  {
+    if( IsRoot() || mNode->GetParent() )
+    {
+      connected = true;
+    }
+  }
+
+  return connected;
+}
+
+unsigned int Actor::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void Actor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* Actor::GetDefaultPropertyName( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].name;
+  }
+
+  return NULL;
+}
+
+Property::Index Actor::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == name.compare( property->name ) )
+    {
+      index = i;
+      break;
+    }
+  }
+
+  return index;
+}
+
+bool Actor::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].writable;
+  }
+
+  return false;
+}
+
+bool Actor::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
+  }
+
+  return false;
+}
+
+bool Actor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
+  }
+
+  return false;
+}
+
+Property::Type Actor::GetDefaultPropertyType( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].type;
+  }
+
+  // index out of range...return Property::NONE
+  return Property::NONE;
+}
+
+void Actor::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  switch( index )
+  {
+    case Dali::Actor::Property::PARENT_ORIGIN:
+    {
+      SetParentOrigin( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_X:
+    {
+      SetParentOriginX( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_Y:
+    {
+      SetParentOriginY( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_Z:
+    {
+      SetParentOriginZ( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT:
+    {
+      SetAnchorPoint( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_X:
+    {
+      SetAnchorPointX( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_Y:
+    {
+      SetAnchorPointY( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_Z:
+    {
+      SetAnchorPointZ( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE:
+    {
+      SetSize( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_WIDTH:
+    {
+      SetWidth( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_HEIGHT:
+    {
+      SetHeight( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_DEPTH:
+    {
+      SetDepth( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION:
+    {
+      SetPosition( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_X:
+    {
+      SetX( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_Y:
+    {
+      SetY( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_Z:
+    {
+      SetZ( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::ORIENTATION:
+    {
+      SetOrientation( property.Get< Quaternion >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE:
+    {
+      SetScale( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_X:
+    {
+      SetScaleX( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_Y:
+    {
+      SetScaleY( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_Z:
+    {
+      SetScaleZ( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::VISIBLE:
+    {
+      SetVisible( property.Get< bool >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR:
+    {
+      SetColor( property.Get< Vector4 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_RED:
+    {
+      SetColorRed( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_GREEN:
+    {
+      SetColorGreen( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_BLUE:
+    {
+      SetColorBlue( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_ALPHA:
+    {
+      SetOpacity( property.Get< float >() );
+      break;
+    }
+
+    case Dali::Actor::Property::NAME:
+    {
+      SetName( property.Get< std::string >() );
+      break;
+    }
+
+    case Dali::Actor::Property::SENSITIVE:
+    {
+      SetSensitive( property.Get< bool >() );
+      break;
+    }
+
+    case Dali::Actor::Property::LEAVE_REQUIRED:
+    {
+      SetLeaveRequired( property.Get< bool >() );
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_ORIENTATION:
+    {
+      SetInheritOrientation( property.Get< bool >() );
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_SCALE:
+    {
+      SetInheritScale( property.Get< bool >() );
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_MODE:
+    {
+      SetColorMode( Scripting::GetColorMode( property.Get< std::string >() ) );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_INHERITANCE:
+    {
+      SetPositionInheritanceMode( Scripting::GetPositionInheritanceMode( property.Get< std::string >() ) );
+      break;
+    }
+
+    case Dali::Actor::Property::DRAW_MODE:
+    {
+      SetDrawMode( Scripting::GetDrawMode( property.Get< std::string >() ) );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_MODE_FACTOR:
+    {
+      SetSizeModeFactor( property.Get< Vector3 >() );
+      break;
+    }
+
+    case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
+    {
+      ResizePolicy::Type type;
+      if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
+      {
+        SetResizePolicy( type, Dimension::WIDTH );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
+    {
+      ResizePolicy::Type type;
+      if( Scripting::GetEnumeration< ResizePolicy::Type >( property.Get< std::string >().c_str(), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount, type ) )
+      {
+        SetResizePolicy( type, Dimension::HEIGHT );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_SCALE_POLICY:
+    {
+      SizeScalePolicy::Type type;
+      if( Scripting::GetEnumeration< SizeScalePolicy::Type >( property.Get< std::string >().c_str(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount, type ) )
+      {
+        SetSizeScalePolicy( type );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
+    {
+      if( property.Get< bool >() )
+      {
+        SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::WIDTH );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
+    {
+      if( property.Get< bool >() )
+      {
+        SetResizePolicy( ResizePolicy::DIMENSION_DEPENDENCY, Dimension::HEIGHT );
+      }
+      break;
+    }
+
+    case Dali::Actor::Property::PADDING:
+    {
+      Vector4 padding = property.Get< Vector4 >();
+      SetPadding( Vector2( padding.x, padding.y ), Dimension::WIDTH );
+      SetPadding( Vector2( padding.z, padding.w ), Dimension::HEIGHT );
+      break;
+    }
+
+    case Dali::Actor::Property::MINIMUM_SIZE:
+    {
+      Vector2 size = property.Get< Vector2 >();
+      SetMinimumSize( size.x, Dimension::WIDTH );
+      SetMinimumSize( size.y, Dimension::HEIGHT );
+      break;
+    }
+
+    case Dali::Actor::Property::MAXIMUM_SIZE:
+    {
+      Vector2 size = property.Get< Vector2 >();
+      SetMaximumSize( size.x, Dimension::WIDTH );
+      SetMaximumSize( size.y, Dimension::HEIGHT );
+      break;
+    }
+
+    default:
+    {
+      // this can happen in the case of a non-animatable default property so just do nothing
+      break;
+    }
+  }
+}
+
+// TODO: This method needs to be removed
+void Actor::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
+{
+  switch( entry.type )
+  {
+    case Property::BOOLEAN:
+    {
+      const AnimatableProperty< bool >* property = dynamic_cast< const AnimatableProperty< bool >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<bool>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<bool>::Bake, value.Get<bool>() );
+
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      const AnimatableProperty< int >* property = dynamic_cast< const AnimatableProperty< int >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<int>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<int>::Bake, value.Get<int>() );
+
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      const AnimatableProperty< float >* property = dynamic_cast< const AnimatableProperty< float >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<float>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<float>::Bake, value.Get<float>() );
+
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      const AnimatableProperty< Vector2 >* property = dynamic_cast< const AnimatableProperty< Vector2 >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeX, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::BakeY, value.Get<float>() );
+      }
+      else
+      {
+        SceneGraph::NodePropertyMessage<Vector2>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
+      }
+
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      const AnimatableProperty< Vector3 >* property = dynamic_cast< const AnimatableProperty< Vector3 >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeX, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeY, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 2)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::BakeZ, value.Get<float>() );
+      }
+      else
+      {
+        SceneGraph::NodePropertyMessage<Vector3>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
+      }
+
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      const AnimatableProperty< Vector4 >* property = dynamic_cast< const AnimatableProperty< Vector4 >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeX, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeY, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 2)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeZ, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 3)
+      {
+        SceneGraph::NodePropertyComponentMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::BakeW, value.Get<float>() );
+      }
+      else
+      {
+        SceneGraph::NodePropertyMessage<Vector4>::Send( GetEventThreadServices(), mNode, property, &AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
+      }
+
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      const AnimatableProperty< Quaternion >* property = dynamic_cast< const AnimatableProperty< Quaternion >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<Quaternion>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
+
+      break;
+    }
+
+    case Property::MATRIX:
+    {
+      const AnimatableProperty< Matrix >* property = dynamic_cast< const AnimatableProperty< Matrix >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<Matrix>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
+
+      break;
+    }
+
+    case Property::MATRIX3:
+    {
+      const AnimatableProperty< Matrix3 >* property = dynamic_cast< const AnimatableProperty< Matrix3 >* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      SceneGraph::NodePropertyMessage<Matrix3>::Send( GetEventThreadServices(), mNode, property,&AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
+
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
+      break;
+    }
+  }
+}
+
+Property::Value Actor::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+
+  switch( index )
+  {
+    case Dali::Actor::Property::PARENT_ORIGIN:
+    {
+      value = GetCurrentParentOrigin();
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_X:
+    {
+      value = GetCurrentParentOrigin().x;
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_Y:
+    {
+      value = GetCurrentParentOrigin().y;
+      break;
+    }
+
+    case Dali::Actor::Property::PARENT_ORIGIN_Z:
+    {
+      value = GetCurrentParentOrigin().z;
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT:
+    {
+      value = GetCurrentAnchorPoint();
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_X:
+    {
+      value = GetCurrentAnchorPoint().x;
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_Y:
+    {
+      value = GetCurrentAnchorPoint().y;
+      break;
+    }
+
+    case Dali::Actor::Property::ANCHOR_POINT_Z:
+    {
+      value = GetCurrentAnchorPoint().z;
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE:
+    {
+      value = GetCurrentSize();
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_WIDTH:
+    {
+      value = GetCurrentSize().width;
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_HEIGHT:
+    {
+      value = GetCurrentSize().height;
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_DEPTH:
+    {
+      value = GetCurrentSize().depth;
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION:
+    {
+      value = GetCurrentPosition();
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_X:
+    {
+      value = GetCurrentPosition().x;
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_Y:
+    {
+      value = GetCurrentPosition().y;
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_Z:
+    {
+      value = GetCurrentPosition().z;
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_POSITION:
+    {
+      value = GetCurrentWorldPosition();
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_POSITION_X:
+    {
+      value = GetCurrentWorldPosition().x;
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_POSITION_Y:
+    {
+      value = GetCurrentWorldPosition().y;
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_POSITION_Z:
+    {
+      value = GetCurrentWorldPosition().z;
+      break;
+    }
+
+    case Dali::Actor::Property::ORIENTATION:
+    {
+      value = GetCurrentOrientation();
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_ORIENTATION:
+    {
+      value = GetCurrentWorldOrientation();
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE:
+    {
+      value = GetCurrentScale();
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_X:
+    {
+      value = GetCurrentScale().x;
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_Y:
+    {
+      value = GetCurrentScale().y;
+      break;
+    }
+
+    case Dali::Actor::Property::SCALE_Z:
+    {
+      value = GetCurrentScale().z;
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_SCALE:
+    {
+      value = GetCurrentWorldScale();
+      break;
+    }
+
+    case Dali::Actor::Property::VISIBLE:
+    {
+      value = IsVisible();
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR:
+    {
+      value = GetCurrentColor();
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_RED:
+    {
+      value = GetCurrentColor().r;
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_GREEN:
+    {
+      value = GetCurrentColor().g;
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_BLUE:
+    {
+      value = GetCurrentColor().b;
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_ALPHA:
+    {
+      value = GetCurrentColor().a;
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_COLOR:
+    {
+      value = GetCurrentWorldColor();
+      break;
+    }
+
+    case Dali::Actor::Property::WORLD_MATRIX:
+    {
+      value = GetCurrentWorldMatrix();
+      break;
+    }
+
+    case Dali::Actor::Property::NAME:
+    {
+      value = GetName();
+      break;
+    }
+
+    case Dali::Actor::Property::SENSITIVE:
+    {
+      value = IsSensitive();
+      break;
+    }
+
+    case Dali::Actor::Property::LEAVE_REQUIRED:
+    {
+      value = GetLeaveRequired();
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_ORIENTATION:
+    {
+      value = IsOrientationInherited();
+      break;
+    }
+
+    case Dali::Actor::Property::INHERIT_SCALE:
+    {
+      value = IsScaleInherited();
+      break;
+    }
+
+    case Dali::Actor::Property::COLOR_MODE:
+    {
+      value = Scripting::GetColorMode( GetColorMode() );
+      break;
+    }
+
+    case Dali::Actor::Property::POSITION_INHERITANCE:
+    {
+      value = Scripting::GetPositionInheritanceMode( GetPositionInheritanceMode() );
+      break;
+    }
+
+    case Dali::Actor::Property::DRAW_MODE:
+    {
+      value = Scripting::GetDrawMode( GetDrawMode() );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_MODE_FACTOR:
+    {
+      value = GetSizeModeFactor();
+      break;
+    }
+
+    case Dali::Actor::Property::WIDTH_RESIZE_POLICY:
+    {
+      value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::WIDTH ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
+      break;
+    }
+
+    case Dali::Actor::Property::HEIGHT_RESIZE_POLICY:
+    {
+      value = Scripting::GetLinearEnumerationName< ResizePolicy::Type >( GetResizePolicy( Dimension::HEIGHT ), ResizePolicy::TypeTable, ResizePolicy::TypeTableCount );
+      break;
+    }
+
+    case Dali::Actor::Property::SIZE_SCALE_POLICY:
+    {
+      value = Scripting::GetLinearEnumerationName< SizeScalePolicy::Type >( GetSizeScalePolicy(), SizeScalePolicy::TypeTable, SizeScalePolicy::TypeTableCount );
+      break;
+    }
+
+    case Dali::Actor::Property::WIDTH_FOR_HEIGHT:
+    {
+      value = ( GetResizePolicy( Dimension::WIDTH ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::WIDTH ) == Dimension::HEIGHT );
+      break;
+    }
+
+    case Dali::Actor::Property::HEIGHT_FOR_WIDTH:
+    {
+      value = ( GetResizePolicy( Dimension::HEIGHT ) == ResizePolicy::DIMENSION_DEPENDENCY ) && ( GetDimensionDependency( Dimension::HEIGHT ) == Dimension::WIDTH );
+      break;
+    }
+
+    case Dali::Actor::Property::PADDING:
+    {
+      Vector2 widthPadding = GetPadding( Dimension::WIDTH );
+      Vector2 heightPadding = GetPadding( Dimension::HEIGHT );
+      value = Vector4( widthPadding.x, widthPadding.y, heightPadding.x, heightPadding.y );
+      break;
+    }
+
+    case Dali::Actor::Property::MINIMUM_SIZE:
+    {
+      value = Vector2( GetMinimumSize( Dimension::WIDTH ), GetMinimumSize( Dimension::HEIGHT ) );
+      break;
+    }
+
+    case Dali::Actor::Property::MAXIMUM_SIZE:
+    {
+      value = Vector2( GetMaximumSize( Dimension::WIDTH ), GetMaximumSize( Dimension::HEIGHT ) );
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS( false && "Actor Property index invalid" ); // should not come here
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Actor::GetPropertyOwner() const
+{
+  return mNode;
+}
+
+const SceneGraph::PropertyOwner* Actor::GetSceneObject() const
+{
+  // This method should only return an object connected to the scene-graph
+  return OnStage() ? mNode : NULL;
+}
+
+const PropertyBase* Actor::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
+
+  const PropertyBase* property( NULL );
+
+  // This method should only return a property of an object connected to the scene-graph
+  if( !OnStage() )
+  {
+    return property;
+  }
+
+  if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
+  {
+    AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
+    DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+
+    property = animatable->GetSceneGraphProperty();
+  }
+  else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+
+    property = custom->GetSceneGraphProperty();
+  }
+  else if( NULL != mNode )
+  {
+    switch( index )
+    {
+      case Dali::Actor::Property::SIZE:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_WIDTH:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_HEIGHT:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_DEPTH:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::POSITION:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_X:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_Y:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_Z:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::ORIENTATION:
+        property = &mNode->mOrientation;
+        break;
+
+      case Dali::Actor::Property::SCALE:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_X:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_Y:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_Z:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::VISIBLE:
+        property = &mNode->mVisible;
+        break;
+
+      case Dali::Actor::Property::COLOR:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_RED:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_GREEN:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_BLUE:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_ALPHA:
+        property = &mNode->mColor;
+        break;
+
+      default:
+        break;
+    }
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* Actor::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property( NULL );
+
+  // This method should only return a property of an object connected to the scene-graph
+  if( !OnStage() )
+  {
+    return property;
+  }
+
+  if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
+  {
+    AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
+    DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+
+    property = animatable->GetSceneGraphProperty();
+  }
+  else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+    property = custom->GetSceneGraphProperty();
+  }
+  else if( NULL != mNode )
+  {
+    switch( index )
+    {
+      case Dali::Actor::Property::PARENT_ORIGIN:
+        property = &mNode->mParentOrigin;
+        break;
+
+      case Dali::Actor::Property::PARENT_ORIGIN_X:
+        property = &mNode->mParentOrigin;
+        break;
+
+      case Dali::Actor::Property::PARENT_ORIGIN_Y:
+        property = &mNode->mParentOrigin;
+        break;
+
+      case Dali::Actor::Property::PARENT_ORIGIN_Z:
+        property = &mNode->mParentOrigin;
+        break;
+
+      case Dali::Actor::Property::ANCHOR_POINT:
+        property = &mNode->mAnchorPoint;
+        break;
+
+      case Dali::Actor::Property::ANCHOR_POINT_X:
+        property = &mNode->mAnchorPoint;
+        break;
+
+      case Dali::Actor::Property::ANCHOR_POINT_Y:
+        property = &mNode->mAnchorPoint;
+        break;
+
+      case Dali::Actor::Property::ANCHOR_POINT_Z:
+        property = &mNode->mAnchorPoint;
+        break;
+
+      case Dali::Actor::Property::SIZE:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_WIDTH:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_HEIGHT:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::SIZE_DEPTH:
+        property = &mNode->mSize;
+        break;
+
+      case Dali::Actor::Property::POSITION:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_X:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_Y:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::POSITION_Z:
+        property = &mNode->mPosition;
+        break;
+
+      case Dali::Actor::Property::WORLD_POSITION:
+        property = &mNode->mWorldPosition;
+        break;
+
+      case Dali::Actor::Property::WORLD_POSITION_X:
+        property = &mNode->mWorldPosition;
+        break;
+
+      case Dali::Actor::Property::WORLD_POSITION_Y:
+        property = &mNode->mWorldPosition;
+        break;
+
+      case Dali::Actor::Property::WORLD_POSITION_Z:
+        property = &mNode->mWorldPosition;
+        break;
+
+      case Dali::Actor::Property::ORIENTATION:
+        property = &mNode->mOrientation;
+        break;
+
+      case Dali::Actor::Property::WORLD_ORIENTATION:
+        property = &mNode->mWorldOrientation;
+        break;
+
+      case Dali::Actor::Property::SCALE:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_X:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_Y:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::SCALE_Z:
+        property = &mNode->mScale;
+        break;
+
+      case Dali::Actor::Property::WORLD_SCALE:
+        property = &mNode->mWorldScale;
+        break;
+
+      case Dali::Actor::Property::VISIBLE:
+        property = &mNode->mVisible;
+        break;
+
+      case Dali::Actor::Property::COLOR:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_RED:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_GREEN:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_BLUE:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::COLOR_ALPHA:
+        property = &mNode->mColor;
+        break;
+
+      case Dali::Actor::Property::WORLD_COLOR:
+        property = &mNode->mWorldColor;
+        break;
+
+      case Dali::Actor::Property::WORLD_MATRIX:
+        property = &mNode->mWorldMatrix;
+        break;
+
+      default:
+        break;
+    }
+  }
+
+  return property;
+}
+
+int Actor::GetPropertyComponentIndex( Property::Index index ) const
+{
+  int componentIndex( Property::INVALID_COMPONENT_INDEX );
+
+  if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // check whether the animatable property is registered already, if not then register one.
+    AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty(index);
+    if( animatableProperty )
+    {
+      componentIndex = animatableProperty->componentIndex;
+    }
+  }
+  else
+  {
+    switch( index )
+    {
+      case Dali::Actor::Property::PARENT_ORIGIN_X:
+      case Dali::Actor::Property::ANCHOR_POINT_X:
+      case Dali::Actor::Property::SIZE_WIDTH:
+      case Dali::Actor::Property::POSITION_X:
+      case Dali::Actor::Property::WORLD_POSITION_X:
+      case Dali::Actor::Property::SCALE_X:
+      case Dali::Actor::Property::COLOR_RED:
+      {
+        componentIndex = 0;
+        break;
+      }
+
+      case Dali::Actor::Property::PARENT_ORIGIN_Y:
+      case Dali::Actor::Property::ANCHOR_POINT_Y:
+      case Dali::Actor::Property::SIZE_HEIGHT:
+      case Dali::Actor::Property::POSITION_Y:
+      case Dali::Actor::Property::WORLD_POSITION_Y:
+      case Dali::Actor::Property::SCALE_Y:
+      case Dali::Actor::Property::COLOR_GREEN:
+      {
+        componentIndex = 1;
+        break;
+      }
+
+      case Dali::Actor::Property::PARENT_ORIGIN_Z:
+      case Dali::Actor::Property::ANCHOR_POINT_Z:
+      case Dali::Actor::Property::SIZE_DEPTH:
+      case Dali::Actor::Property::POSITION_Z:
+      case Dali::Actor::Property::WORLD_POSITION_Z:
+      case Dali::Actor::Property::SCALE_Z:
+      case Dali::Actor::Property::COLOR_BLUE:
+      {
+        componentIndex = 2;
+        break;
+      }
+
+      case Dali::Actor::Property::COLOR_ALPHA:
+      {
+        componentIndex = 3;
+        break;
+      }
+
+      default:
+      {
+        // Do nothing
+        break;
+      }
+    }
+  }
+
+  return componentIndex;
+}
+
+void Actor::SetParent( Actor* parent, int index )
+{
+  if( parent )
+  {
+    DALI_ASSERT_ALWAYS( !mParent && "Actor cannot have 2 parents" );
+
+    mParent = parent;
+
+    if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
+         parent->OnStage() )
+    {
+      // Instruct each actor to create a corresponding node in the scene graph
+      ConnectToStage( parent->GetHierarchyDepth(), index );
+    }
+  }
+  else // parent being set to NULL
+  {
+    DALI_ASSERT_ALWAYS( mParent != NULL && "Actor should have a parent" );
+
+    mParent = NULL;
+
+    if ( EventThreadServices::IsCoreRunning() && // Don't emit signals or send messages during Core destruction
+         OnStage() )
+    {
+      DALI_ASSERT_ALWAYS( mNode != NULL );
+
+      if( NULL != mNode )
+      {
+        // Disconnect the Node & its children from the scene-graph.
+        DisconnectNodeMessage( GetEventThreadServices().GetUpdateManager(), *mNode );
+      }
+
+      // Instruct each actor to discard pointers to the scene-graph
+      DisconnectFromStage();
+    }
+  }
+}
+
+SceneGraph::Node* Actor::CreateNode() const
+{
+  return Node::New();
+}
+
+bool Actor::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /* attributes */ )
+{
+  bool done = false;
+  Actor* actor = dynamic_cast< Actor* >( object );
+
+  if( actor )
+  {
+    if( 0 == actionName.compare( ACTION_SHOW ) )
+    {
+      actor->SetVisible( true );
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_HIDE ) )
+    {
+      actor->SetVisible( false );
+      done = true;
+    }
+  }
+
+  return done;
+}
+
+void Actor::EnsureRelayoutData()
+{
+  // Assign relayout data.
+  if( !mRelayoutData )
+  {
+    mRelayoutData = new RelayoutData();
+  }
+}
+
+bool Actor::RelayoutDependentOnParent( Dimension::Type dimension )
+{
+  // Check if actor is dependent on parent
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( ( dimension & ( 1 << i ) ) )
+    {
+      const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
+      if( resizePolicy == ResizePolicy::FILL_TO_PARENT || resizePolicy == ResizePolicy::SIZE_RELATIVE_TO_PARENT || resizePolicy == ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT )
+      {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+bool Actor::RelayoutDependentOnChildren( Dimension::Type dimension )
+{
+  // Check if actor is dependent on children
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( ( dimension & ( 1 << i ) ) )
+    {
+      const ResizePolicy::Type resizePolicy = GetResizePolicy( static_cast< Dimension::Type >( 1 << i ) );
+      switch( resizePolicy )
+      {
+        case ResizePolicy::FIT_TO_CHILDREN:
+        case ResizePolicy::USE_NATURAL_SIZE:      // i.e. For things that calculate their size based on children
+        {
+          return true;
+        }
+
+        default:
+        {
+          break;
+        }
+      }
+    }
+  }
+
+  return false;
+}
+
+bool Actor::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
+{
+  return Actor::RelayoutDependentOnChildren( dimension );
+}
+
+bool Actor::RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension )
+{
+  // Check each possible dimension and see if it is dependent on the input one
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      return mRelayoutData->resizePolicies[ i ] == ResizePolicy::DIMENSION_DEPENDENCY && mRelayoutData->dimensionDependencies[ i ] == dependentDimension;
+    }
+  }
+
+  return false;
+}
+
+void Actor::SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension )
+{
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->negotiatedDimensions[ i ] = negotiatedDimension;
+    }
+  }
+}
+
+float Actor::GetNegotiatedDimension( Dimension::Type dimension ) const
+{
+  // If more than one dimension is requested, just return the first one found
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( ( dimension & ( 1 << i ) ) )
+    {
+      return mRelayoutData->negotiatedDimensions[ i ];
+    }
+  }
+
+  return 0.0f;   // Default
+}
+
+void Actor::SetPadding( const Vector2& padding, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->dimensionPadding[ i ] = padding;
+    }
+  }
+}
+
+Vector2 Actor::GetPadding( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    // If more than one dimension is requested, just return the first one found
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( ( dimension & ( 1 << i ) ) )
+      {
+        return mRelayoutData->dimensionPadding[ i ];
+      }
+    }
+  }
+
+  return GetDefaultDimensionPadding();
+}
+
+void Actor::SetLayoutNegotiated( bool negotiated, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->dimensionNegotiated[ i ] = negotiated;
+    }
+  }
+}
+
+bool Actor::IsLayoutNegotiated( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( ( dimension & ( 1 << i ) ) && mRelayoutData->dimensionNegotiated[ i ] )
+      {
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
+float Actor::GetHeightForWidthBase( float width )
+{
+  float height = 0.0f;
+
+  const Vector3 naturalSize = GetNaturalSize();
+  if( naturalSize.width > 0.0f )
+  {
+    height = naturalSize.height * width / naturalSize.width;
+  }
+  else // we treat 0 as 1:1 aspect ratio
+  {
+    height = width;
+  }
+
+  return height;
+}
+
+float Actor::GetWidthForHeightBase( float height )
+{
+  float width = 0.0f;
+
+  const Vector3 naturalSize = GetNaturalSize();
+  if( naturalSize.height > 0.0f )
+  {
+    width = naturalSize.width * height / naturalSize.height;
+  }
+  else // we treat 0 as 1:1 aspect ratio
+  {
+    width = height;
+  }
+
+  return width;
+}
+
+float Actor::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
+{
+  // Fill to parent, taking size mode factor into account
+  switch( child.GetResizePolicy( dimension ) )
+  {
+    case ResizePolicy::FILL_TO_PARENT:
+    {
+      return GetLatestSize( dimension );
+    }
+
+    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
+    {
+      return GetLatestSize( dimension ) * GetDimensionValue( child.GetSizeModeFactor(), dimension );
+    }
+
+    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
+    {
+      return GetLatestSize( dimension ) + GetDimensionValue( child.GetSizeModeFactor(), dimension );
+    }
+
+    default:
+    {
+      return GetLatestSize( dimension );
+    }
+  }
+}
+
+float Actor::CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+{
+  // Can be overridden in derived class
+  return CalculateChildSizeBase( child, dimension );
+}
+
+float Actor::GetHeightForWidth( float width )
+{
+  // Can be overridden in derived class
+  return GetHeightForWidthBase( width );
+}
+
+float Actor::GetWidthForHeight( float height )
+{
+  // Can be overridden in derived class
+  return GetWidthForHeightBase( height );
+}
+
+float Actor::GetLatestSize( Dimension::Type dimension ) const
+{
+  return IsLayoutNegotiated( dimension ) ? GetNegotiatedDimension( dimension ) : GetSize( dimension );
+}
+
+float Actor::GetRelayoutSize( Dimension::Type dimension ) const
+{
+  Vector2 padding = GetPadding( dimension );
+
+  return GetLatestSize( dimension ) + padding.x + padding.y;
+}
+
+float Actor::NegotiateFromParent( Dimension::Type dimension )
+{
+  Actor* parent = GetParent();
+  if( parent )
+  {
+    Vector2 padding( GetPadding( dimension ) );
+    Vector2 parentPadding( parent->GetPadding( dimension ) );
+    return parent->CalculateChildSize( Dali::Actor( this ), dimension ) - parentPadding.x - parentPadding.y - padding.x - padding.y;
+  }
+
+  return 0.0f;
+}
+
+float Actor::NegotiateFromChildren( Dimension::Type dimension )
+{
+  float maxDimensionPoint = 0.0f;
+
+  for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
+  {
+    ActorPtr child = GetChildAt( i );
+
+    if( !child->RelayoutDependentOnParent( dimension ) )
+    {
+      // Calculate the min and max points that the children range across
+      float childPosition = GetDimensionValue( child->GetTargetPosition(), dimension );
+      float dimensionSize = child->GetRelayoutSize( dimension );
+      maxDimensionPoint = std::max( maxDimensionPoint, childPosition + dimensionSize );
+    }
+  }
+
+  return maxDimensionPoint;
+}
+
+float Actor::GetSize( Dimension::Type dimension ) const
+{
+  return GetDimensionValue( GetTargetSize(), dimension );
+}
+
+float Actor::GetNaturalSize( Dimension::Type dimension ) const
+{
+  return GetDimensionValue( GetNaturalSize(), dimension );
+}
+
+float Actor::CalculateSize( Dimension::Type dimension, const Vector2& maximumSize )
+{
+  switch( GetResizePolicy( dimension ) )
+  {
+    case ResizePolicy::USE_NATURAL_SIZE:
+    {
+      return GetNaturalSize( dimension );
+    }
+
+    case ResizePolicy::FIXED:
+    {
+      return GetDimensionValue( GetPreferredSize(), dimension );
+    }
+
+    case ResizePolicy::USE_ASSIGNED_SIZE:
+    {
+      return GetDimensionValue( maximumSize, dimension );
+    }
+
+    case ResizePolicy::FILL_TO_PARENT:
+    case ResizePolicy::SIZE_RELATIVE_TO_PARENT:
+    case ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT:
+    {
+      return NegotiateFromParent( dimension );
+    }
+
+    case ResizePolicy::FIT_TO_CHILDREN:
+    {
+      return NegotiateFromChildren( dimension );
+    }
+
+    case ResizePolicy::DIMENSION_DEPENDENCY:
+    {
+      const Dimension::Type dimensionDependency = GetDimensionDependency( dimension );
+
+      // Custom rules
+      if( dimension == Dimension::WIDTH && dimensionDependency == Dimension::HEIGHT )
+      {
+        return GetWidthForHeight( GetNegotiatedDimension( Dimension::HEIGHT ) );
+      }
+
+      if( dimension == Dimension::HEIGHT && dimensionDependency == Dimension::WIDTH )
+      {
+        return GetHeightForWidth( GetNegotiatedDimension( Dimension::WIDTH ) );
+      }
+
+      break;
+    }
+
+    default:
+    {
+      break;
+    }
+  }
+
+  return 0.0f;  // Default
+}
+
+float Actor::ClampDimension( float size, Dimension::Type dimension )
+{
+  const float minSize = GetMinimumSize( dimension );
+  const float maxSize = GetMaximumSize( dimension );
+
+  return std::max( minSize, std::min( size, maxSize ) );
+}
+
+void Actor::NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack )
+{
+  // Check if it needs to be negotiated
+  if( IsLayoutDirty( dimension ) && !IsLayoutNegotiated( dimension ) )
+  {
+    // Check that we havn't gotten into an infinite loop
+    ActorDimensionPair searchActor = ActorDimensionPair( this, dimension );
+    bool recursionFound = false;
+    for( ActorDimensionStack::iterator it = recursionStack.begin(), itEnd = recursionStack.end(); it != itEnd; ++it )
+    {
+      if( *it == searchActor )
+      {
+        recursionFound = true;
+        break;
+      }
+    }
+
+    if( !recursionFound )
+    {
+      // Record the path that we have taken
+      recursionStack.push_back( ActorDimensionPair( this, dimension ) );
+
+      // Dimension dependency check
+      for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+      {
+        Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
+
+        if( RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
+        {
+          NegotiateDimension( dimensionToCheck, allocatedSize, recursionStack );
+        }
+      }
+
+      // Parent dependency check
+      Actor* parent = GetParent();
+      if( parent && RelayoutDependentOnParent( dimension ) )
+      {
+        parent->NegotiateDimension( dimension, allocatedSize, recursionStack );
+      }
+
+      // Children dependency check
+      if( RelayoutDependentOnChildren( dimension ) )
+      {
+        for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
+        {
+          ActorPtr child = GetChildAt( i );
+
+          // Only relayout child first if it is not dependent on this actor
+          if( !child->RelayoutDependentOnParent( dimension ) )
+          {
+            child->NegotiateDimension( dimension, allocatedSize, recursionStack );
+          }
+        }
+      }
+
+      // For deriving classes
+      OnCalculateRelayoutSize( dimension );
+
+      // All dependencies checked, calculate the size and set negotiated flag
+      const float newSize = ClampDimension( CalculateSize( dimension, allocatedSize ), dimension );
+
+      SetNegotiatedDimension( newSize, dimension );
+      SetLayoutNegotiated( true, dimension );
+
+      // For deriving classes
+      OnLayoutNegotiated( newSize, dimension );
+
+      // This actor has been successfully processed, pop it off the recursion stack
+      recursionStack.pop_back();
+    }
+    else
+    {
+      // TODO: Break infinite loop
+      SetLayoutNegotiated( true, dimension );
+    }
+  }
+}
+
+void Actor::NegotiateDimensions( const Vector2& allocatedSize )
+{
+  // Negotiate all dimensions that require it
+  ActorDimensionStack recursionStack;
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    const Dimension::Type dimension = static_cast< Dimension::Type >( 1 << i );
+
+    // Negotiate
+    NegotiateDimension( dimension, allocatedSize, recursionStack );
+  }
+}
+
+Vector2 Actor::ApplySizeSetPolicy( const Vector2 size )
+{
+  switch( mRelayoutData->sizeSetPolicy )
+  {
+    case SizeScalePolicy::USE_SIZE_SET:
+    {
+      return size;
+    }
+
+    case SizeScalePolicy::FIT_WITH_ASPECT_RATIO:
+    {
+      // Scale size to fit within the original size bounds, keeping the natural size aspect ratio
+      const Vector3 naturalSize = GetNaturalSize();
+      if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
+      {
+        const float sizeRatio = size.width / size.height;
+        const float naturalSizeRatio = naturalSize.width / naturalSize.height;
+
+        if( naturalSizeRatio < sizeRatio )
+        {
+          return Vector2( naturalSizeRatio * size.height, size.height );
+        }
+        else if( naturalSizeRatio > sizeRatio )
+        {
+          return Vector2( size.width, size.width / naturalSizeRatio );
+        }
+        else
+        {
+          return size;
+        }
+      }
+
+      break;
+    }
+
+    case SizeScalePolicy::FILL_WITH_ASPECT_RATIO:
+    {
+      // Scale size to fill the original size bounds, keeping the natural size aspect ratio. Potentially exceeding the original bounds.
+      const Vector3 naturalSize = GetNaturalSize();
+      if( naturalSize.width > 0.0f && naturalSize.height > 0.0f && size.width > 0.0f && size.height > 0.0f )
+      {
+        const float sizeRatio = size.width / size.height;
+        const float naturalSizeRatio = naturalSize.width / naturalSize.height;
+
+        if( naturalSizeRatio < sizeRatio )
+        {
+          return Vector2( size.width, size.width / naturalSizeRatio );
+        }
+        else if( naturalSizeRatio > sizeRatio )
+        {
+          return Vector2( naturalSizeRatio * size.height, size.height );
+        }
+        else
+        {
+          return size;
+        }
+      }
+    }
+
+    default:
+    {
+      break;
+    }
+  }
+
+  return size;
+}
+
+void Actor::SetNegotiatedSize( RelayoutContainer& container )
+{
+  // Do the set actor size
+  Vector2 negotiatedSize( GetLatestSize( Dimension::WIDTH ), GetLatestSize( Dimension::HEIGHT ) );
+
+  // Adjust for size set policy
+  negotiatedSize = ApplySizeSetPolicy( negotiatedSize );
+
+  // Lock the flag to stop recursive relayouts on set size
+  mRelayoutData->insideRelayout = true;
+  SetSize( negotiatedSize );
+  mRelayoutData->insideRelayout = false;
+
+  // Clear flags for all dimensions
+  SetLayoutDirty( false );
+
+  // Give deriving classes a chance to respond
+  OnRelayout( negotiatedSize, container );
+
+  if( !mOnRelayoutSignal.Empty() )
+  {
+    Dali::Actor handle( this );
+    mOnRelayoutSignal.Emit( handle );
+  }
+}
+
+void Actor::NegotiateSize( const Vector2& allocatedSize, RelayoutContainer& container )
+{
+  // Do the negotiation
+  NegotiateDimensions( allocatedSize );
+
+  // Set the actor size
+  SetNegotiatedSize( container );
+
+  // Negotiate down to children
+  const Vector2 newBounds = GetTargetSize().GetVectorXY();
+
+  for( unsigned int i = 0, count = GetChildCount(); i < count; ++i )
+  {
+    ActorPtr child = GetChildAt( i );
+
+    // Only relayout if required
+    if( child->RelayoutRequired() )
+    {
+      container.Add( Dali::Actor( child.Get() ), newBounds );
+    }
+  }
+}
+
+void Actor::RelayoutRequest( Dimension::Type dimension )
+{
+  Internal::RelayoutController* relayoutController = Internal::RelayoutController::Get();
+  if( relayoutController )
+  {
+    Dali::Actor self( this );
+    relayoutController->RequestRelayout( self, dimension );
+  }
+}
+
+void Actor::OnCalculateRelayoutSize( Dimension::Type dimension )
+{
+}
+
+void Actor::OnLayoutNegotiated( float size, Dimension::Type dimension )
+{
+}
+
+void Actor::SetPreferredSize( const Vector2& size )
+{
+  EnsureRelayoutData();
+
+  if( size.width > 0.0f )
+  {
+    SetResizePolicy( ResizePolicy::FIXED, Dimension::WIDTH );
+  }
+
+  if( size.height > 0.0f )
+  {
+    SetResizePolicy( ResizePolicy::FIXED, Dimension::HEIGHT );
+  }
+
+  mRelayoutData->preferredSize = size;
+
+  RelayoutRequest();
+}
+
+Vector2 Actor::GetPreferredSize() const
+{
+  if ( mRelayoutData )
+  {
+    return mRelayoutData->preferredSize;
+  }
+
+  return GetDefaultPreferredSize();
+}
+
+void Actor::SetMinimumSize( float size, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->minimumSize[ i ] = size;
+    }
+  }
+
+  RelayoutRequest();
+}
+
+float Actor::GetMinimumSize( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( dimension & ( 1 << i ) )
+      {
+        return mRelayoutData->minimumSize[ i ];
+      }
+    }
+  }
+
+  return 0.0f;  // Default
+}
+
+void Actor::SetMaximumSize( float size, Dimension::Type dimension )
+{
+  EnsureRelayoutData();
+
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      mRelayoutData->maximumSize[ i ] = size;
+    }
+  }
+
+  RelayoutRequest();
+}
+
+float Actor::GetMaximumSize( Dimension::Type dimension ) const
+{
+  if ( mRelayoutData )
+  {
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      if( dimension & ( 1 << i ) )
+      {
+        return mRelayoutData->maximumSize[ i ];
+      }
+    }
+  }
+
+  return FLT_MAX;  // Default
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/actor-impl.h b/dali/internal/event/actors/actor-impl.h
new file mode 100644 (file)
index 0000000..9a5e971
--- /dev/null
@@ -0,0 +1,1856 @@
+#ifndef __DALI_INTERNAL_ACTOR_H__
+#define __DALI_INTERNAL_ACTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/viewport.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-declarations.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/common/stage-def.h>
+#include <dali/internal/event/rendering/renderer-impl.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+
+namespace Dali
+{
+
+struct KeyEvent;
+struct TouchEvent;
+struct HoverEvent;
+struct WheelEvent;
+
+namespace Internal
+{
+
+class Actor;
+class ActorGestureData;
+class Animation;
+class RenderTask;
+class Renderer;
+
+typedef std::vector< ActorPtr > ActorContainer;
+typedef ActorContainer::iterator ActorIter;
+typedef ActorContainer::const_iterator ActorConstIter;
+
+/**
+ * Actor is the primary object which Dali applications interact with.
+ * UI controls can be built by combining multiple actors.
+ * Multi-Touch events are received through signals emitted by the actor tree.
+ *
+ * An Actor is a proxy for a Node in the scene graph.
+ * When an Actor is added to the Stage, it creates a node and attaches it to the scene graph.
+ * The scene-graph can be updated in a separate thread, so the attachment is done using an asynchronous message.
+ * When a tree of Actors is detached from the Stage, a message is sent to destroy the associated nodes.
+ */
+class Actor : public Object
+{
+public:
+
+  /**
+   * @brief Struct to hold an actor and a dimension
+   */
+  struct ActorDimensionPair
+  {
+    /**
+     * @brief Constructor
+     *
+     * @param[in] newActor The actor to assign
+     * @param[in] newDimension The dimension to assign
+     */
+    ActorDimensionPair( Actor* newActor, Dimension::Type newDimension )
+    : actor( newActor ),
+      dimension( newDimension )
+    {
+    }
+
+    /**
+     * @brief Equality operator
+     *
+     * @param[in] lhs The left hand side argument
+     * @param[in] rhs The right hand side argument
+     */
+    bool operator== ( const ActorDimensionPair& rhs )
+    {
+      return ( actor == rhs.actor ) && ( dimension == rhs.dimension );
+    }
+
+    Actor* actor;           ///< The actor to hold
+    Dimension::Type dimension;    ///< The dimension to hold
+  };
+
+  typedef std::vector< ActorDimensionPair > ActorDimensionStack;
+
+public:
+
+  /**
+   * Create a new actor.
+   * @return A smart-pointer to the newly allocated Actor.
+   */
+  static ActorPtr New();
+
+  /**
+   * Retrieve the name of the actor.
+   * @return The name.
+   */
+  const std::string& GetName() const;
+
+  /**
+   * Set the name of the actor.
+   * @param[in] name The new name.
+   */
+  void SetName( const std::string& name );
+
+  /**
+   * @copydoc Dali::Actor::GetId
+   */
+  unsigned int GetId() const;
+
+  // Attachments
+
+  /**
+   * Attach an object to an actor.
+   * @pre The actor does not already have an attachment.
+   * @param[in] attachment The object to attach.
+   */
+  void Attach( ActorAttachment& attachment );
+
+  /**
+   * Retreive the object attached to an actor.
+   * @return The attachment.
+   */
+  ActorAttachmentPtr GetAttachment();
+
+  // Containment
+
+  /**
+   * Query whether an actor is the root actor, which is owned by the Stage.
+   * @return True if the actor is a root actor.
+   */
+  bool IsRoot() const
+  {
+    return mIsRoot;
+  }
+
+  /**
+   * Query whether the actor is connected to the Stage.
+   */
+  bool OnStage() const;
+
+  /**
+   * Query whether the actor is a RenderableActor derived type.
+   * @return True if the actor is renderable.
+   */
+  bool IsRenderable() const
+  {
+    // inlined as this is called a lot in hit testing
+    return mIsRenderable;
+  }
+
+  /**
+   * Query whether the actor is of class Dali::Layer
+   * @return True if the actor is a layer.
+   */
+  bool IsLayer() const
+  {
+    // inlined as this is called a lot in hit testing
+    return mIsLayer;
+  }
+
+  /**
+   * Gets the layer in which the actor is present
+   * @return The layer, which will be uninitialized if the actor is off-stage.
+   */
+  Dali::Layer GetLayer();
+
+  /**
+   * Adds a child Actor to this Actor.
+   * @pre The child actor is not the same as the parent actor.
+   * @pre The child actor does not already have a parent.
+   * @param [in] child The child.
+   * @post The child will be referenced by its parent.
+   */
+  void Add( Actor& child );
+
+  /**
+   * Removes a child Actor from this Actor.
+   * @param [in] child The child.
+   * @post The child will be unreferenced.
+   */
+  void Remove( Actor& child );
+
+  /**
+   * @copydoc Dali::Actor::Unparent
+   */
+  void Unparent();
+
+  /**
+   * Retrieve the number of children held by the actor.
+   * @return The number of children
+   */
+  unsigned int GetChildCount() const;
+
+  /**
+   * @copydoc Dali::Actor::GetChildAt
+   */
+  ActorPtr GetChildAt( unsigned int index ) const;
+
+  /**
+   * Retrieve a reference to Actor's children.
+   * @note Not for public use.
+   * @return A reference to the container of children.
+   */
+  ActorContainer& GetChildrenInternal()
+  {
+    return *mChildren;
+  }
+
+  /**
+   * @copydoc Dali::Actor::FindChildByName
+   */
+  ActorPtr FindChildByName( const std::string& actorName );
+
+  /**
+   * @copydoc Dali::Actor::FindChildById
+   */
+  ActorPtr FindChildById( const unsigned int id );
+
+  /**
+   * Retrieve the parent of an Actor.
+   * @return The parent actor, or NULL if the Actor does not have a parent.
+   */
+  Actor* GetParent() const
+  {
+    return mParent;
+  }
+
+  /**
+   * Sets the size of an actor.
+   * ActorAttachments attached to the actor, can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @param [in] width  The new width.
+   * @param [in] height The new height.
+   */
+  void SetSize( float width, float height );
+
+  /**
+   * Sets the size of an actor.
+   * ActorAttachments attached to the actor, can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @param [in] width The size of the actor along the x-axis.
+   * @param [in] height The size of the actor along the y-axis.
+   * @param [in] depth The size of the actor along the z-axis.
+   */
+  void SetSize( float width, float height, float depth );
+
+  /**
+   * Sets the size of an actor.
+   * ActorAttachments attached to the actor, can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @param [in] size The new size.
+   */
+  void SetSize( const Vector2& size );
+
+  /**
+   * Sets the update size for an actor.
+   *
+   * @param[in] size The size to set.
+   */
+  void SetSizeInternal( const Vector2& size );
+
+  /**
+   * Sets the size of an actor.
+   * ActorAttachments attached to the actor, can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @param [in] size The new size.
+   */
+  void SetSize( const Vector3& size );
+
+  /**
+   * Sets the update size for an actor.
+   *
+   * @param[in] size The size to set.
+   */
+  void SetSizeInternal( const Vector3& size );
+
+  /**
+   * Set the width component of the Actor's size.
+   * @param [in] width The new width component.
+   */
+  void SetWidth( float width );
+
+  /**
+   * Set the height component of the Actor's size.
+   * @param [in] height The new height component.
+   */
+  void SetHeight( float height );
+
+  /**
+   * Set the depth component of the Actor's size.
+   * @param [in] depth The new depth component.
+   */
+  void SetDepth( float depth );
+
+  /**
+   * Retrieve the Actor's size from event side.
+   * This size will be the size set or if animating then the target size.
+   * @return The Actor's size.
+   */
+  const Vector3& GetTargetSize() const;
+
+  /**
+   * Retrieve the Actor's size from update side.
+   * This size will be the size set or animating but will be a frame behind.
+   * @return The Actor's size.
+   */
+  const Vector3& GetCurrentSize() const;
+
+  /**
+   * Return the natural size of the actor
+   *
+   * @return The actor's natural size
+   */
+  virtual Vector3 GetNaturalSize() const;
+
+  /**
+   * Set the origin of an actor, within its parent's area.
+   * This is expressed in 2D unit coordinates, such that (0.0, 0.0, 0.5) is the top-left corner of the parent,
+   * and (1.0, 1.0, 0.5) is the bottom-right corner.
+   * The default parent-origin is top-left (0.0, 0.0, 0.5).
+   * An actor position is the distance between this origin, and the actors anchor-point.
+   * @param [in] origin The new parent-origin.
+   */
+  void SetParentOrigin( const Vector3& origin );
+
+  /**
+   * Set the x component of the parent-origin
+   * @param [in] x The new x value.
+   */
+  void SetParentOriginX( float x );
+
+  /**
+   * Set the y component of the parent-origin
+   * @param [in] y The new y value.
+   */
+  void SetParentOriginY( float y );
+
+  /**
+   * Set the z component of the parent-origin
+   * @param [in] z The new z value.
+   */
+  void SetParentOriginZ( float z );
+
+  /**
+   * Retrieve the parent-origin of an actor.
+   * @return The parent-origin.
+   */
+  const Vector3& GetCurrentParentOrigin() const;
+
+  /**
+   * Set the anchor-point of an actor. This is expressed in 2D unit coordinates, such that
+   * (0.0, 0.0, 0.5) is the top-left corner of the actor, and (1.0, 1.0, 0.5) is the bottom-right corner.
+   * The default anchor point is top-left (0.0, 0.0, 0.5).
+   * An actor position is the distance between its parent-origin, and this anchor-point.
+   * An actor's rotation is centered around its anchor-point.
+   * @param [in] anchorPoint The new anchor-point.
+   */
+  void SetAnchorPoint( const Vector3& anchorPoint );
+
+  /**
+   * Set the x component of the anchor-point.
+   * @param [in] x The new x value.
+   */
+  void SetAnchorPointX( float x );
+
+  /**
+   * Set the y component of the anchor-point.
+   * @param [in] y The new y value.
+   */
+  void SetAnchorPointY( float y );
+
+  /**
+   * Set the z component of the anchor-point.
+   * @param [in] z The new z value.
+   */
+  void SetAnchorPointZ( float z );
+
+  /**
+   * Retrieve the anchor-point of an actor.
+   * @return The anchor-point.
+   */
+  const Vector3& GetCurrentAnchorPoint() const;
+
+  /**
+   * Sets the position of the Actor.
+   * The coordinates are relative to the Actor's parent.
+   * The Actor's z position will be set to 0.0f.
+   * @param [in] x The new x position
+   * @param [in] y The new y position
+   */
+  void SetPosition( float x, float y );
+
+  /**
+   * Sets the position of the Actor.
+   * The coordinates are relative to the Actor's parent.
+   * @param [in] x The new x position
+   * @param [in] y The new y position
+   * @param [in] z The new z position
+   */
+  void SetPosition( float x, float y, float z );
+
+  /**
+   * Sets the position of the Actor.
+   * The coordinates are relative to the Actor's parent.
+   * @param [in] position The new position.
+   */
+  void SetPosition( const Vector3& position );
+
+  /**
+   * Set the position of an actor along the X-axis.
+   * @param [in] x The new x position
+   */
+  void SetX( float x );
+
+  /**
+   * Set the position of an actor along the Y-axis.
+   * @param [in] y The new y position.
+   */
+  void SetY( float y );
+
+  /**
+   * Set the position of an actor along the Z-axis.
+   * @param [in] z The new z position
+   */
+  void SetZ( float z );
+
+  /**
+   * Translate an actor relative to its existing position.
+   * @param[in] distance The actor will move by this distance.
+   */
+  void TranslateBy( const Vector3& distance );
+
+  /**
+   * Retrieve the position of the Actor.
+   * The coordinates are relative to the Actor's parent.
+   * @return the Actor's position.
+   */
+  const Vector3& GetCurrentPosition() const;
+
+  /**
+   * Retrieve the target position of the Actor.
+   * The coordinates are relative to the Actor's parent.
+   * @return the Actor's position.
+   */
+  const Vector3& GetTargetPosition() const;
+
+  /**
+   * @copydoc Dali::Actor::GetCurrentWorldPosition()
+   */
+  const Vector3& GetCurrentWorldPosition() const;
+
+  /**
+   * @copydoc Dali::Actor::SetPositionInheritanceMode()
+   */
+  void SetPositionInheritanceMode( PositionInheritanceMode mode );
+
+  /**
+   * @copydoc Dali::Actor::GetPositionInheritanceMode()
+   */
+  PositionInheritanceMode GetPositionInheritanceMode() const;
+
+  /**
+   * Sets the orientation of the Actor.
+   * @param [in] angleRadians The new orientation angle in radians.
+   * @param [in] axis The new axis of orientation.
+   */
+  void SetOrientation( const Radian& angleRadians, const Vector3& axis );
+
+  /**
+   * Sets the orientation of the Actor.
+   * @param [in] orientation The new orientation.
+   */
+  void SetOrientation( const Quaternion& orientation );
+
+  /**
+   * Rotate an actor around its existing rotation axis.
+   * @param[in] angleRadians The angle to the rotation to combine with the existing rotation.
+   * @param[in] axis The axis of the rotation to combine with the existing rotation.
+   */
+  void RotateBy( const Radian& angleRadians, const Vector3& axis );
+
+  /**
+   * Apply a relative rotation to an actor.
+   * @param[in] relativeRotation The rotation to combine with the actors existing rotation.
+   */
+  void RotateBy( const Quaternion& relativeRotation );
+
+  /**
+   * Retreive the Actor's orientation.
+   * @return the orientation.
+   */
+  const Quaternion& GetCurrentOrientation() const;
+
+  /**
+   * Set whether a child actor inherits it's parent's orientation. Default is to inherit.
+   * Switching this off means that using SetOrientation() sets the actor's world orientation.
+   * @param[in] inherit - true if the actor should inherit orientation, false otherwise.
+   */
+  void SetInheritOrientation( bool inherit );
+
+  /**
+   * Returns whether the actor inherit's it's parent's orientation.
+   * @return true if the actor inherit's it's parent orientation, false if it uses world orientation.
+   */
+  bool IsOrientationInherited() const;
+
+  /**
+   * Sets the factor of the parents size used for the child actor.
+   * Note: Only used if ResizePolicy is ResizePolicy::SIZE_RELATIVE_TO_PARENT or ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT.
+   * @param[in] factor The vector to multiply the parents size by to get the childs size.
+   */
+  void SetSizeModeFactor( const Vector3& factor );
+
+  /**
+   * Gets the factor of the parents size used for the child actor.
+   * Note: Only used if ResizePolicy is ResizePolicy::SIZE_RELATIVE_TO_PARENT or ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT.
+   * @return The vector being used to multiply the parents size by to get the childs size.
+   */
+  const Vector3& GetSizeModeFactor() const;
+
+  /**
+   * @copydoc Dali::Actor::GetCurrentWorldOrientation()
+   */
+  const Quaternion& GetCurrentWorldOrientation() const;
+
+  /**
+   * Sets a scale factor applied to an actor.
+   * @param [in] scale The scale factor applied on all axes.
+   */
+  void SetScale( float scale );
+
+  /**
+   * Sets a scale factor applied to an actor.
+   * @param [in] scaleX The scale factor applied along the x-axis.
+   * @param [in] scaleY The scale factor applied along the y-axis.
+   * @param [in] scaleZ The scale factor applied along the z-axis.
+   */
+  void SetScale( float scaleX, float scaleY, float scaleZ );
+
+  /**
+   * Sets a scale factor applied to an actor.
+   * @param [in] scale A vector representing the scale factor for each axis.
+   */
+  void SetScale( const Vector3& scale );
+
+  /**
+   * Set the x component of the scale factor.
+   * @param [in] x The new x value.
+   */
+  void SetScaleX( float x );
+
+  /**
+   * Set the y component of the scale factor.
+   * @param [in] y The new y value.
+   */
+  void SetScaleY( float y );
+
+  /**
+   * Set the z component of the scale factor.
+   * @param [in] z The new z value.
+   */
+  void SetScaleZ( float z );
+
+  /**
+   * Apply a relative scale to an actor.
+   * @param[in] relativeScale The scale to combine with the actors existing scale.
+   */
+  void ScaleBy( const Vector3& relativeScale );
+
+  /**
+   * Retrieve the scale factor applied to an actor.
+   * @return A vector representing the scale factor for each axis.
+   */
+  const Vector3& GetCurrentScale() const;
+
+  /**
+   * @copydoc Dali::Actor::GetCurrentWorldScale()
+   */
+  const Vector3& GetCurrentWorldScale() const;
+
+  /**
+   * @copydoc Dali::Actor::SetInheritScale()
+   */
+  void SetInheritScale( bool inherit );
+
+  /**
+   * @copydoc Dali::Actor::IsScaleInherited()
+   */
+  bool IsScaleInherited() const;
+
+  /**
+   * @copydoc Dali::Actor::GetCurrentWorldMatrix()
+   */
+  Matrix GetCurrentWorldMatrix() const;
+
+  // Visibility
+
+  /**
+   * Sets the visibility flag of an actor.
+   * @param [in] visible The new visibility flag.
+   */
+  void SetVisible( bool visible );
+
+  /**
+   * Retrieve the visibility flag of an actor.
+   * @return The visibility flag.
+   */
+  bool IsVisible() const;
+
+  /**
+   * Sets the opacity of an actor.
+   * @param [in] opacity The new opacity.
+   */
+  void SetOpacity( float opacity );
+
+  /**
+   * Retrieve the actor's opacity.
+   * @return The actor's opacity.
+   */
+  float GetCurrentOpacity() const;
+
+  /**
+   * Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover().
+   * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(),
+   * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the
+   * hover event signal will be emitted.
+   *
+   * If the application wishes to temporarily disable the touch or hover event signal emission, then they can do so by calling:
+   * @code
+   * actor.SetSensitive(false);
+   * @endcode
+   *
+   * Then, to re-enable the touch or hover event signal emission, the application should call:
+   * @code
+   * actor.SetSensitive(true);
+   * @endcode
+   *
+   * @see SignalTouch() and SignalHover().
+   * @note If an actor's sensitivity is set to false, then it's children will not emit a touch or hover event signal either.
+   * @param[in]  sensitive  true to enable emission of the touch or hover event signals, false otherwise.
+   */
+  void SetSensitive( bool sensitive )
+  {
+    mSensitive = sensitive;
+  }
+
+  /**
+   * Query whether an actor emits touch or hover event signals.
+   * @see SetSensitive(bool)
+   * @return true, if emission of touch or hover event signals is enabled, false otherwise.
+   */
+  bool IsSensitive() const
+  {
+    return mSensitive;
+  }
+
+  /**
+   * @copydoc Dali::Actor::SetDrawMode
+   */
+  void SetDrawMode( DrawMode::Type drawMode );
+
+  /**
+   * @copydoc Dali::Actor::GetDrawMode
+   */
+  DrawMode::Type GetDrawMode() const;
+
+  /**
+   * @copydoc Dali::Actor::SetOverlay
+   */
+  void SetOverlay( bool enable );
+
+  /**
+   * @copydoc Dali::Actor::IsOverlay
+   */
+  bool IsOverlay() const;
+
+  /**
+   * Sets the actor's color.  The final color of actor depends on its color mode.
+   * This final color is applied to the drawable elements of an actor.
+   * @param [in] color The new color.
+   */
+  void SetColor( const Vector4& color );
+
+  /**
+   * Set the red component of the color.
+   * @param [in] red The new red component.
+   */
+  void SetColorRed( float red );
+
+  /**
+   * Set the green component of the color.
+   * @param [in] green The new green component.
+   */
+  void SetColorGreen( float green );
+
+  /**
+   * Set the blue component of the scale factor.
+   * @param [in] blue The new blue value.
+   */
+  void SetColorBlue( float blue );
+
+  /**
+   * Retrieve the actor's color.
+   * @return The color.
+   */
+  const Vector4& GetCurrentColor() const;
+
+  /**
+   * Sets the actor's color mode.
+   * Color mode specifies whether Actor uses its own color or inherits its parent color
+   * @param [in] colorMode to use.
+   */
+  void SetColorMode( ColorMode colorMode );
+
+  /**
+   * Returns the actor's color mode.
+   * @return currently used colorMode.
+   */
+  ColorMode GetColorMode() const;
+
+  /**
+   * @copydoc Dali::Actor::GetCurrentWorldColor()
+   */
+  const Vector4& GetCurrentWorldColor() const;
+
+  /**
+   * @copydoc Dali::Actor::GetHierarchyDepth()
+   */
+  int GetHierarchyDepth() const
+  {
+    if( mIsOnStage )
+    {
+      return static_cast<int>(mDepth);
+    }
+
+    return -1;
+  }
+
+public:
+
+  // Size negotiation virtual functions
+
+  /**
+   * @brief Called after the size negotiation has been finished for this control.
+   *
+   * The control is expected to assign this given size to itself/its children.
+   *
+   * Should be overridden by derived classes if they need to layout
+   * actors differently after certain operations like add or remove
+   * actors, resize or after changing specific properties.
+   *
+   * Note! As this function is called from inside the size negotiation algorithm, you cannot
+   * call RequestRelayout (the call would just be ignored)
+   *
+   * @param[in]      size       The allocated size.
+   * @param[in,out]  container  The control should add actors to this container that it is not able
+   *                            to allocate a size for.
+   */
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+  }
+
+  /**
+   * @brief Notification for deriving classes when the resize policy is set
+   *
+   * @param[in] policy The policy being set
+   * @param[in] dimension The dimension the policy is being set for
+   */
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) {}
+
+  /**
+   * @brief Virtual method to notify deriving classes that relayout dependencies have been
+   * met and the size for this object is about to be calculated for the given dimension
+   *
+   * @param dimension The dimension that is about to be calculated
+   */
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension );
+
+  /**
+   * @brief Virtual method to notify deriving classes that the size for a dimension
+   * has just been negotiated
+   *
+   * @param[in] size The new size for the given dimension
+   * @param[in] dimension The dimension that was just negotiated
+   */
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension );
+
+  /**
+   * @brief Determine if this actor is dependent on it's children for relayout
+   *
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's children
+   */
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Determine if this actor is dependent on it's children for relayout.
+   *
+   * Called from deriving classes
+   *
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's children
+   */
+  virtual bool RelayoutDependentOnChildrenBase( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Calculate the size for a child
+   *
+   * @param[in] child The child actor to calculate the size for
+   * @param[in] dimension The dimension to calculate the size for. E.g. width or height.
+   * @return Return the calculated size for the given dimension
+   */
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension );
+
+  /**
+   * @brief This method is called during size negotiation when a height is required for a given width.
+   *
+   * Derived classes should override this if they wish to customize the height returned.
+   *
+   * @param width to use.
+   * @return the height based on the width.
+   */
+  virtual float GetHeightForWidth( float width );
+
+  /**
+   * @brief This method is called during size negotiation when a width is required for a given height.
+   *
+   * Derived classes should override this if they wish to customize the width returned.
+   *
+   * @param height to use.
+   * @return the width based on the width.
+   */
+  virtual float GetWidthForHeight( float height );
+
+public:
+
+  // Size negotiation
+
+  /**
+   * @brief Called by the RelayoutController to negotiate the size of an actor.
+   *
+   * The size allocated by the the algorithm is passed in which the
+   * actor must adhere to.  A container is passed in as well which
+   * the actor should populate with actors it has not / or does not
+   * need to handle in its size negotiation.
+   *
+   * @param[in]      size       The allocated size.
+   * @param[in,out]  container  The container that holds actors that are fed back into the
+   *                            RelayoutController algorithm.
+   */
+  void NegotiateSize( const Vector2& size, RelayoutContainer& container );
+
+  /**
+   * @copydoc Dali::Actor::SetResizePolicy()
+   */
+  void SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @copydoc Dali::Actor::GetResizePolicy()
+   */
+  ResizePolicy::Type GetResizePolicy( Dimension::Type dimension ) const;
+
+  /**
+   * @copydoc Dali::Actor::SetSizeScalePolicy()
+   */
+  void SetSizeScalePolicy( SizeScalePolicy::Type policy );
+
+  /**
+   * @copydoc Dali::Actor::GetSizeScalePolicy()
+   */
+  SizeScalePolicy::Type GetSizeScalePolicy() const;
+
+  /**
+   * @copydoc Dali::Actor::SetDimensionDependency()
+   */
+  void SetDimensionDependency( Dimension::Type dimension, Dimension::Type dependency );
+
+  /**
+   * @copydoc Dali::Actor::GetDimensionDependency()
+   */
+  Dimension::Type GetDimensionDependency( Dimension::Type dimension ) const;
+
+  /**
+   * @brief Set the size negotiation relayout enabled on this actor
+   *
+   * @param[in] relayoutEnabled Boolean to enable or disable relayout
+   */
+  void SetRelayoutEnabled( bool relayoutEnabled );
+
+  /**
+   * @brief Return if relayout is enabled
+   *
+   * @return Return if relayout is enabled or not for this actor
+   */
+  bool IsRelayoutEnabled() const;
+
+  /**
+   * @brief Mark an actor as having it's layout dirty
+   *
+   * @param dirty Whether to mark actor as dirty or not
+   * @param dimension The dimension(s) to mark as dirty
+   */
+  void SetLayoutDirty( bool dirty, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Return if any of an actor's dimensions are marked as dirty
+   *
+   * @param dimension The dimension(s) to check
+   * @return Return if any of the requested dimensions are dirty
+   */
+  bool IsLayoutDirty( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const;
+
+  /**
+   * @brief Returns if relayout is enabled and the actor is not dirty
+   *
+   * @return Return if it is possible to relayout the actor
+   */
+  bool RelayoutPossible( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const;
+
+  /**
+   * @brief Returns if relayout is enabled and the actor is dirty
+   *
+   * @return Return if it is required to relayout the actor
+   */
+  bool RelayoutRequired( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const;
+
+  /**
+   * @brief Request a relayout, which means performing a size negotiation on this actor, its parent and children (and potentially whole scene)
+   *
+   * This method is automatically called from OnStageConnection(), OnChildAdd(),
+   * OnChildRemove(), SetSizePolicy(), SetMinimumSize() and SetMaximumSize().
+   *
+   * This method can also be called from a derived class every time it needs a different size.
+   * At the end of event processing, the relayout process starts and
+   * all controls which requested Relayout will have their sizes (re)negotiated.
+   *
+   * @note RelayoutRequest() can be called multiple times; the size negotiation is still
+   * only performed once, i.e. there is no need to keep track of this in the calling side.
+   */
+  void RelayoutRequest( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Determine if this actor is dependent on it's parent for relayout
+   *
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's parent
+   */
+  bool RelayoutDependentOnParent( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Determine if this actor has another dimension depedent on the specified one
+   *
+   * @param dimension The dimension to check for
+   * @param dependentDimension The dimension to check for dependency with
+   * @return Return if the actor is dependent on this dimension
+   */
+  bool RelayoutDependentOnDimension( Dimension::Type dimension, Dimension::Type dependentDimension );
+
+  /**
+   * Negotiate sizes for a control in all dimensions
+   *
+   * @param[in] allocatedSize The size constraint that the control must respect
+   */
+  void NegotiateDimensions( const Vector2& allocatedSize );
+
+  /**
+   * Negotiate size for a specific dimension
+   *
+   * The algorithm adopts a recursive dependency checking approach. Meaning, that wherever dependencies
+   * are found, e.g. an actor dependent on its parent, the dependency will be calculated first with NegotiatedDimension and
+   * LayoutDimensionNegotiated flags being filled in on the actor.
+   *
+   * @post All actors that exist in the dependency chain connected to the given actor will have had their NegotiatedDimensions
+   * calculated and set as well as the LayoutDimensionNegotiated flags.
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @param[in] allocatedSize The size constraint that the actor must respect
+   */
+  void NegotiateDimension( Dimension::Type dimension, const Vector2& allocatedSize, ActorDimensionStack& recursionStack );
+
+  /**
+   * @brief Calculate the size of a dimension
+   *
+   * @param[in] dimension The dimension to calculate the size for
+   * @param[in] maximumSize The upper bounds on the size
+   * @return Return the calculated size for the dimension
+   */
+  float CalculateSize( Dimension::Type dimension, const Vector2& maximumSize );
+
+  /**
+   * @brief Clamp a dimension given the relayout constraints on this actor
+   *
+   * @param[in] size The size to constrain
+   * @param[in] dimension The dimension the size exists in
+   * @return Return the clamped size
+   */
+  float ClampDimension( float size, Dimension::Type dimension );
+
+  /**
+   * Negotiate a dimension based on the size of the parent
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromParent( Dimension::Type dimension );
+
+  /**
+   * Negotiate a dimension based on the size of the parent. Fitting inside.
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromParentFit( Dimension::Type dimension );
+
+  /**
+   * Negotiate a dimension based on the size of the parent. Flooding the whole space.
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromParentFlood( Dimension::Type dimension );
+
+  /**
+   * @brief Negotiate a dimension based on the size of the children
+   *
+   * @param[in] dimension The dimension to negotiate on
+   * @return Return the negotiated size
+   */
+  float NegotiateFromChildren( Dimension::Type dimension );
+
+  /**
+   * Set the negotiated dimension value for the given dimension(s)
+   *
+   * @param negotiatedDimension The value to set
+   * @param dimension The dimension(s) to set the value for
+   */
+  void SetNegotiatedDimension( float negotiatedDimension, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * Return the value of negotiated dimension for the given dimension
+   *
+   * @param dimension The dimension to retrieve
+   * @return Return the value of the negotiated dimension
+   */
+  float GetNegotiatedDimension( Dimension::Type dimension ) const;
+
+  /**
+   * @brief Set the padding for a dimension
+   *
+   * @param[in] padding Padding for the dimension. X = start (e.g. left, bottom), y = end (e.g. right, top)
+   * @param[in] dimension The dimension to set
+   */
+  void SetPadding( const Vector2& padding, Dimension::Type dimension );
+
+  /**
+   * Return the value of padding for the given dimension
+   *
+   * @param dimension The dimension to retrieve
+   * @return Return the value of padding for the dimension
+   */
+  Vector2 GetPadding( Dimension::Type dimension ) const;
+
+  /**
+   * Return the actor size for a given dimension
+   *
+   * @param[in] dimension The dimension to retrieve the size for
+   * @return Return the size for the given dimension
+   */
+  float GetSize( Dimension::Type dimension ) const;
+
+  /**
+   * Return the natural size of the actor for a given dimension
+   *
+   * @param[in] dimension The dimension to retrieve the size for
+   * @return Return the natural size for the given dimension
+   */
+  float GetNaturalSize( Dimension::Type dimension ) const;
+
+  /**
+   * @brief Return the amount of size allocated for relayout
+   *
+   * May include padding
+   *
+   * @param[in] dimension The dimension to retrieve
+   * @return Return the size
+   */
+  float GetRelayoutSize( Dimension::Type dimension ) const;
+
+  /**
+   * @brief If the size has been negotiated return that else return normal size
+   *
+   * @param[in] dimension The dimension to retrieve
+   * @return Return the size
+   */
+  float GetLatestSize( Dimension::Type dimension ) const;
+
+  /**
+   * Apply the negotiated size to the actor
+   *
+   * @param[in] container The container to fill with actors that require further relayout
+   */
+  void SetNegotiatedSize( RelayoutContainer& container );
+
+  /**
+   * @brief Flag the actor as having it's layout dimension negotiated.
+   *
+   * @param[in] negotiated The status of the flag to set.
+   * @param[in] dimension The dimension to set the flag for
+   */
+  void SetLayoutNegotiated( bool negotiated, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Test whether the layout dimension for this actor has been negotiated or not.
+   *
+   * @param[in] dimension The dimension to determine the value of the flag for
+   * @return Return if the layout dimension is negotiated or not.
+   */
+  bool IsLayoutNegotiated( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) const;
+
+  /**
+   * @brief provides the Actor implementation of GetHeightForWidth
+   * @param width to use.
+   * @return the height based on the width.
+   */
+  float GetHeightForWidthBase( float width );
+
+  /**
+   * @brief provides the Actor implementation of GetWidthForHeight
+   * @param height to use.
+   * @return the width based on the height.
+   */
+  float GetWidthForHeightBase( float height );
+
+  /**
+   * @brief Calculate the size for a child
+   *
+   * @param[in] child The child actor to calculate the size for
+   * @param[in] dimension The dimension to calculate the size for. E.g. width or height.
+   * @return Return the calculated size for the given dimension
+   */
+  float CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension );
+
+  /**
+   * @brief Set the preferred size for size negotiation
+   *
+   * @param[in] size The preferred size to set
+   */
+  void SetPreferredSize( const Vector2& size );
+
+  /**
+   * @brief Return the preferred size used for size negotiation
+   *
+   * @return Return the preferred size
+   */
+  Vector2 GetPreferredSize() const;
+
+  /**
+   * @copydoc Dali::Actor::SetMinimumSize
+   */
+  void SetMinimumSize( float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @copydoc Dali::Actor::GetMinimumSize
+   */
+  float GetMinimumSize( Dimension::Type dimension ) const;
+
+  /**
+   * @copydoc Dali::Actor::SetMaximumSize
+   */
+  void SetMaximumSize( float size, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @copydoc Dali::Actor::GetMaximumSize
+   */
+  float GetMaximumSize( Dimension::Type dimension ) const;
+  
+  /**
+   * @copydoc Dali::Actor::AddRenderer()
+   */
+  unsigned int AddRenderer( Renderer& renderer );
+
+  /**
+   * @copydoc Dali::Actor::GetRendererCount()
+   */
+  unsigned int GetRendererCount() const;
+
+  /**
+   * @copydoc Dali::Actor::GetRendererAt()
+   */
+  Renderer& GetRendererAt( unsigned int index );
+
+  /**
+   * @copydoc Dali::Actor::RemoveRenderer()
+   */
+  void RemoveRenderer( Renderer& renderer );
+
+  /**
+   * @copydoc Dali::Actor::RemoveRenderer()
+   */
+  void RemoveRenderer( unsigned int index );
+
+public:
+
+  /**
+   * Converts screen coordinates into the actor's coordinate system.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   * @param[out] localX On return, the X-coordinate relative to the actor.
+   * @param[out] localY On return, the Y-coordinate relative to the actor.
+   * @param[in] screenX The screen X-coordinate.
+   * @param[in] screenY The screen Y-coordinate.
+   * @return True if the conversion succeeded.
+   */
+  bool ScreenToLocal( float& localX, float& localY, float screenX, float screenY ) const;
+
+  /**
+   * Converts screen coordinates into the actor's coordinate system.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   * @param[in] renderTask The render-task used to display the actor.
+   * @param[out] localX On return, the X-coordinate relative to the actor.
+   * @param[out] localY On return, the Y-coordinate relative to the actor.
+   * @param[in] screenX The screen X-coordinate.
+   * @param[in] screenY The screen Y-coordinate.
+   * @return True if the conversion succeeded.
+   */
+  bool ScreenToLocal( RenderTask& renderTask, float& localX, float& localY, float screenX, float screenY ) const;
+
+  /**
+   * Converts from the actor's coordinate system to screen coordinates.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   * @param[in] viewMatrix The view-matrix
+   * @param[in] projectionMatrix The projection-matrix
+   * @param[in] viewport The view-port
+   * @param[out] localX On return, the X-coordinate relative to the actor.
+   * @param[out] localY On return, the Y-coordinate relative to the actor.
+   * @param[in] screenX The screen X-coordinate.
+   * @param[in] screenY The screen Y-coordinate.
+   * @return True if the conversion succeeded.
+   */
+  bool ScreenToLocal( const Matrix& viewMatrix,
+                      const Matrix& projectionMatrix,
+                      const Viewport& viewport,
+                      float& localX,
+                      float& localY,
+                      float screenX,
+                      float screenY ) const;
+
+  /**
+   * Performs a ray-sphere test with the given pick-ray and the actor's bounding sphere.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   * @param[in] rayOrigin The ray origin in the world's reference system.
+   * @param[in] rayDir The ray director vector in the world's reference system.
+   * @return True if the ray intersects the actor's bounding sphere.
+   */
+  bool RaySphereTest( const Vector4& rayOrigin, const Vector4& rayDir ) const;
+
+  /**
+   * Performs a ray-actor test with the given pick-ray and the actor's geometry.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   * @param[in] rayOrigin The ray origin in the world's reference system.
+   * @param[in] rayDir The ray director vector in the world's reference system.
+   * @param[out] hitPointLocal The hit point in the Actor's local reference system.
+   * @param[out] distance The distance from the hit point to the camera.
+   * @return True if the ray intersects the actor's geometry.
+   */
+  bool RayActorTest( const Vector4& rayOrigin,
+                     const Vector4& rayDir,
+                     Vector4& hitPointLocal,
+                     float& distance ) const;
+
+  /**
+   * Sets whether the actor should receive a notification when touch or hover motion events leave
+   * the boundary of the actor.
+   *
+   * @note By default, this is set to false as most actors do not require this.
+   * @note Need to connect to the SignalTouch or SignalHover to actually receive this event.
+   *
+   * @param[in]  required  Should be set to true if a Leave event is required
+   */
+  void SetLeaveRequired( bool required );
+
+  /**
+   * This returns whether the actor requires touch or hover events whenever touch or hover motion events leave
+   * the boundary of the actor.
+   * @return true if a Leave event is required, false otherwise.
+   */
+  bool GetLeaveRequired() const;
+
+  /**
+   * @copydoc Dali::Actor::SetKeyboardFocusable()
+   */
+  void SetKeyboardFocusable( bool focusable );
+
+  /**
+   * @copydoc Dali::Actor::IsKeyboardFocusable()
+   */
+  bool IsKeyboardFocusable() const;
+
+  /**
+   * Query whether the application or derived actor type requires touch events.
+   * @return True if touch events are required.
+   */
+  bool GetTouchRequired() const;
+
+  /**
+   * Query whether the application or derived actor type requires hover events.
+   * @return True if hover events are required.
+   */
+  bool GetHoverRequired() const;
+
+  /**
+   * Query whether the application or derived actor type requires wheel events.
+   * @return True if wheel events are required.
+   */
+  bool GetWheelEventRequired() const;
+
+  /**
+   * Query whether the actor is actually hittable.  This method checks whether the actor is
+   * sensitive, has the visibility flag set to true and is not fully transparent.
+   * @return true, if it can be hit, false otherwise.
+   */
+  bool IsHittable() const;
+
+  // Gestures
+
+  /**
+   * Retrieve the gesture data associated with this actor. The first call to this method will
+   * allocate space for the ActorGestureData so this should only be called if an actor really does
+   * require gestures.
+   * @return Reference to the ActorGestureData for this actor.
+   * @note Once the gesture-data is created for an actor it is likely that gestures are required
+   * throughout the actor's lifetime so it will only be deleted when the actor is destroyed.
+   */
+  ActorGestureData& GetGestureData();
+
+  /**
+   * Queries whether the actor requires the gesture type.
+   * @param[in] type The gesture type.
+   */
+  bool IsGestureRequred( Gesture::Type type ) const;
+
+  // Signals
+
+  /**
+   * Used by the EventProcessor to emit touch event signals.
+   * @param[in] event The touch event.
+   * @return True if the event was consumed.
+   */
+  bool EmitTouchEventSignal( const TouchEvent& event );
+
+  /**
+   * Used by the EventProcessor to emit hover event signals.
+   * @param[in] event The hover event.
+   * @return True if the event was consumed.
+   */
+  bool EmitHoverEventSignal( const HoverEvent& event );
+
+  /**
+   * Used by the EventProcessor to emit wheel event signals.
+   * @param[in] event The wheel event.
+   * @return True if the event was consumed.
+   */
+  bool EmitWheelEventSignal( const WheelEvent& event );
+
+  /**
+   * @copydoc Dali::Actor::TouchedSignal()
+   */
+  Dali::Actor::TouchSignalType& TouchedSignal();
+
+  /**
+   * @copydoc Dali::Actor::HoveredSignal()
+   */
+  Dali::Actor::HoverSignalType& HoveredSignal();
+
+  /**
+   * @copydoc Dali::Actor::WheelEventSignal()
+   */
+  Dali::Actor::WheelEventSignalType& WheelEventSignal();
+
+  /**
+   * @copydoc Dali::Actor::OnStageSignal()
+   */
+  Dali::Actor::OnStageSignalType& OnStageSignal();
+
+  /**
+   * @copydoc Dali::Actor::OffStageSignal()
+   */
+  Dali::Actor::OffStageSignalType& OffStageSignal();
+
+  /**
+   * @copydoc Dali::Actor::OnRelayoutSignal()
+   */
+  Dali::Actor::OnRelayoutSignalType& OnRelayoutSignal();
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object,
+                               ConnectionTrackerInterface* tracker,
+                               const std::string& signalName,
+                               FunctorDelegate* functor );
+
+  /**
+   * Performs actions as requested using the action name.
+   * @param[in] object The object on which to perform the action.
+   * @param[in] actionName The action to perform.
+   * @param[in] attributes The attributes with which to perfrom this action.
+   * @return true if the action was done.
+   */
+  static bool DoAction( BaseObject* object,
+                        const std::string& actionName,
+                        const Property::Map& attributes );
+
+public:
+  // For Animation
+
+  /**
+   * This should only be called by Animation, when the actors SIZE property is animated.
+   *
+   * @param[in] animation The animation that resized the actor
+   * @param[in] targetSize The new target size of the actor
+   */
+  void NotifySizeAnimation( Animation& animation, const Vector3& targetSize );
+
+  /**
+   * This should only be called by Animation, when the actors SIZE_WIDTH or SIZE_HEIGHT property is animated.
+   *
+   * @param[in] animation The animation that resized the actor
+   * @param[in] targetSize The new target size of the actor
+   */
+  void NotifySizeAnimation( Animation& animation, float targetSize, Property::Index property );
+
+  /**
+   * For use in derived classes.
+   * This should only be called by Animation, when the actor is resized using Animation::Resize().
+   */
+  virtual void OnSizeAnimation( Animation& animation, const Vector3& targetSize )
+  {
+  }
+
+protected:
+
+  enum DerivedType
+  {
+    BASIC, RENDERABLE, LAYER, ROOT_LAYER
+  };
+
+  /**
+   * Protected Constructor.  See Actor::New().
+   * The second-phase construction Initialize() member should be called immediately after this.
+   * @param[in] derivedType The derived type of actor (if any).
+   */
+  Actor( DerivedType derivedType );
+
+  /**
+   * Second-phase constructor. Must be called immediately after creating a new Actor;
+   */
+  void Initialize( void );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Actor();
+
+  /**
+   * Called on a child during Add() when the parent actor is connected to the Stage.
+   * @param[in] stage The stage.
+   * @param[in] parentDepth The depth of the parent in the hierarchy
+   * @param[in] index If set, it is only used for positioning the actor within the parent's child list.
+   */
+  void ConnectToStage( unsigned int parentDepth, int index = -1 );
+
+  /**
+   * Helper for ConnectToStage, to recursively connect a tree of actors.
+   * This is atomic i.e. not interrupted by user callbacks.
+   * @param[in] index If set, it is only used for positioning the actor within the parent's child list.
+   * @param[in] depth The depth in the hierarchy of the actor
+   * @param[out] connectionList On return, the list of connected actors which require notification.
+   */
+  void RecursiveConnectToStage( ActorContainer& connectionList, unsigned int depth, int index = -1 );
+
+  /**
+   * Connect the Node associated with this Actor to the scene-graph.
+   * @param[in] index If set, it is only used for positioning the actor within the parent's child list.
+   */
+  void ConnectToSceneGraph( int index = -1 );
+
+  /**
+   * Helper for ConnectToStage, to notify a connected actor through the public API.
+   */
+  void NotifyStageConnection();
+
+  /**
+   * Called on a child during Remove() when the actor was previously on the Stage.
+   */
+  void DisconnectFromStage();
+
+  /**
+   * Helper for DisconnectFromStage, to recursively disconnect a tree of actors.
+   * This is atomic i.e. not interrupted by user callbacks.
+   * @param[out] disconnectionList On return, the list of disconnected actors which require notification.
+   */
+  void RecursiveDisconnectFromStage( ActorContainer& disconnectionList );
+
+  /**
+   * Disconnect the Node associated with this Actor from the scene-graph.
+   */
+  void DisconnectFromSceneGraph();
+
+  /**
+   * Helper for DisconnectFromStage, to notify a disconnected actor through the public API.
+   */
+  void NotifyStageDisconnection();
+
+  /**
+   * When the Actor is OnStage, checks whether the corresponding Node is connected to the scene graph.
+   * @return True if the Actor is OnStage & has a Node connected to the scene graph.
+   */
+  bool IsNodeConnected() const;
+
+  /**
+   * Calculate the size of the z dimension for a 2D size
+   *
+   * @param[in] size The 2D size (X, Y) to calculate Z from
+   *
+   * @return Return the Z dimension for this size
+   */
+  float CalculateSizeZ( const Vector2& size ) const;
+
+public:
+  // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue );
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+private:
+
+  // Undefined
+  Actor();
+
+  // Undefined
+  Actor( const Actor& );
+
+  // Undefined
+  Actor& operator=( const Actor& rhs );
+
+  /**
+   * Set the actors parent.
+   * @param[in] parent The new parent.
+   * @param[in] index If set, it is only used for positioning the actor within the parent's child list.
+   */
+  void SetParent( Actor* parent, int index = -1 );
+
+  /**
+   * Helper to create a Node for this Actor.
+   * To be overriden in derived classes.
+   * @return A newly allocated node.
+   */
+  virtual SceneGraph::Node* CreateNode() const;
+
+  /**
+   * For use in derived classes, called after Initialize()
+   */
+  virtual void OnInitialize()
+  {
+  }
+
+  /**
+   * For use in internal derived classes.
+   * This is called during ConnectToStage(), after the actor has finished adding its node to the scene-graph.
+   * The derived class must not modify the actor hierachy (Add/Remove children) during this callback.
+   */
+  virtual void OnStageConnectionInternal()
+  {
+  }
+
+  /**
+   * For use in internal derived classes.
+   * This is called during DisconnectFromStage(), before the actor removes its node from the scene-graph.
+   * The derived class must not modify the actor hierachy (Add/Remove children) during this callback.
+   */
+  virtual void OnStageDisconnectionInternal()
+  {
+  }
+
+  /**
+   * For use in external (CustomActor) derived classes.
+   * This is called after the atomic ConnectToStage() traversal has been completed.
+   */
+  virtual void OnStageConnectionExternal( int depth )
+  {
+  }
+
+  /**
+   * For use in external (CustomActor) derived classes.
+   * This is called after the atomic DisconnectFromStage() traversal has been completed.
+   */
+  virtual void OnStageDisconnectionExternal()
+  {
+  }
+
+  /**
+   * For use in derived classes; this is called after Add() has added a child.
+   * @param[in] child The child that was added.
+   */
+  virtual void OnChildAdd( Actor& child )
+  {
+  }
+
+  /**
+   * For use in derived classes; this is called after Remove() has removed a child.
+   * @param[in] child The child that was removed.
+   */
+  virtual void OnChildRemove( Actor& child )
+  {
+  }
+
+  /**
+   * For use in derived classes.
+   * This is called after SizeSet() has been called.
+   */
+  virtual void OnSizeSet( const Vector3& targetSize )
+  {
+  }
+
+  /**
+   * For use in derived classes.
+   * This is only called if mDerivedRequiresTouch is true, and the touch-signal was not consumed.
+   * @param[in] event The touch event.
+   * @return True if the event should be consumed.
+   */
+  virtual bool OnTouchEvent( const TouchEvent& event )
+  {
+    return false;
+  }
+
+  /**
+   * For use in derived classes.
+   * This is only called if mDerivedRequiresHover is true, and the hover-signal was not consumed.
+   * @param[in] event The hover event.
+   * @return True if the event should be consumed.
+   */
+  virtual bool OnHoverEvent( const HoverEvent& event )
+  {
+    return false;
+  }
+
+  /**
+   * For use in derived classes.
+   * This is only called if the wheel signal was not consumed.
+   * @param[in] event The wheel event.
+   * @return True if the event should be consumed.
+   */
+  virtual bool OnWheelEvent( const WheelEvent& event )
+  {
+    return false;
+  }
+
+  /**
+   * @brief Ensure the relayout data is allocated
+   */
+  void EnsureRelayoutData();
+
+  /**
+   * @brief Apply the size set policy to the input size
+   *
+   * @param[in] size The size to apply the policy to
+   * @return Return the adjusted size
+   */
+  Vector2 ApplySizeSetPolicy( const Vector2 size );
+
+protected:
+
+  Actor* mParent;                 ///< Each actor (except the root) can have one parent
+  ActorContainer* mChildren;      ///< Container of referenced actors
+  const SceneGraph::Node* mNode;  ///< Not owned
+  Vector3* mParentOrigin;         ///< NULL means ParentOrigin::DEFAULT. ParentOrigin is non-animatable
+  Vector3* mAnchorPoint;          ///< NULL means AnchorPoint::DEFAULT. AnchorPoint is non-animatable
+
+  struct RelayoutData;
+  RelayoutData* mRelayoutData; ///< Struct to hold optional collection of relayout variables
+
+  ActorGestureData* mGestureData;   ///< Optional Gesture data. Only created when actor requires gestures
+
+  ActorAttachmentPtr mAttachment;   ///< Optional referenced attachment
+
+  // Signals
+  Dali::Actor::TouchSignalType             mTouchedSignal;
+  Dali::Actor::HoverSignalType             mHoveredSignal;
+  Dali::Actor::WheelEventSignalType        mWheelEventSignal;
+  Dali::Actor::OnStageSignalType           mOnStageSignal;
+  Dali::Actor::OffStageSignalType          mOffStageSignal;
+  Dali::Actor::OnRelayoutSignalType        mOnRelayoutSignal;
+
+  Vector3         mTargetSize;       ///< Event-side storage for size (not a pointer as most actors will have a size)
+  Vector3         mTargetPosition;   ///< Event-side storage for position (not a pointer as most actors will have a position)
+
+  std::string     mName;      ///< Name of the actor
+  unsigned int    mId;        ///< A unique ID to identify the actor starting from 1, and 0 is reserved
+
+  unsigned short mDepth                            :12; ///< Cached: The depth in the hierarchy of the actor. Only 4096 levels of depth are supported
+  const bool mIsRoot                               : 1; ///< Flag to identify the root actor
+  const bool mIsRenderable                         : 1; ///< Flag to identify that this is a renderable actor
+  const bool mIsLayer                              : 1; ///< Flag to identify that this is a layer
+  bool mIsOnStage                                  : 1; ///< Flag to identify whether the actor is on-stage
+  bool mSensitive                                  : 1; ///< Whether the actor emits touch event signals
+  bool mLeaveRequired                              : 1; ///< Whether a touch event signal is emitted when the a touch leaves the actor's bounds
+  bool mKeyboardFocusable                          : 1; ///< Whether the actor should be focusable by keyboard navigation
+  bool mDerivedRequiresTouch                       : 1; ///< Whether the derived actor type requires touch event signals
+  bool mDerivedRequiresHover                       : 1; ///< Whether the derived actor type requires hover event signals
+  bool mDerivedRequiresWheelEvent                  : 1; ///< Whether the derived actor type requires wheel event signals
+  bool mOnStageSignalled                           : 1; ///< Set to true before OnStageConnection signal is emitted, and false before OnStageDisconnection
+  bool mInsideOnSizeSet                            : 1; ///< Whether we are inside OnSizeSet
+  bool mInheritOrientation                         : 1; ///< Cached: Whether the parent's orientation should be inherited.
+  bool mInheritScale                               : 1; ///< Cached: Whether the parent's scale should be inherited.
+  DrawMode::Type mDrawMode                         : 2; ///< Cached: How the actor and its children should be drawn
+  PositionInheritanceMode mPositionInheritanceMode : 2; ///< Cached: Determines how position is inherited
+  ColorMode mColorMode                             : 2; ///< Cached: Determines whether mWorldColor is inherited
+
+private:
+
+  static ActorContainer mNullChildren;  ///< Empty container (shared by all actors, returned by GetChildren() const)
+  static unsigned int mActorCounter;    ///< A counter to track the actor instance creation
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Actor& GetImplementation( Dali::Actor& actor )
+{
+  DALI_ASSERT_ALWAYS( actor && "Actor handle is empty" );
+
+  BaseObject& handle = actor.GetBaseObject();
+
+  return static_cast< Internal::Actor& >( handle );
+}
+
+inline const Internal::Actor& GetImplementation( const Dali::Actor& actor )
+{
+  DALI_ASSERT_ALWAYS( actor && "Actor handle is empty" );
+
+  const BaseObject& handle = actor.GetBaseObject();
+
+  return static_cast< const Internal::Actor& >( handle );
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_H__
diff --git a/dali/internal/event/actors/camera-actor-impl.cpp b/dali/internal/event/actors/camera-actor-impl.cpp
new file mode 100644 (file)
index 0000000..7ee2ef1
--- /dev/null
@@ -0,0 +1,802 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/camera-actor-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cmath>
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/event/common/projection.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+/**
+ * We want to discourage the use of property strings (minimize string comparisons),
+ * particularly for the default properties.
+ *              Name                     Type   writable animatable constraint-input  enum for index-checking
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "type",                   STRING,   true,    false,   true,   Dali::CameraActor::Property::TYPE                  )
+DALI_PROPERTY( "projection-mode",        STRING,   true,    false,   true,   Dali::CameraActor::Property::PROJECTION_MODE       )
+DALI_PROPERTY( "field-of-view",          FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FIELD_OF_VIEW         )
+DALI_PROPERTY( "aspect-ratio",           FLOAT,    true,    false,   true,   Dali::CameraActor::Property::ASPECT_RATIO          )
+DALI_PROPERTY( "near-plane-distance",    FLOAT,    true,    false,   true,   Dali::CameraActor::Property::NEAR_PLANE_DISTANCE   )
+DALI_PROPERTY( "far-plane-distance",     FLOAT,    true,    false,   true,   Dali::CameraActor::Property::FAR_PLANE_DISTANCE    )
+DALI_PROPERTY( "left-plane-distance",    FLOAT,    true,    false,   true,   Dali::CameraActor::Property::LEFT_PLANE_DISTANCE   )
+DALI_PROPERTY( "right-plane-distance",   FLOAT,    true,    false,   true,   Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE  )
+DALI_PROPERTY( "top-plane-distance",     FLOAT,    true,    false,   true,   Dali::CameraActor::Property::TOP_PLANE_DISTANCE    )
+DALI_PROPERTY( "bottom-plane-distance",  FLOAT,    true,    false,   true,   Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE )
+DALI_PROPERTY( "target-position",        VECTOR3,  true,    false,   true,   Dali::CameraActor::Property::TARGET_POSITION       )
+DALI_PROPERTY( "projection-matrix",      MATRIX,   false,   false,   true,   Dali::CameraActor::Property::PROJECTION_MATRIX     )
+DALI_PROPERTY( "view-matrix",            MATRIX,   false,   false,   true,   Dali::CameraActor::Property::VIEW_MATRIX           )
+DALI_PROPERTY( "invert-y-axis",          BOOLEAN,  true,    false,   true,   Dali::CameraActor::Property::INVERT_Y_AXIS         )
+DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
+
+// calculate the far plane distance for a 16bit depth buffer with 4 bits per unit precision
+void CalculateClippingAndZ( float width, float height, float& nearClippingPlane, float& farClippingPlane, float& cameraZ )
+{
+  nearClippingPlane = std::max( width, height );
+  farClippingPlane = nearClippingPlane + static_cast<float>( 0xFFFF >> 4 );
+  cameraZ = 2.0f * nearClippingPlane;
+}
+
+BaseHandle Create()
+{
+  return Dali::CameraActor::New();
+}
+
+TypeRegistration mType( typeid( Dali::CameraActor ), typeid( Dali::Actor ), Create );
+
+/**
+ * Builds the picking ray in the world reference system from an orthographic camera
+ * The ray origin is the screen coordinate in the near plane translated to a parallel
+ * plane at the camera origin. The ray direction is the direction the camera is facing
+ * (i.e. Z=-1 in view space).
+ */
+void BuildOrthoPickingRay( const Matrix& viewMatrix,
+                           const Matrix& projectionMatrix,
+                           const Viewport& viewport,
+                           float screenX,
+                           float screenY,
+                           Vector4& rayOrigin,
+                           Vector4& rayDir,
+                           float nearPlaneDistance )
+{
+  //          inv( modelMatrix )          inv( viewMatrix )    inv( projectionMatrix )           normalize
+  //          <-----------------         <-----------------         <--------------           <-------------
+  //  Local                      World                      Camera                 Normalized                 Screen
+  // reference                  reference                  reference                  clip                  coordinates
+  //  system                     system                     system                 coordinates
+  //          ----------------->         ----------------->         -------------->           ------------->
+  //             modelMatrix                 viewMatrix             projectionMatrix             viewport
+
+  // Transforms the touch point from the screen reference system to the world reference system.
+  Matrix invViewProjection( false ); // Don't initialize.
+  Matrix::Multiply( invViewProjection, viewMatrix, projectionMatrix );
+  if( !invViewProjection.Invert() )
+  {
+    DALI_ASSERT_DEBUG( false );
+  }
+
+  Vector4 near( screenX - viewport.x, viewport.height - (screenY - viewport.y), 0.f, 1.f );
+  if( !Unproject( near, invViewProjection, viewport.width, viewport.height, rayOrigin ) )
+  {
+    DALI_ASSERT_DEBUG( false );
+  }
+
+  Matrix invView = viewMatrix;
+  if( !invView.Invert() )
+  {
+    DALI_ASSERT_DEBUG( false );
+  }
+
+  Vector4 cameraOrigin = invView * Vector4( 0.f, 0.f, 0.f, 1.f );
+  Vector4 nearPlaneOrigin = invView * Vector4( 0.0f, 0.0f, -nearPlaneDistance, 1.0f);
+
+  // Vector pointing from the camera to the near plane
+  rayDir = cameraOrigin - nearPlaneOrigin;
+  rayOrigin -= rayDir;
+  rayDir.Normalize();
+  rayDir.w = 1.0f;
+}
+
+} // namespace
+
+CameraActorPtr CameraActor::New( const Size& size )
+{
+  CameraActorPtr actor(new CameraActor());
+
+  // Second-phase construction
+
+  actor->Initialize();
+
+  actor->SetName("DefaultCamera");
+
+  // Create the attachment
+  actor->mCameraAttachment = CameraAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
+
+  actor->Attach(*actor->mCameraAttachment);
+
+  actor->SetPerspectiveProjection( size );
+
+  // By default Actors face in the positive Z direction in world space
+  // CameraActors should face in the negative Z direction, towards the other actors
+  actor->SetOrientation( Quaternion( Dali::ANGLE_180, Vector3::YAXIS ) );
+
+  return actor;
+}
+
+void CameraActor::OnInitialize()
+{
+}
+
+CameraActor::CameraActor()
+: Actor( Actor::BASIC )
+{
+}
+
+CameraActor::~CameraActor()
+{
+}
+
+void CameraActor::SetType( Dali::Camera::Type type )
+{
+  mCameraAttachment->SetType(type);
+}
+
+Dali::Camera::Type CameraActor::GetType() const
+{
+  return mCameraAttachment->GetType();
+}
+
+void CameraActor::SetProjectionMode( Dali::Camera::ProjectionMode mode )
+{
+  mCameraAttachment->SetProjectionMode(mode);
+}
+
+Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
+{
+  return mCameraAttachment->GetProjectionMode();
+}
+
+void CameraActor::SetFieldOfView( float fieldOfView )
+{
+  mCameraAttachment->SetFieldOfView(fieldOfView);
+}
+
+float CameraActor::GetFieldOfView( ) const
+{
+  return mCameraAttachment->GetFieldOfView();
+}
+
+void CameraActor::SetAspectRatio( float aspectRatio )
+{
+  mCameraAttachment->SetAspectRatio(aspectRatio);
+}
+
+float CameraActor::GetAspectRatio( ) const
+{
+  return mCameraAttachment->GetAspectRatio();
+}
+
+void CameraActor::SetNearClippingPlane( float nearClippingPlane )
+{
+  mCameraAttachment->SetNearClippingPlane(nearClippingPlane);
+}
+
+float CameraActor::GetNearClippingPlane( ) const
+{
+  return mCameraAttachment->GetNearClippingPlane();
+}
+
+void CameraActor::SetFarClippingPlane( float farClippingPlane )
+{
+  mCameraAttachment->SetFarClippingPlane(farClippingPlane);
+}
+
+float CameraActor::GetFarClippingPlane( ) const
+{
+  return mCameraAttachment->GetFarClippingPlane();
+}
+
+void CameraActor::SetTargetPosition(const Vector3& target)
+{
+  mCameraAttachment->SetTargetPosition(target);
+}
+
+Vector3 CameraActor::GetTargetPosition() const
+{
+  return mCameraAttachment->GetTargetPosition();
+}
+
+void CameraActor::SetInvertYAxis(bool invertYAxis)
+{
+  mCameraAttachment->SetInvertYAxis(invertYAxis);
+}
+
+bool CameraActor::GetInvertYAxis() const
+{
+  return mCameraAttachment->GetInvertYAxis();
+}
+
+void CameraActor::SetPerspectiveProjection( const Size& size, const Vector2& stereoBias /* = Vector2::ZERO */ )
+{
+  float width = size.width;
+  float height = size.height;
+
+  if( Size::ZERO == size )
+  {
+    StagePtr stage = Stage::GetCurrent();
+    if( stage )
+    {
+      const Size& stageSize = stage->GetSize();
+
+      width = stageSize.width;
+      height = stageSize.height;
+    }
+  }
+
+  if( ( width < Math::MACHINE_EPSILON_1000 ) || ( height < Math::MACHINE_EPSILON_1000 ) )
+  {
+    // On the stage initialization this method is called but the size has not been set.
+    // There is no point to set any value if width or height is zero.
+    return;
+  }
+
+  float nearClippingPlane;
+  float farClippingPlane;
+  float cameraZ;
+  CalculateClippingAndZ( width, height, nearClippingPlane, farClippingPlane, cameraZ );
+
+  // calculate the position of the camera to have the desired aspect ratio
+  const float fieldOfView = 2.0f * std::atan( height * 0.5f / cameraZ );
+
+  // unless it is too small, we want at least as much space to the back as we have torwards the front
+  const float minClippingFarPlane = 2.f * nearClippingPlane;
+  if ( farClippingPlane < minClippingFarPlane )
+  {
+    farClippingPlane = minClippingFarPlane;
+  }
+
+  const float aspectRatio = width / height;
+
+  SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
+  SetFieldOfView( fieldOfView );
+  SetNearClippingPlane( nearClippingPlane );
+  SetFarClippingPlane( farClippingPlane );
+  SetAspectRatio( aspectRatio );
+  mCameraAttachment->SetStereoBias( stereoBias );
+  SetZ( cameraZ );
+}
+
+
+void CameraActor::SetOrthographicProjection( const Vector2& size )
+{
+  // Choose near, far and Z parameters to match the SetPerspectiveProjection above.
+  float nearClippingPlane;
+  float farClippingPlane;
+  float cameraZ;
+  CalculateClippingAndZ( size.width, size.height, nearClippingPlane, farClippingPlane, cameraZ );
+  SetOrthographicProjection( -size.x*0.5f, size.x*0.5f, size.y*0.5f, -size.y*0.5f,
+                             nearClippingPlane, farClippingPlane );
+  SetZ( cameraZ );
+}
+
+void CameraActor::SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
+{
+  mCameraAttachment->SetLeftClippingPlane(left);
+  mCameraAttachment->SetRightClippingPlane(right);
+  mCameraAttachment->SetTopClippingPlane(top);
+  mCameraAttachment->SetBottomClippingPlane(bottom);
+  SetNearClippingPlane( near );
+  SetFarClippingPlane( far );
+  SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
+}
+
+bool CameraActor::BuildPickingRay( const Vector2& screenCoordinates,
+                                   const Viewport& viewport,
+                                   Vector4& rayOrigin,
+                                   Vector4& rayDirection )
+{
+  bool success = true;
+  if( GetProjectionMode() == Dali::Camera::PERSPECTIVE_PROJECTION )
+  {
+    // Build a picking ray in the world reference system.
+    // ray starts from the camera world position
+    rayOrigin = mNode->GetWorldPosition( GetEventThreadServices().GetEventBufferIndex() );
+    rayOrigin.w = 1.0f;
+
+    // Transform the touch point from the screen coordinate system to the world coordinates system.
+    Vector4 near( screenCoordinates.x - viewport.x, viewport.height - (screenCoordinates.y - viewport.y), 0.f, 1.f );
+    if( !Unproject( near, mCameraAttachment->GetInverseViewProjectionMatrix(), viewport.width, viewport.height, near ) )
+    {
+      // unproject failed so no picking ray possible
+      success = false;
+    }
+
+    // Compute the ray's director vector.
+    rayDirection.x = near.x - rayOrigin.x;
+    rayDirection.y = near.y - rayOrigin.y;
+    rayDirection.z = near.z - rayOrigin.z;
+    rayDirection.Normalize();
+    rayDirection.w = 1.f;
+  }
+  else
+  {
+    float nearPlaneDistance = GetNearClippingPlane();
+    BuildOrthoPickingRay( GetViewMatrix(),
+                          GetProjectionMatrix(),
+                          viewport, screenCoordinates.x,
+                          screenCoordinates.y,
+                          rayOrigin,
+                          rayDirection,
+                          nearPlaneDistance );
+  }
+
+  return success;
+}
+
+const Matrix& CameraActor::GetViewMatrix() const
+{
+  if ( OnStage() )
+  {
+    return mCameraAttachment->GetViewMatrix();
+  }
+  else
+  {
+    return Matrix::IDENTITY;
+  }
+}
+
+const Matrix& CameraActor::GetProjectionMatrix() const
+{
+  if ( OnStage() )
+  {
+    return mCameraAttachment->GetProjectionMatrix();
+  }
+  else
+  {
+    return Matrix::IDENTITY;
+  }
+}
+
+unsigned int CameraActor::GetDefaultPropertyCount() const
+{
+  return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
+}
+
+void CameraActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
+
+  indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
+
+  int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
+  {
+    indices.PushBack( index );
+  }
+}
+
+bool CameraActor::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyWritable( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].writable;
+}
+
+bool CameraActor::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAnimatable( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].animatable;
+}
+
+bool CameraActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAConstraintInput( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX].constraintInput;
+}
+
+Property::Type CameraActor::GetDefaultPropertyType( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::GetDefaultPropertyType( index );
+  }
+  else
+  {
+    index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+
+    if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+    {
+      return DEFAULT_PROPERTY_DETAILS[index].type;
+    }
+    else
+    {
+      // index out-of-bounds
+      return Property::NONE;
+    }
+  }
+}
+
+const char* CameraActor::GetDefaultPropertyName( Property::Index index ) const
+{
+  if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
+  {
+    return Actor::GetDefaultPropertyName(index);
+  }
+  else
+  {
+    index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+
+    if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+    {
+      return DEFAULT_PROPERTY_DETAILS[index].name;
+    }
+    return NULL;
+  }
+}
+
+Property::Index CameraActor::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in current class' default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
+    {
+      index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+      break;
+    }
+  }
+
+  // If not found, check in base class
+  if( Property::INVALID_INDEX == index )
+  {
+    index = Actor::GetDefaultPropertyIndex( name );
+  }
+
+  return index;
+}
+
+void CameraActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
+  {
+    Actor::SetDefaultProperty(index, propertyValue);
+  }
+  else
+  {
+    DALI_ASSERT_DEBUG(mCameraAttachment && "where is the camera?");
+    switch(index)
+    {
+      case Dali::CameraActor::Property::TYPE:
+      {
+        std::string s( propertyValue.Get<std::string>() );
+        if(s == "LOOK_AT_TARGET")
+        {
+          mCameraAttachment->SetType(Dali::Camera::LOOK_AT_TARGET);
+        }
+        else if(s == "FREE_LOOK")
+        {
+          mCameraAttachment->SetType(Dali::Camera::FREE_LOOK);
+        }
+        else
+        {
+          DALI_LOG_WARNING("Unknown camera type\n");
+        }
+        break;
+      }
+      case Dali::CameraActor::Property::PROJECTION_MODE:
+      {
+        std::string s(propertyValue.Get<std::string>());
+        if(s == "PERSPECTIVE_PROJECTION")
+        {
+          mCameraAttachment->SetProjectionMode(Dali::Camera::PERSPECTIVE_PROJECTION);
+        }
+        else if(s == "ORTHOGRAPHIC_PROJECTION")
+        {
+          mCameraAttachment->SetProjectionMode(Dali::Camera::ORTHOGRAPHIC_PROJECTION);
+        }
+        else
+        {
+          DALI_LOG_WARNING("Unknown projection mode\n");
+        }
+        break;
+      }
+      case Dali::CameraActor::Property::FIELD_OF_VIEW:
+      {
+        mCameraAttachment->SetFieldOfView(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::ASPECT_RATIO:
+      {
+        mCameraAttachment->SetAspectRatio(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetLeftClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetRightClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetTopClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetBottomClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetNearClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
+      {
+        mCameraAttachment->SetFarClippingPlane(propertyValue.Get<float>());
+        break;
+      }
+      case Dali::CameraActor::Property::TARGET_POSITION:
+      {
+        mCameraAttachment->SetTargetPosition(propertyValue.Get<Vector3>());
+        break;
+      }
+      case Dali::CameraActor::Property::PROJECTION_MATRIX:
+      {
+        DALI_LOG_WARNING("projection-matrix property is not animatable \n");
+        break;
+      }
+      case Dali::CameraActor::Property::VIEW_MATRIX:
+      {
+        DALI_LOG_WARNING("view-matrix property is not animatable \n");
+        break;
+      }
+      case Dali::CameraActor::Property::INVERT_Y_AXIS:
+      {
+        mCameraAttachment->SetInvertYAxis(propertyValue.Get<bool>());
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING("Unknown property (%d)\n", index);
+        break;
+      }
+    } // switch(index)
+
+  } // else
+}
+
+Property::Value CameraActor::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value ret;
+  if(index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
+  {
+    ret = Actor::GetDefaultProperty(index);
+  }
+  else
+  {
+    DALI_ASSERT_DEBUG(mCameraAttachment && "where is the camera?");
+    switch(index)
+    {
+      case Dali::CameraActor::Property::TYPE:
+      {
+        if(mCameraAttachment->GetType() == Dali::Camera::LOOK_AT_TARGET)
+        {
+          ret = "LOOK_AT_TARGET";
+        }
+        else if(mCameraAttachment->GetType() == Dali::Camera::FREE_LOOK)
+        {
+          ret = "FREE_LOOK";
+        }
+        else
+        {
+          ret = "";
+          DALI_ASSERT_DEBUG("Unknown camera type\n");
+        }
+        break;
+      }
+      case Dali::CameraActor::Property::PROJECTION_MODE:
+      {
+        if(mCameraAttachment->GetProjectionMode() == Dali::Camera::PERSPECTIVE_PROJECTION)
+        {
+          ret = "PERSPECTIVE_PROJECTION";
+        }
+        else if(mCameraAttachment->GetProjectionMode() == Dali::Camera::ORTHOGRAPHIC_PROJECTION)
+        {
+          ret = "ORTHOGRAPHIC_PROJECTION";
+        }
+        else
+        {
+          ret = "";
+          DALI_ASSERT_DEBUG("Unknown projection mode\n");
+        }
+        break;
+      }
+      case Dali::CameraActor::Property::FIELD_OF_VIEW:
+      {
+        ret = mCameraAttachment->GetFieldOfView();
+        break;
+      }
+      case Dali::CameraActor::Property::ASPECT_RATIO:
+      {
+        ret = mCameraAttachment->GetAspectRatio();
+        break;
+      }
+      case Dali::CameraActor::Property::LEFT_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetLeftClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::RIGHT_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetRightClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::TOP_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetTopClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::BOTTOM_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetBottomClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::NEAR_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetNearClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::FAR_PLANE_DISTANCE:
+      {
+        ret = mCameraAttachment->GetFarClippingPlane();
+        break;
+      }
+      case Dali::CameraActor::Property::TARGET_POSITION:
+      {
+        ret = mCameraAttachment->GetTargetPosition();
+        break;
+      }
+      case Dali::CameraActor::Property::PROJECTION_MATRIX:
+      {
+        ret = mCameraAttachment->GetProjectionMatrix();
+        break;
+      }
+      case Dali::CameraActor::Property::VIEW_MATRIX:
+      {
+        ret = mCameraAttachment->GetViewMatrix();
+        break;
+      }
+      case Dali::CameraActor::Property::INVERT_Y_AXIS:
+      {
+        ret = mCameraAttachment->GetInvertYAxis();
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING("Unknown property (%d)\n", index);
+        break;
+      }
+    } // switch(index)
+  }
+
+  return ret;
+}
+
+const SceneGraph::PropertyBase* CameraActor::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
+
+  const SceneGraph::PropertyBase* property( NULL );
+
+  // This method should only return a property of an object connected to the scene-graph
+  if ( !OnStage() )
+  {
+    return property;
+  }
+
+  // let actor handle animatable properties, we have no animatable properties
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    property = Actor::GetSceneObjectAnimatableProperty(index);
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* CameraActor::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property( NULL );
+
+  // This method should only return a property of an object connected to the scene-graph
+  if ( !OnStage() )
+  {
+    return property;
+  }
+
+  // if its an actor default property or a custom property (actor already handles custom properties)
+  if( ( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT ) || ( index >= DEFAULT_PROPERTY_MAX_COUNT ) )
+  {
+    property = Actor::GetSceneObjectInputProperty(index);
+  }
+  else
+  {
+    switch( index )
+    {
+      case Dali::CameraActor::Property::PROJECTION_MATRIX:
+      {
+        property = mCameraAttachment->GetProjectionMatrixProperty();
+        break;
+      }
+      case Dali::CameraActor::Property::VIEW_MATRIX:
+      {
+        property = mCameraAttachment->GetViewMatrixProperty();
+        break;
+      }
+      default:
+        DALI_LOG_WARNING("Not an input property (%d)\n", index);
+        break;
+    }
+  }
+
+  return property;
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/camera-actor-impl.h b/dali/internal/event/actors/camera-actor-impl.h
new file mode 100644 (file)
index 0000000..3cd8d59
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef __DALI_INTERNAL_CAMERA_ACTOR_H__
+#define __DALI_INTERNAL_CAMERA_ACTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * An actor with a conveniently pre-attached CameraAttachment.
+ */
+class CameraActor : public Actor
+{
+public:
+
+  /**
+   * Create an initialised camera actor.
+   *
+   * Sets the default camera perspective projection for the given canvas size. @see SetPerspectiveProjection().
+   *
+   * @param[in] size The canvas size.
+   *
+   * @return A smart-pointer to a newly allocated camera actor.
+   */
+  static CameraActorPtr New( const Size& size );
+
+  /**
+   * @copydoc Dali::Actor::OnInitialize
+   */
+  void OnInitialize();
+
+  /**
+   * Retrieve the camera attachment.
+   * @return The attachment.
+   */
+  CameraAttachment& GetCameraAttachment()
+  {
+    return *mCameraAttachment;
+  }
+
+  /**
+   * @copydoc Dali::CameraActor::SetType
+   */
+  void SetType( Dali::Camera::Type type );
+
+  /**
+   * @copydoc Dali::CameraActor::GetType
+   */
+  Dali::Camera::Type GetType() const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetProjectionMode
+   */
+  void SetProjectionMode( Dali::Camera::ProjectionMode mode );
+
+  /**
+   * @copydoc Dali::CameraActor::GetProjectionMode
+   */
+  Dali::Camera::ProjectionMode GetProjectionMode() const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetFieldOfView
+   */
+  void SetFieldOfView( float fieldOfView );
+
+  /**
+   * @copydoc Dali::CameraActor::GetFieldOfView
+   */
+  float GetFieldOfView( ) const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetAspectRatio
+   */
+  void SetAspectRatio( float aspectRatio );
+
+  /**
+   * @copydoc Dali::CameraActor::GetAspectRatio
+   */
+  float GetAspectRatio( ) const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetNearClippingPlane
+   */
+  void SetNearClippingPlane( float nearClippingPlane );
+
+  /**
+   * @copydoc Dali::CameraActor::GetNearClippingPlane
+   */
+  float GetNearClippingPlane( ) const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetFarClippingPlane
+   */
+  void SetFarClippingPlane( float farClippingPlane );
+
+  /**
+   * @copydoc Dali::CameraActor::GetFarClippingPlane
+   */
+  float GetFarClippingPlane( ) const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetTargetPosition
+   */
+  void SetTargetPosition( const Vector3& targetPosition );
+
+  /**
+   * @copydoc Dali::CameraActor::GetTargetPosition
+   */
+  Vector3 GetTargetPosition() const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetInvertYAxis
+   */
+  void SetInvertYAxis(bool invertYAxis);
+
+  /**
+   * @copydoc Dali::CameraActor::GetCurrentInvertYAxis
+   */
+  bool GetInvertYAxis() const;
+
+  /**
+   * @copydoc Dali::CameraActor::SetPerspectiveProjection()
+   * @param[in] stereoBias The frustum horizontal and vertical offset for stereoscopic cameras
+   */
+  void SetPerspectiveProjection( const Size& size, const Vector2& stereoBias = Vector2::ZERO );
+
+  /**
+   * @copydoc Dali::CameraActor::SetOrthographicProjection(const Vector2& size);
+   */
+  void SetOrthographicProjection( const Vector2& size );
+
+  /**
+   * @copydoc Dali::CameraActor::SetOrthographicProjection(float left, float right, float top, float bottom, float near, float far);
+   */
+  void SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far );
+
+  /**
+   * Build a picking ray with this camera and given screen coordinates
+   * @param [in] screenCoordinates the ray passed through
+   * @param [in] viewport to use
+   * @param [out] rayOrigin for the picking ray
+   * @param [out] rayDirection for the picking ray
+   * @return true if the building was successful, false if its not possible (camera is not valid for hit testing)
+   */
+  bool BuildPickingRay( const Vector2& screenCoordinates, const Viewport& viewport, Vector4& rayOrigin, Vector4& rayDirection );
+
+  /**
+   * Retrieve the view-matrix; This will only be valid when the actor is on-stage.
+   * @return The view-matrix.
+   */
+  const Matrix& GetViewMatrix() const;
+
+  /**
+   * Retrieve the projection-matrix; This will only be valid when the actor is on-stage.
+   * @return The projection-matrix.
+   */
+  const Matrix& GetProjectionMatrix() const;
+
+public: // properties
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const;
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue );
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * copydoc Dali::Internal::Object
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const ;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+protected:
+
+  /**
+   * Protected constructor; see also CameraActor::New()
+   */
+  CameraActor();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~CameraActor();
+
+private:
+
+  CameraAttachmentPtr mCameraAttachment;
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::CameraActor& GetImplementation(Dali::CameraActor& camera)
+{
+  DALI_ASSERT_ALWAYS(camera && "Camera handle is empty");
+
+  BaseObject& handle = camera.GetBaseObject();
+
+  return static_cast<Internal::CameraActor&>(handle);
+}
+
+inline const Internal::CameraActor& GetImplementation(const Dali::CameraActor& camera)
+{
+  DALI_ASSERT_ALWAYS(camera && "Camera handle is empty");
+
+  const BaseObject& handle = camera.GetBaseObject();
+
+  return static_cast<const Internal::CameraActor&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CAMERA_ACTOR_H__
diff --git a/dali/internal/event/actors/custom-actor-internal.cpp b/dali/internal/event/actors/custom-actor-internal.cpp
new file mode 100644 (file)
index 0000000..acfd82c
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/custom-actor-internal.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CustomActorPtr CustomActor::New(CustomActorImpl& extension)
+{
+  CustomActorPtr actor(new CustomActor(extension));
+
+  // Second-phase construction
+  extension.Initialize(*actor);
+  actor->Initialize();
+
+  return actor;
+}
+
+CustomActor::CustomActor(CustomActorImpl& extension)
+: Actor( Actor::BASIC ),
+  mImpl( &extension )
+{
+  mDerivedRequiresTouch = extension.RequiresTouchEvents();
+  mDerivedRequiresHover = extension.RequiresHoverEvents();
+  mDerivedRequiresWheelEvent = extension.RequiresWheelEvents();
+  SetRelayoutEnabled( extension.IsRelayoutEnabled() );
+}
+
+CustomActor::~CustomActor()
+{
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/custom-actor-internal.h b/dali/internal/event/actors/custom-actor-internal.h
new file mode 100644 (file)
index 0000000..f4bef9f
--- /dev/null
@@ -0,0 +1,273 @@
+#ifndef __DALI_INTERNAL_CUSTOM_ACTOR_H__
+#define __DALI_INTERNAL_CUSTOM_ACTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+#include <dali/public-api/actors/custom-actor.h>
+#include <dali/public-api/animation/animation.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class CustomActor : public Actor
+{
+public:
+
+  /**
+   * Create a new custom actor.
+   * @return A smart-pointer to the newly allocated Actor.
+   */
+  static CustomActorPtr New(CustomActorImpl& extension);
+
+  /**
+   * Retrieve the custom actor implementation.
+   * @return The implementation, or an invalid pointer if no implementation was set.
+   */
+  CustomActorImpl& GetImplementation()
+  {
+    return *mImpl;
+  }
+
+  /**
+   * Retrieve the custom actor implementation.
+   * @return The implementation, or an invalid pointer if no implementation was set.
+   */
+  const CustomActorImpl& GetImplementation() const
+  {
+    return *mImpl;
+  }
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~CustomActor();
+
+private:
+
+  /**
+   * @copydoc Internal::Actor::OnStageConnectionExternal
+   */
+  virtual void OnStageConnectionExternal( int depth )
+  {
+    mImpl->OnStageConnection( depth );
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnStageDisconnectionExternal
+   */
+  virtual void OnStageDisconnectionExternal()
+  {
+    mImpl->OnStageDisconnection();
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnChildAdd
+   */
+  virtual void OnChildAdd(Actor& child)
+  {
+    Dali::Actor handle(&child);
+    mImpl->OnChildAdd(handle);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnChildRemove
+   */
+  virtual void OnChildRemove(Actor& child)
+  {
+    Dali::Actor handle(&child);
+    mImpl->OnChildRemove(handle);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnPropertySet
+   */
+  virtual void OnPropertySet( Property::Index index, Property::Value propertyValue )
+  {
+    mImpl->OnPropertySet(index, propertyValue);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnSizeSet
+   */
+  virtual void OnSizeSet(const Vector3& targetSize)
+  {
+    mImpl->OnSizeSet(targetSize);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnSizeAnimation
+   */
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize)
+  {
+    Dali::Animation animationHandle(&animation);
+    mImpl->OnSizeAnimation(animationHandle, targetSize);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnTouchEvent
+   */
+  virtual bool OnTouchEvent(const TouchEvent& event)
+  {
+    return mImpl->OnTouchEvent(event);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnHoverEvent
+   */
+  virtual bool OnHoverEvent(const HoverEvent& event)
+  {
+    return mImpl->OnHoverEvent(event);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnKeyEvent
+   */
+  virtual bool OnKeyEvent(const KeyEvent& event)
+  {
+    return mImpl->OnKeyEvent(event);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnWheelEvent
+   */
+  virtual bool OnWheelEvent(const WheelEvent& event)
+  {
+    return mImpl->OnWheelEvent(event);
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnRelayout
+   */
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container )
+  {
+    mImpl->OnRelayout( size, container );
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnSetResizePolicy
+   */
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+  {
+    mImpl->OnSetResizePolicy( policy, dimension );
+  }
+
+  /**
+   * @copydoc Internal::Actor::GetNaturalSize
+   */
+  virtual Vector3 GetNaturalSize() const
+  {
+    return mImpl->GetNaturalSize();
+  }
+
+  /**
+   * @copydoc Internal::Actor::CalculateChildSize
+   */
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension )
+  {
+    return mImpl->CalculateChildSize( child, dimension );
+  }
+
+  /**
+   * @copydoc Internal::Actor::GetHeightForWidth
+   */
+  virtual float GetHeightForWidth( float width )
+  {
+    return mImpl->GetHeightForWidth( width );
+  }
+
+  /**
+   * @copydoc Internal::Actor::GetWidthForHeight
+   */
+  virtual float GetWidthForHeight( float height )
+  {
+    return mImpl->GetWidthForHeight( height );
+  }
+
+  /**
+   * @copydoc Internal::Actor::RelayoutDependentOnChildren
+   */
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS )
+  {
+    return mImpl->RelayoutDependentOnChildren( dimension );
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnCalculateRelayoutSize
+   */
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension )
+  {
+    return mImpl->OnCalculateRelayoutSize( dimension );
+  }
+
+  /**
+   * @copydoc Internal::Actor::OnLayoutNegotiated
+   */
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension )
+  {
+    return mImpl->OnLayoutNegotiated( size, dimension );
+  }
+
+  /**
+   * Private constructor; see also CustomActor::New()
+   */
+  CustomActor(CustomActorImpl& extension);
+
+  // Undefined
+  CustomActor(const CustomActor&);
+
+  // Undefined
+  CustomActor& operator=(const CustomActor& rhs);
+
+protected:
+
+  CustomActorImplPtr mImpl;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::CustomActor& GetImpl(Dali::CustomActor& actor)
+{
+  DALI_ASSERT_ALWAYS( actor && "CustomActor handle is empty" );
+
+  BaseObject& handle = actor.GetBaseObject();
+
+  return static_cast<Internal::CustomActor&>(handle);
+}
+
+inline const Internal::CustomActor& GetImpl(const Dali::CustomActor& actor)
+{
+  DALI_ASSERT_ALWAYS( actor && "CustomActor handle is empty" );
+
+  const BaseObject& handle = actor.GetBaseObject();
+
+  return static_cast<const Internal::CustomActor&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CUSTOM_ACTOR_H__
diff --git a/dali/internal/event/actors/image-actor-impl.cpp b/dali/internal/event/actors/image-actor-impl.cpp
new file mode 100644 (file)
index 0000000..5c6b028
--- /dev/null
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/image-actor-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/event/images/image-connector.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+//              Name           Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "pixel-area",   RECTANGLE, true,    false,   true,    Dali::ImageActor::Property::PIXEL_AREA )
+DALI_PROPERTY( "style",        STRING,    true,    false,   true,    Dali::ImageActor::Property::STYLE      )
+DALI_PROPERTY( "border",       VECTOR4,   true,    false,   true,    Dali::ImageActor::Property::BORDER     )
+DALI_PROPERTY( "image",        MAP,       true,    false,   false,   Dali::ImageActor::Property::IMAGE      )
+DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
+
+BaseHandle Create()
+{
+  return Dali::ImageActor::New();
+}
+
+TypeRegistration mType( typeid( Dali::ImageActor ), typeid( Dali::Actor ), Create );
+
+ImageActor::Style StyleEnum(const std::string &s)
+{
+  if(s == "STYLE_NINE_PATCH")
+  {
+    return Dali::ImageActor::STYLE_NINE_PATCH;
+  }
+  else if(s == "STYLE_NINE_PATCH_NO_CENTER")
+  {
+    return Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER;
+  }
+  else // if(s == "QUAD")
+  {
+    return Dali::ImageActor::STYLE_QUAD;
+  }
+}
+
+std::string StyleString(const ImageActor::Style style)
+{
+  if(style == Dali::ImageActor::STYLE_NINE_PATCH)
+  {
+    return "STYLE_NINE_PATCH";
+  }
+  else if(style == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER)
+  {
+    return "STYLE_NINE_PATCH_NO_CENTER";
+  }
+  else // if(s == "QUAD")
+  {
+    return "STYLE_QUAD";
+  }
+}
+}
+
+ImageActorPtr ImageActor::New()
+{
+  ImageActorPtr actor( new ImageActor );
+
+  // Second-phase construction of base class
+  actor->Initialize();
+
+  // Create the attachment
+  actor->mImageAttachment = ImageAttachment::New( actor->GetEventThreadServices(), *actor->mNode );
+  actor->Attach( *actor->mImageAttachment );
+
+  return actor;
+}
+
+void ImageActor::OnInitialize()
+{
+  SetResizePolicy( ResizePolicy::USE_NATURAL_SIZE, Dimension::ALL_DIMENSIONS );
+}
+
+void ImageActor::SetImage( ImagePtr& image )
+{
+  ImagePtr currentImage = mImageAttachment->GetImage();
+  // early exit if it's the same image as we already have
+  if ( currentImage == image )
+  {
+    return;
+  }
+
+  // NOTE! image might be pointing to NULL, which is fine as in that case app wants to just remove the image
+  ImagePtr newImage( image );
+  // if image is not NULL, check for 9 patch
+  if( newImage )
+  {
+    // Automatically convert nine-patch images to cropped bitmap
+    NinePatchImage* ninePatchImage = NinePatchImage::DownCast( image.Get() );
+    if( ninePatchImage )
+    {
+      newImage = ninePatchImage->CreateCroppedBufferImage();
+      SetStyle( Dali::ImageActor::STYLE_NINE_PATCH );
+      SetNinePatchBorder( ninePatchImage->GetStretchBorders(), true );
+    }
+  }
+  // set the actual image (normal or 9 patch) and natural size based on that
+  mImageAttachment->SetImage( newImage );
+
+  RelayoutRequest();
+}
+
+ImagePtr ImageActor::GetImage()
+{
+  return mImageAttachment->GetImage();
+}
+
+void ImageActor::SetPixelArea( const PixelArea& pixelArea )
+{
+  mImageAttachment->SetPixelArea( pixelArea );
+
+  RelayoutRequest();
+}
+
+const ImageActor::PixelArea& ImageActor::GetPixelArea() const
+{
+  return mImageAttachment->GetPixelArea();
+}
+
+bool ImageActor::IsPixelAreaSet() const
+{
+  return mImageAttachment->IsPixelAreaSet();
+}
+
+void ImageActor::ClearPixelArea()
+{
+  mImageAttachment->ClearPixelArea();
+
+  RelayoutRequest();
+}
+
+void ImageActor::SetStyle( Style style )
+{
+  mImageAttachment->SetStyle( style );
+}
+
+ImageActor::Style ImageActor::GetStyle() const
+{
+  return mImageAttachment->GetStyle();
+}
+
+void ImageActor::SetNinePatchBorder( const Vector4& border, bool inPixels )
+{
+  mImageAttachment->SetNinePatchBorder( border, inPixels );
+}
+
+Vector4 ImageActor::GetNinePatchBorder() const
+{
+  return mImageAttachment->GetNinePatchBorder();
+}
+
+ImageAttachment& ImageActor::GetImageAttachment()
+{
+  return *mImageAttachment;
+}
+
+RenderableAttachment& ImageActor::GetRenderableAttachment() const
+{
+  DALI_ASSERT_DEBUG( mImageAttachment && "ImageAttachment missing from ImageActor" );
+  return *mImageAttachment;
+}
+
+ImageActor::ImageActor()
+: Actor( Actor::RENDERABLE )
+{
+}
+
+ImageActor::~ImageActor()
+{
+}
+
+Vector3 ImageActor::GetNaturalSize() const
+{
+  Vector2 naturalSize( CalculateNaturalSize() );
+  return Vector3( naturalSize.width, naturalSize.height, CalculateSizeZ( naturalSize ) );
+}
+
+Vector2 ImageActor::CalculateNaturalSize() const
+{
+  // if no image then natural size is 0
+  Vector2 size( 0.0f, 0.0f );
+
+  ImagePtr image = mImageAttachment->GetImage();
+  if( image )
+  {
+    if( IsPixelAreaSet() )
+    {
+      PixelArea area(GetPixelArea());
+      size.width = area.width;
+      size.height = area.height;
+    }
+    else
+    {
+      size = image->GetNaturalSize();
+    }
+  }
+
+  return size;
+}
+
+void ImageActor::OnStageConnectionInternal()
+{
+}
+
+void ImageActor::OnStageDisconnectionInternal()
+{
+}
+
+unsigned int ImageActor::GetDefaultPropertyCount() const
+{
+  return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
+}
+
+void ImageActor::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
+
+  indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
+
+  int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
+  {
+    indices.PushBack( index );
+  }
+}
+
+bool ImageActor::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyWritable(index);
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].writable;
+  }
+
+  return false;
+}
+
+bool ImageActor::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAnimatable( index );
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
+  }
+
+  return false;
+}
+
+bool ImageActor::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAConstraintInput( index );
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
+  }
+
+  return false;
+}
+
+Property::Type ImageActor::GetDefaultPropertyType( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::GetDefaultPropertyType( index );
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out-of-bounds
+  return Property::NONE;
+}
+
+const char* ImageActor::GetDefaultPropertyName( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT)
+  {
+    return Actor::GetDefaultPropertyName(index);
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out-of-bounds
+  return NULL;
+}
+
+Property::Index ImageActor::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // Don't want to convert rhs to string
+    {
+      index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+      break;
+    }
+  }
+
+  // If not found, check in base class
+  if( Property::INVALID_INDEX == index )
+  {
+    index = Actor::GetDefaultPropertyIndex( name );
+  }
+  return index;
+}
+
+void ImageActor::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    Actor::SetDefaultProperty( index, propertyValue );
+  }
+  else
+  {
+    switch(index)
+    {
+      case Dali::ImageActor::Property::PIXEL_AREA:
+      {
+        SetPixelArea(propertyValue.Get<Rect<int> >());
+        break;
+      }
+      case Dali::ImageActor::Property::STYLE:
+      {
+        SetStyle( StyleEnum( propertyValue.Get<std::string>() ) );
+        break;
+      }
+      case Dali::ImageActor::Property::BORDER:
+      {
+        SetNinePatchBorder( propertyValue.Get<Vector4>(), true /*in pixels*/ );
+        break;
+      }
+      case Dali::ImageActor::Property::IMAGE:
+      {
+        Dali::Image img = Scripting::NewImage( propertyValue );
+        if(img)
+        {
+          ImagePtr image( &GetImplementation(img) );
+          SetImage( image );
+        }
+        else
+        {
+          DALI_LOG_WARNING("Cannot create image from property value\n");
+        }
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING("Unknown property (%d)\n", index);
+        break;
+      }
+    } // switch(index)
+
+  } // else
+}
+
+Property::Value ImageActor::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value ret;
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    ret = Actor::GetDefaultProperty( index );
+  }
+  else
+  {
+    switch( index )
+    {
+      case Dali::ImageActor::Property::PIXEL_AREA:
+      {
+        Rect<int> r = GetPixelArea();
+        ret = r;
+        break;
+      }
+      case Dali::ImageActor::Property::STYLE:
+      {
+        ret = StyleString( GetStyle() );
+        break;
+      }
+      case Dali::ImageActor::Property::BORDER:
+      {
+        ret = GetNinePatchBorder();
+        break;
+      }
+      case Dali::ImageActor::Property::IMAGE:
+      {
+        Property::Map map;
+        Scripting::CreatePropertyMap( Dali::Image( mImageAttachment->GetImage().Get() ), map );
+        ret = Property::Value( map );
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING( "Unknown property (%d)\n", index );
+        break;
+      }
+    } // switch(index)
+  }
+
+  return ret;
+}
+
+
+void ImageActor::SetSortModifier(float modifier)
+{
+  mImageAttachment->SetSortModifier( modifier );
+}
+
+float ImageActor::GetSortModifier() const
+{
+  return mImageAttachment->GetSortModifier();
+}
+
+void ImageActor::SetDepthIndex( int depthIndex )
+{
+   mImageAttachment->SetSortModifier( depthIndex );
+}
+
+int ImageActor::GetDepthIndex() const
+{
+  return static_cast< int >( mImageAttachment->GetSortModifier() );
+}
+
+void ImageActor::SetCullFace(CullFaceMode mode)
+{
+  mImageAttachment->SetCullFace( mode );
+}
+
+CullFaceMode ImageActor::GetCullFace() const
+{
+  return mImageAttachment->GetCullFace();
+}
+
+void ImageActor::SetBlendMode( BlendingMode::Type mode )
+{
+  mImageAttachment->SetBlendMode( mode );
+}
+
+BlendingMode::Type ImageActor::GetBlendMode() const
+{
+  return mImageAttachment->GetBlendMode();
+}
+
+void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba )
+{
+  mImageAttachment->SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
+}
+
+void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                               BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
+{
+  mImageAttachment->SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                                    BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
+{
+  mImageAttachment->GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
+{
+  mImageAttachment->SetBlendEquation( equationRgba, equationRgba );
+}
+
+void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
+{
+  mImageAttachment->SetBlendEquation( equationRgb, equationAlpha );
+}
+
+void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
+{
+  mImageAttachment->GetBlendEquation( equationRgb, equationAlpha );
+}
+
+void ImageActor::SetBlendColor( const Vector4& color )
+{
+  mImageAttachment->SetBlendColor( color );
+}
+
+const Vector4& ImageActor::GetBlendColor() const
+{
+  return mImageAttachment->GetBlendColor();
+}
+
+void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
+{
+  mImageAttachment->SetFilterMode( minFilter, magFilter );
+}
+
+void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
+{
+  return mImageAttachment->GetFilterMode( minFilter, magFilter );
+}
+
+void ImageActor::SetShaderEffect(ShaderEffect& effect)
+{
+  mImageAttachment->SetShaderEffect( effect );
+}
+
+ShaderEffectPtr ImageActor::GetShaderEffect() const
+{
+  return mImageAttachment->GetShaderEffect();
+}
+
+void ImageActor::RemoveShaderEffect()
+{
+  return mImageAttachment->RemoveShaderEffect();
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/image-actor-impl.h b/dali/internal/event/actors/image-actor-impl.h
new file mode 100644 (file)
index 0000000..785216e
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef __DALI_INTERNAL_IMAGE_ACTOR_H__
+#define __DALI_INTERNAL_IMAGE_ACTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actor-attachments/image-attachment-impl.h>
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Image;
+
+/**
+ * An actor which displays an Image object.
+ *
+ * This handles image fade-in if required, waiting for the image to load.
+ *
+ * If a new image is set on the actor, then this ensures that the old image
+ * is displayed until the new image is ready to render to prevent flashing
+ * to the actor color. This will also happen if the image is reloaded.
+ *
+ * This is achieved by using two connector objects to Image: mImageNext and
+ * mImageAttachment's member object. The first one points to the Image object that is going to
+ * be displayed next, the second one to the Image that is currently being displayed.
+ */
+class ImageActor : public Actor
+{
+public:
+
+  typedef Dali::ImageActor::Style Style;
+  typedef Dali::ImageActor::PixelArea PixelArea;
+
+  /**
+   * @brief Create an image actor instance.
+   * @return A smart-pointer to a newly allocated image actor.
+   */
+  static ImageActorPtr New();
+
+  /**
+   * @copydoc Dali::Internal::Actor::OnInitialize
+   */
+  void OnInitialize() ;
+
+  /**
+   * @see Dali::ImageActor::SetImage()
+   * @param[in] ImagePtr reference to the image object to display. Reference to avoid unnecessary increment/decrement reference.
+   */
+  void SetImage( ImagePtr& image );
+
+  /**
+   * Retrieve the image rendered by the actor's attachment.
+   * @return smart pointer to the image or an empty one if no image is assigned
+   */
+  ImagePtr GetImage();
+
+  /**
+   * @copydoc Dali::ImageActor::SetPixelArea()
+   */
+  void SetPixelArea( const PixelArea& pixelArea );
+
+  /**
+   * @copydoc Dali::ImageActor::GetPixelArea()
+   */
+  const PixelArea& GetPixelArea() const;
+
+  /**
+   * @copydoc Dali::ImageActor::IsPixelAreaSet()
+   */
+  bool IsPixelAreaSet() const;
+
+  /**
+   * @copydoc Dali::ImageActor::ClearPixelArea()
+   */
+  void ClearPixelArea();
+
+  /**
+   * @copydoc Dali::ImageActor::SetStyle()
+   */
+  void SetStyle( Style style );
+
+  /**
+   * @copydoc Dali::ImageActor::GetStyle()
+   */
+  Style GetStyle() const;
+
+  /**
+   * @copydoc Dali::ImageActor::SetNinePatchBorder
+   */
+  void SetNinePatchBorder( const Vector4& border, bool inPixels = false );
+
+  /**
+   * @copydoc Dali::ImageActor::GetNinePatchBorder
+   */
+  Vector4 GetNinePatchBorder() const;
+
+  /**
+   * Retrieve the attachment which renders the image.
+   * @return The attachment.
+   */
+  ImageAttachment& GetImageAttachment();
+
+
+  /**
+   * @copydoc Dali::RenderableActor::SetSortModifier()
+   */
+  void SetSortModifier(float modifier);
+
+  /**
+   * @copydoc Dali::RenderableActor::GetSortModifier()
+   */
+  float GetSortModifier() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetDepthIndex()
+   */
+  void SetDepthIndex( int depthIndex );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetDepthIndex()
+   */
+  int GetDepthIndex() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetCullFace()
+   */
+  void SetCullFace(CullFaceMode mode);
+
+  /**
+   * @copydoc Dali::RenderableActor::GetCullFace()
+   */
+  CullFaceMode GetCullFace() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendMode()
+   */
+  void SetBlendMode( BlendingMode::Type mode );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendMode()
+   */
+  BlendingMode::Type GetBlendMode() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgba,   BlendingFactor::Type destFactorRgba );
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendFunc()
+   */
+  void GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgba );
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendEquation()
+   */
+  void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetBlendColor()
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendColor()
+   */
+  const Vector4& GetBlendColor() const;
+
+  /**
+   * @copydoc Dali::RenderableActor::SetFilterMode()
+   */
+  void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetFilterMode()
+   */
+  void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const;
+
+public:
+  /**
+   * @copydoc Actor::SetShaderEffect
+   */
+  virtual void SetShaderEffect(ShaderEffect& effect);
+
+  /**
+   * @copydoc Actor::GetShaderEffect
+   */
+  virtual ShaderEffectPtr GetShaderEffect() const;
+
+  /**
+   * @copydoc Actor::RemoveShaderEffect
+   */
+  virtual void RemoveShaderEffect();
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+public: // From Actor
+
+  /**
+   * @copydoc Dali::Actor::GetNaturalSize()
+   */
+  virtual Vector3 GetNaturalSize() const;
+
+private: // From RenderableActor
+
+  /**
+   * @copydoc RenderableActor::GetRenderableAttachment
+   */
+  virtual RenderableAttachment& GetRenderableAttachment() const;
+
+protected:
+
+  /**
+   * Protected constructor; see also ImageActor::New()
+   */
+  ImageActor();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ImageActor();
+
+private:
+
+  /**
+   * Calculate the natural size of this image actor
+   *
+   * @return Return the natural size as a Vector2
+   */
+  Vector2 CalculateNaturalSize() const;
+
+  /**
+   * From Actor; used to trigger fade-in animations.
+   */
+  virtual void OnStageConnectionInternal();
+
+  /**
+   * From Actor; used to notify Image.
+   */
+  virtual void OnStageDisconnectionInternal();
+
+private:
+
+  ImageAttachmentPtr mImageAttachment; ///< Used to display the image (holds a pointer to currently showed Image)
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ImageActor& GetImplementation(Dali::ImageActor& image)
+{
+  DALI_ASSERT_ALWAYS(image && "Image handle is empty");
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::ImageActor&>(handle);
+}
+
+inline const Internal::ImageActor& GetImplementation(const Dali::ImageActor& image)
+{
+  DALI_ASSERT_ALWAYS(image && "Image handle is empty");
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::ImageActor&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_ACTOR_H__
diff --git a/dali/internal/event/actors/layer-impl.cpp b/dali/internal/event/actors/layer-impl.cpp
new file mode 100644 (file)
index 0000000..f70b3e3
--- /dev/null
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/layer-impl.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/actors/layer-list.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+using Dali::Internal::SceneGraph::UpdateManager;
+
+namespace Dali
+{
+
+namespace
+{
+typedef Dali::Layer::Behavior Behavior;
+
+DALI_ENUM_TO_STRING_TABLE_BEGIN( Behavior )
+DALI_ENUM_TO_STRING( Dali::Layer::LAYER_2D )
+DALI_ENUM_TO_STRING( Dali::Layer::LAYER_3D )
+DALI_ENUM_TO_STRING_TABLE_END( Behavior )
+} // namespace
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+//              Name                Type      writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "clipping-enable",   BOOLEAN,    true,    false,   true,   Dali::Layer::Property::CLIPPING_ENABLE )
+DALI_PROPERTY( "clipping-box",      RECTANGLE,  true,    false,   true,   Dali::Layer::Property::CLIPPING_BOX    )
+DALI_PROPERTY( "behavior",          STRING,     true,    false,   false,  Dali::Layer::Property::BEHAVIOR        )
+DALI_PROPERTY_TABLE_END( DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX )
+
+// Actions
+
+const char* const ACTION_RAISE =           "raise";
+const char* const ACTION_LOWER =           "lower";
+const char* const ACTION_RAISE_TO_TOP =    "raise-to-top";
+const char* const ACTION_LOWER_TO_BOTTOM = "lower-to-bottom";
+
+BaseHandle Create()
+{
+  return Dali::Layer::New();
+}
+
+TypeRegistration mType( typeid( Dali::Layer ), typeid( Dali::Actor ), Create );
+
+TypeAction a1( mType, ACTION_RAISE, &Layer::DoAction );
+TypeAction a2( mType, ACTION_LOWER, &Layer::DoAction );
+TypeAction a3( mType, ACTION_RAISE_TO_TOP, &Layer::DoAction );
+TypeAction a4( mType, ACTION_LOWER_TO_BOTTOM, &Layer::DoAction );
+
+} // unnamed namespace
+
+
+LayerPtr Layer::New()
+{
+  LayerPtr layer( new Layer( Actor::LAYER ) );
+
+  // Second-phase construction
+  layer->Initialize();
+
+  return layer;
+}
+
+LayerPtr Layer::NewRoot( LayerList& layerList, UpdateManager& manager, bool systemLevel )
+{
+  LayerPtr root( new Layer( Actor::ROOT_LAYER ) );
+
+  // Second-phase construction
+  SceneGraph::Layer* layer = static_cast<SceneGraph::Layer*>( root->CreateNode() );
+  InstallRootMessage( manager, *layer, systemLevel ); // Transfer ownership to scene-graph
+
+  // Keep a raw pointer to the layer node.
+  root->mNode = layer;
+
+  // root actor is immediately considered to be on-stage
+  root->mIsOnStage = true;
+
+  // The root actor will not emit a stage connection signal so set the signalled flag here as well
+  root->mOnStageSignalled = true;
+
+  // layer-list must be set for the root layer
+  root->mLayerList = &layerList;
+  layerList.RegisterLayer( *root );
+
+  return root;
+}
+
+Layer::Layer( Actor::DerivedType type )
+: Actor( type ),
+  mLayerList(NULL),
+  mClippingBox(0,0,0,0),
+  mSortFunction(Layer::ZValue),
+  mBehavior(Dali::Layer::LAYER_2D),
+  mIsClipping(false),
+  mDepthTestDisabled(false),
+  mTouchConsumed(false),
+  mHoverConsumed(false)
+{
+}
+
+void Layer::OnInitialize()
+{
+}
+
+Layer::~Layer()
+{
+}
+
+unsigned int Layer::GetDepth() const
+{
+  return mLayerList ? mLayerList->GetDepth( this ) : 0u;
+}
+
+void Layer::Raise()
+{
+  if ( mLayerList )
+  {
+    mLayerList->RaiseLayer(*this);
+  }
+}
+
+void Layer::Lower()
+{
+  if ( mLayerList )
+  {
+    mLayerList->LowerLayer(*this);
+  }
+}
+
+void Layer::RaiseAbove( const Internal::Layer& target )
+{
+  // cannot raise above ourself, both have to be on stage
+  if( ( this != &target ) && OnStage() && target.OnStage() )
+  {
+    // get parameters depth
+    const unsigned int targetDepth = target.GetDepth();
+    if( GetDepth() < targetDepth )
+    {
+      MoveAbove( target );
+    }
+  }
+}
+
+void Layer::LowerBelow( const Internal::Layer& target )
+{
+  // cannot lower below ourself, both have to be on stage
+  if( ( this != &target ) && OnStage() && target.OnStage() )
+  {
+    // get parameters depth
+    const unsigned int targetDepth = target.GetDepth();
+    if( GetDepth() > targetDepth )
+    {
+      MoveBelow( target );
+    }
+  }
+}
+
+void Layer::RaiseToTop()
+{
+  if ( mLayerList )
+  {
+    mLayerList->RaiseLayerToTop(*this);
+  }
+}
+
+void Layer::LowerToBottom()
+{
+  if ( mLayerList )
+  {
+    mLayerList->LowerLayerToBottom(*this);
+  }
+}
+
+void Layer::MoveAbove( const Internal::Layer& target )
+{
+  // cannot raise above ourself, both have to be on stage
+  if( ( this != &target ) && mLayerList && target.OnStage() )
+  {
+    mLayerList->MoveLayerAbove(*this, target );
+  }
+}
+
+void Layer::MoveBelow( const Internal::Layer& target )
+{
+  // cannot lower below ourself, both have to be on stage
+  if( ( this != &target ) && mLayerList && target.OnStage() )
+  {
+    mLayerList->MoveLayerBelow(*this, target );
+  }
+}
+
+void Layer::SetBehavior( Dali::Layer::Behavior behavior )
+{
+  mBehavior = behavior;
+
+  // notify update side object
+  SetBehaviorMessage( GetEventThreadServices(), GetSceneLayerOnStage(), behavior );
+}
+
+void Layer::SetClipping(bool enabled)
+{
+  if (enabled != mIsClipping)
+  {
+    mIsClipping = enabled;
+
+    // layerNode is being used in a separate thread; queue a message to set the value
+    SetClippingMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mIsClipping );
+  }
+}
+
+void Layer::SetClippingBox(int x, int y, int width, int height)
+{
+  if( ( x != mClippingBox.x ) ||
+      ( y != mClippingBox.y ) ||
+      ( width != mClippingBox.width ) ||
+      ( height != mClippingBox.height ) )
+  {
+    // Clipping box is not animatable; this is the most up-to-date value
+    mClippingBox.Set(x, y, width, height);
+
+    // Convert mClippingBox to GL based coordinates (from bottom-left)
+    ClippingBox clippingBox( mClippingBox );
+
+    StagePtr stage = Stage::GetCurrent();
+    if( stage )
+    {
+      clippingBox.y = stage->GetSize().height - clippingBox.y - clippingBox.height;
+
+      // layerNode is being used in a separate thread; queue a message to set the value
+      SetClippingBoxMessage( GetEventThreadServices(), GetSceneLayerOnStage(), clippingBox );
+    }
+  }
+}
+
+void Layer::SetDepthTestDisabled( bool disable )
+{
+  if( disable != mDepthTestDisabled )
+  {
+    mDepthTestDisabled = disable;
+
+    // Send message .....
+    // layerNode is being used in a separate thread; queue a message to set the value
+    SetDepthTestDisabledMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mDepthTestDisabled );
+  }
+}
+
+bool Layer::IsDepthTestDisabled() const
+{
+  return mDepthTestDisabled || (mBehavior == Dali::Layer::LAYER_2D);
+}
+
+void Layer::SetSortFunction(Dali::Layer::SortFunctionType function)
+{
+  if( function != mSortFunction )
+  {
+    mSortFunction = function;
+
+    // layerNode is being used in a separate thread; queue a message to set the value
+    SetSortFunctionMessage( GetEventThreadServices(), GetSceneLayerOnStage(), mSortFunction );
+  }
+}
+
+void Layer::SetTouchConsumed( bool consume )
+{
+  mTouchConsumed = consume;
+}
+
+bool Layer::IsTouchConsumed() const
+{
+  return mTouchConsumed;
+}
+
+void Layer::SetHoverConsumed( bool consume )
+{
+  mHoverConsumed = consume;
+}
+
+bool Layer::IsHoverConsumed() const
+{
+  return mHoverConsumed;
+}
+
+SceneGraph::Node* Layer::CreateNode() const
+{
+  return SceneGraph::Layer::New();
+}
+
+void Layer::OnStageConnectionInternal()
+{
+  if ( !mIsRoot )
+  {
+    DALI_ASSERT_DEBUG( NULL == mLayerList );
+
+    // Find the ordered layer-list
+    // This is different for Layers added via Integration::GetSystemOverlay()
+    for ( Actor* parent = mParent; parent != NULL; parent = parent->GetParent() )
+    {
+      if( parent->IsLayer() )
+      {
+        Layer* parentLayer = static_cast< Layer* >( parent ); // cheaper than dynamic_cast
+        mLayerList = parentLayer->mLayerList;
+      }
+    }
+  }
+
+  DALI_ASSERT_DEBUG( NULL != mLayerList );
+  mLayerList->RegisterLayer( *this );
+}
+
+void Layer::OnStageDisconnectionInternal()
+{
+  mLayerList->UnregisterLayer(*this);
+
+  // mLayerList is only valid when on-stage
+  mLayerList = NULL;
+}
+
+const SceneGraph::Layer& Layer::GetSceneLayerOnStage() const
+{
+  DALI_ASSERT_DEBUG( mNode != NULL );
+  return dynamic_cast< const SceneGraph::Layer& >( *mNode );
+}
+
+unsigned int Layer::GetDefaultPropertyCount() const
+{
+  return Actor::GetDefaultPropertyCount() + DEFAULT_PROPERTY_COUNT;
+}
+
+void Layer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  Actor::GetDefaultPropertyIndices( indices ); // Actor class properties
+  indices.Reserve( indices.Size() + DEFAULT_PROPERTY_COUNT );
+
+  int index = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
+  {
+    indices.PushBack( index );
+  }
+}
+
+bool Layer::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyWritable( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].writable;
+}
+
+bool Layer::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAnimatable( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].animatable;
+}
+
+bool Layer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::IsDefaultPropertyAConstraintInput( index );
+  }
+
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX ].constraintInput;
+}
+
+Property::Type Layer::GetDefaultPropertyType( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::GetDefaultPropertyType( index );
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out-of-bounds
+  return Property::NONE;
+}
+
+const char* Layer::GetDefaultPropertyName( Property::Index index ) const
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    return Actor::GetDefaultPropertyName( index );
+  }
+
+  index -= DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  return NULL;
+}
+
+Property::Index Layer::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in current class' default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[i];
+    if( 0 == name.compare( property->name ) ) // dont want to convert rhs to string
+    {
+      index = i + DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX;
+      break;
+    }
+  }
+  if( Property::INVALID_INDEX == index )
+  {
+    // If not found, check in base class
+    index = Actor::GetDefaultPropertyIndex( name );
+  }
+
+  return index;
+}
+
+void Layer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    Actor::SetDefaultProperty( index, propertyValue );
+  }
+  else
+  {
+    switch( index )
+    {
+      case Dali::Layer::Property::CLIPPING_ENABLE:
+      {
+        SetClipping( propertyValue.Get<bool>() );
+        break;
+      }
+      case Dali::Layer::Property::CLIPPING_BOX:
+      {
+        Rect<int> clippingBox( propertyValue.Get<Rect<int> >() );
+        SetClippingBox( clippingBox.x, clippingBox.y, clippingBox.width, clippingBox.height );
+        break;
+      }
+      case Dali::Layer::Property::BEHAVIOR:
+      {
+        Behavior behavior(Dali::Layer::LAYER_2D);
+        if( Scripting::GetEnumeration< Behavior >( propertyValue.Get< std::string >().c_str(), BehaviorTable, BehaviorTableCount, behavior ) )
+        {
+          SetBehavior( behavior );
+        }
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING( "Unknown property (%d)\n", index );
+        break;
+      }
+    } // switch(index)
+
+  } // else
+}
+
+Property::Value Layer::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value ret;
+  if( index < DEFAULT_ACTOR_PROPERTY_MAX_COUNT )
+  {
+    ret = Actor::GetDefaultProperty( index );
+  }
+  else
+  {
+    switch( index )
+    {
+      case Dali::Layer::Property::CLIPPING_ENABLE:
+      {
+        ret = mIsClipping;
+        break;
+      }
+      case Dali::Layer::Property::CLIPPING_BOX:
+      {
+        ret = mClippingBox;
+        break;
+      }
+      case Dali::Layer::Property::BEHAVIOR:
+      {
+        ret = Scripting::GetLinearEnumerationName< Behavior >( GetBehavior(), BehaviorTable, BehaviorTableCount );
+        break;
+      }
+      default:
+      {
+        DALI_LOG_WARNING( "Unknown property (%d)\n", index );
+        break;
+      }
+    } // switch(index)
+  }
+
+  return ret;
+}
+
+bool Layer::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& /*attributes*/ )
+{
+  bool done = false;
+  Layer* layer = dynamic_cast<Layer*>( object );
+
+  if( layer )
+  {
+    if( 0 == actionName.compare( ACTION_RAISE ) )
+    {
+      layer->Raise();
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_LOWER ) )
+    {
+      layer->Lower();
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_RAISE_TO_TOP ) )
+    {
+      layer->RaiseToTop();
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_LOWER_TO_BOTTOM ) )
+    {
+      layer->LowerToBottom();
+      done = true;
+    }
+  }
+
+  return done;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/layer-impl.h b/dali/internal/event/actors/layer-impl.h
new file mode 100644 (file)
index 0000000..0e97f3a
--- /dev/null
@@ -0,0 +1,338 @@
+#ifndef __DALI_INTERNAL_LAYER_H__
+#define __DALI_INTERNAL_LAYER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class LayerList;
+
+namespace SceneGraph
+{
+class UpdateManager;
+class Layer;
+}
+
+typedef Dali::ClippingBox ClippingBox;
+
+class Layer : public Actor
+{
+public:
+
+  /**
+   * @copydoc Dali::Layer::ZValue(const Vector3&, float)
+   *
+   * This is the default sorting function.
+   * It is useful for 2D user interfaces, and it's used to sort translucent renderers.
+   *
+   * Only the Z signed distance from the camera is considererd, lower values will be drawn on top.
+   *
+   * @param[in] position     position of actor in view space
+   * @return depth
+   */
+  static float ZValue(const Vector3& position)
+  {
+    // inlined so we avoid a function call when sorting renderers
+    return position.z;
+  }
+
+  /**
+   * Create a new Layer.
+   * @return A smart-pointer to the newly allocated Layer.
+   */
+  static LayerPtr New();
+
+  /**
+   * Create a new root layer; this is typically owned by the stage.
+   * @param[in] layerList The layer will be added to this ordered list.
+   * @param[in] manager The update manager to install a root node with.
+   * @param[in] systemLevel True if using the SystemOverlay API; see Integration::GetSystemOverlay() for more details.
+   * @return A smart-pointer to the newly allocated Actor.
+   */
+  static LayerPtr NewRoot( LayerList& layerList, SceneGraph::UpdateManager& manager, bool systemLevel );
+
+  /**
+   * @copydoc Dali::Internal::Actor::OnInitialize
+   */
+  void OnInitialize();
+
+  /**
+   * Query the current depth of the layer
+   */
+  unsigned int GetDepth() const;
+
+  /**
+   * @copydoc Dali::Layer::Raise
+   */
+  void Raise();
+
+  /**
+   * @copydoc Dali::Layer::Lower
+   */
+  void Lower();
+
+  /**
+   * @copydoc Dali::Layer::RaiseAbove
+   */
+  void RaiseAbove( const Internal::Layer& target );
+
+  /**
+   * @copydoc Dali::Layer::LowerBelow
+   */
+  void LowerBelow( const Internal::Layer& target );
+
+  /**
+   * @copydoc Dali::Layer::RaiseToTop
+   */
+  void RaiseToTop();
+
+  /**
+   * @copydoc Dali::Layer::LowerToBottom
+   */
+  void LowerToBottom();
+
+  /**
+   * @copydoc Dali::Layer::MoveAbove
+   */
+  void MoveAbove( const Internal::Layer& target );
+
+  /**
+   * @copydoc Dali::Layer::MoveAbove
+   */
+  void MoveBelow( const Internal::Layer& target );
+
+  /**
+   * @copydoc Dali::Layer::SetClipping()
+   */
+  void SetClipping(bool enabled);
+
+  /**
+   * @copydoc Dali::Layer::IsClipping()
+   */
+  bool IsClipping() const
+  {
+    return mIsClipping; // Actor-side has most up-to-date value
+  }
+
+  /**
+   * @copydoc Dali::Layer::SetClippingBox()
+   */
+  void SetClippingBox(int x, int y, int width, int height);
+
+  /**
+   * @copydoc Dali::Layer::GetClippingBox()
+   */
+  const Dali::ClippingBox& GetClippingBox() const
+  {
+    return mClippingBox; // Actor-side has most up-to-date value
+  }
+
+  /**
+   * @copydoc Dali::Layer::SetBehavior()
+   */
+  void SetBehavior( Dali::Layer::Behavior behavior );
+
+  /**
+   * @copydoc Dali::Layer::GetBehavior()
+   */
+  Dali::Layer::Behavior GetBehavior() const
+  {
+    return mBehavior;
+  }
+
+  /**
+   * @copydoc Dali::Layer::SetDepthTestDisabled()
+   */
+  void SetDepthTestDisabled( bool disable );
+
+  /**
+   * @copydoc Dali::Layer::IsDepthTestDisabled()
+   */
+  bool IsDepthTestDisabled() const;
+
+  /**
+   * @copydoc Dali::Layer::SetSortFunction()
+   */
+  void SetSortFunction(Dali::Layer::SortFunctionType function);
+
+  /**
+   * @copydoc Dali::Layer::SetTouchConsumed()
+   */
+  void SetTouchConsumed( bool consume );
+
+  /**
+   * @copydoc Dali::Layer::IsTouchConsumed()
+   */
+  bool IsTouchConsumed() const;
+
+  /**
+   * @copydoc Dali::Layer::SetHoverConsumed()
+   */
+  void SetHoverConsumed( bool consume );
+
+  /**
+   * @copydoc Dali::Layer::IsHoverConsumed()
+   */
+  bool IsHoverConsumed() const;
+
+  /**
+   * Helper function to get the scene object.
+   * This should only be called by Stage
+   * @return the scene object for the layer.
+   */
+  const SceneGraph::Layer& GetSceneLayerOnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Actor::DoAction()
+   */
+  static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
+
+public: // Default property extensions from Object
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+protected:
+
+  /**
+   * Construct a new layer.
+   * @param[in] type Either Actor::LAYER or Actor::ROOT_LAYER if this is the root actor.
+   */
+  Layer( Actor::DerivedType type );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Layer();
+
+private: // From Actor
+
+  /**
+   * From Actor; create a node to represent the layer in the scene-graph.
+   * @return A newly allocated layer node.
+   */
+  virtual SceneGraph::Node* CreateNode() const;
+
+  /**
+   * From Actor.
+   */
+  virtual void OnStageConnectionInternal();
+
+  /**
+   * From Actor.
+   */
+  virtual void OnStageDisconnectionInternal();
+
+private:
+
+  LayerList* mLayerList; ///< Only valid when layer is on-stage
+
+  // These properties not animatable; the actor side has the most up-to-date values
+  ClippingBox mClippingBox;                     ///< The clipping box, in window coordinates
+  Dali::Layer::SortFunctionType mSortFunction;  ///< Used to sort semi-transparent geometry
+
+  Dali::Layer::Behavior mBehavior;              ///< Behavior of the layer
+
+  bool mIsClipping:1;                           ///< True when clipping is enabled
+  bool mDepthTestDisabled:1;                    ///< Whether depth test is disabled.
+  bool mTouchConsumed:1;                        ///< Whether we should consume touch (including gesture).
+  bool mHoverConsumed:1;                        ///< Whether we should consume hover.
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Layer& GetImplementation(Dali::Layer& layer)
+{
+  DALI_ASSERT_ALWAYS(layer && "Layer handle is empty");
+
+  BaseObject& handle = layer.GetBaseObject();
+
+  return static_cast<Internal::Layer&>(handle);
+}
+
+inline const Internal::Layer& GetImplementation(const Dali::Layer& layer)
+{
+  DALI_ASSERT_ALWAYS(layer && "Layer handle is empty");
+
+  const BaseObject& handle = layer.GetBaseObject();
+
+  return static_cast<const Internal::Layer&>(handle);
+}
+
+} // namespace Dali
+
+
+#endif //__DALI_INTERNAL_LAYER_H__
diff --git a/dali/internal/event/actors/layer-list.cpp b/dali/internal/event/actors/layer-list.cpp
new file mode 100644 (file)
index 0000000..82be760
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/actors/layer-list.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>  // for std::swap
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+typedef std::vector<Layer*> LayerContainer;
+typedef LayerContainer::iterator LayerIter;
+typedef LayerContainer::reverse_iterator ReverseLayerIter;
+
+/**
+ * A private helper template to return an iterator to the layer passed in.
+ * @param[in] first position to start searching from
+ * @param[in] last position to search to
+ * @param[in] layer to search for
+ * @return iterator to layer if found
+ */
+template<class InputIterator> InputIterator Find( InputIterator first, InputIterator last, const Layer& layer )
+{
+  for( ; first != last ; ++first )
+  {
+    if( *first == &layer )
+    {
+      break;
+    }
+ }
+ return first;
+}
+
+} // unnamed namespace
+
+LayerList* LayerList::New( SceneGraph::UpdateManager& updateManager, bool systemLevel )
+{
+  return new LayerList( updateManager, systemLevel );
+}
+
+LayerList::~LayerList()
+{
+}
+
+unsigned int LayerList::GetLayerCount() const
+{
+  return mLayers.size();
+}
+
+Layer* LayerList::GetLayer( unsigned int depth ) const
+{
+  DALI_ASSERT_ALWAYS( depth < mLayers.size() );
+
+  return mLayers[ depth ];
+}
+
+unsigned int LayerList::GetDepth( const Layer* layer ) const
+{
+  for( unsigned int count = 0; count < mLayers.size(); ++count )
+  {
+    if( layer == mLayers[ count ] )
+    {
+      return count;
+    }
+  }
+  return 0;
+}
+
+void LayerList::RegisterLayer(Layer& layer)
+{
+  DALI_ASSERT_DEBUG(  mLayers.end() == Find( mLayers.begin(), mLayers.end(), layer) );
+  mLayers.push_back(&layer);
+
+  SetLayerDepths();
+}
+
+void LayerList::UnregisterLayer(Layer& layer)
+{
+  // Find the layer...
+  LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer);
+  DALI_ASSERT_DEBUG(iter != mLayers.end());
+
+  // ...and remove it
+  mLayers.erase(iter);
+
+  SetLayerDepths();
+}
+
+void LayerList::RaiseLayer(Layer& raiseLayer)
+{
+  LayerIter iter = Find( mLayers.begin(), mLayers.end(), raiseLayer);
+
+  if (iter   != mLayers.end() &&
+      iter+1 != mLayers.end())
+  {
+    LayerIter nextIter = iter+1;
+
+    // Swap the pointers
+    std::swap(*iter, *nextIter);
+
+    SetLayerDepths();
+  }
+}
+
+void LayerList::LowerLayer(Layer& lowerLayer)
+{
+  ReverseLayerIter iter =  Find( mLayers.rbegin(), mLayers.rend(), lowerLayer);
+
+  if (iter   != mLayers.rend() &&
+      iter+1 != mLayers.rend())
+  {
+    ReverseLayerIter nextIter = iter+1;
+
+    // Swap the pointers
+    std::swap(*iter, *nextIter);
+
+    SetLayerDepths();
+  }
+}
+
+void LayerList::RaiseLayerToTop( const Layer& layer )
+{
+  LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer);
+
+  if (iter   != mLayers.end() &&
+      iter+1 != mLayers.end())
+  {
+    Layer* raised = *iter;
+
+    copy(iter+1, mLayers.end(), iter);
+    mLayers.back() = raised;
+
+    SetLayerDepths();
+  }
+}
+
+void LayerList::LowerLayerToBottom( const Layer& layer )
+{
+  ReverseLayerIter iter =  Find( mLayers.rbegin(), mLayers.rend(), layer);
+
+  if (iter   != mLayers.rend() &&
+      iter+1 != mLayers.rend())
+  {
+    Layer* lowered = *iter;
+
+    copy(iter+1, mLayers.rend(), iter);
+    mLayers.front() = lowered;
+
+    SetLayerDepths();
+  }
+}
+
+void LayerList::MoveLayerAbove( const Layer& layer, const Layer& target )
+{
+  // check if it already is
+  if( layer.GetDepth() == ( target.GetDepth() + 1 ) )
+  {
+    return;
+  }
+
+  // find the layer to move
+  LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer);
+
+  if( iter != mLayers.end() )
+  {
+    Layer* moved = *iter;
+    mLayers.erase( iter );
+    // find target
+    LayerIter iterT = Find( mLayers.begin(), mLayers.end(), target);
+    // if target is not found there's a programming error somewhere
+    DALI_ASSERT_DEBUG( iterT != mLayers.end() );
+    // iterT might be the last
+    if( ( iterT+1 ) == mLayers.end() )
+    {
+      mLayers.push_back( moved );
+    }
+    else
+    {
+      mLayers.insert( iterT+1, moved );
+    }
+
+    SetLayerDepths();
+  }
+}
+
+void LayerList::MoveLayerBelow( const Layer& layer, const Layer& target )
+{
+  // check if it already is in correct order
+  if( layer.GetDepth() == ( target.GetDepth() - 1 ) )
+  {
+    return;
+  }
+
+  // find the layer to move
+  LayerIter iter = Find( mLayers.begin(), mLayers.end(), layer);
+  if( iter != mLayers.end() )
+  {
+    Layer* moved = *iter;
+    mLayers.erase( iter );
+    // find target
+    LayerIter iterT = Find( mLayers.begin(), mLayers.end(), target);
+    // if target is not found there's a programming error somewhere
+    DALI_ASSERT_DEBUG( iterT != mLayers.end() );
+    mLayers.insert( iterT, moved );
+
+    SetLayerDepths();
+  }
+}
+
+LayerList::LayerList( SceneGraph::UpdateManager& updateManager, bool systemLevel )
+: mUpdateManager( updateManager ),
+  mIsSystemLevel( systemLevel )
+{
+}
+
+void LayerList::SetLayerDepths()
+{
+  // we've got a list of on-stage layers on actor side, need to get their stage
+  // pointers so we can send them to the update manager
+  std::vector< SceneGraph::Layer* > layers;
+  layers.reserve( mLayers.size() );
+
+  // Set the layers (possibly) new depth
+  for (LayerIter iter = mLayers.begin(); iter != mLayers.end(); ++iter)
+  {
+    SceneGraph::Layer* layerPtr = const_cast< SceneGraph::Layer* >( &( (*iter)->GetSceneLayerOnStage() ) );
+    layers.push_back( layerPtr );
+  }
+
+  // Layers are being used in a separate thread; queue a message to set order
+  SetLayerDepthsMessage( mUpdateManager, layers, mIsSystemLevel );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/actors/layer-list.h b/dali/internal/event/actors/layer-list.h
new file mode 100644 (file)
index 0000000..22b5bfc
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef __DALI_INTERNAL_LAYER_LIST_H__
+#define __DALI_INTERNAL_LAYER_LIST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+class Layer;
+
+/**
+ * An ordered list of layers.
+ * Layers are not owned by the LayerList; each layer is responsible for registering & unregistering.
+ * This is used by the Stage, to keep track of layer depths.
+ * A separate LayerList is maintained for actors added via the SystemOverlay::Add().
+ */
+class LayerList
+{
+public:
+
+  /**
+   * Create a new list of layers.
+   * @param[in] updateManager A reference to the update manager.
+   * @param[in] systemLevel True if the layers are added via the SystemOverlay API.
+   */
+  static LayerList* New( SceneGraph::UpdateManager& updateManager, bool systemLevel );
+
+  /**
+   * Non-virtual destructor; not suitable as a base class.
+   */
+  ~LayerList();
+
+  /**
+   * Query the number of layers.
+   * @return The number of layers.
+   */
+  unsigned int GetLayerCount() const;
+
+  /**
+   * Retrieve the layer at a specified depth.
+   * @pre depth is less than layer count; see GetLayerCount().
+   * @param[in] depth The depth.
+   * @return The layer found at the given depth.
+   */
+  Layer* GetLayer( unsigned int depth ) const;
+
+  /**
+   * Gets the depth of a given layer
+   * @param layer which depth to check
+   */
+  unsigned int GetDepth( const Layer* layer ) const;
+
+  /**
+   * Register a layer with the stage.
+   * The stage determines the relative depth of each layer.
+   */
+  void RegisterLayer( Layer& layer );
+
+  /**
+   * Unregister a layer from the stage
+   */
+  void UnregisterLayer(Layer& layer);
+
+  /**
+   * Increment the depth of the layer inside the stage
+   * @pre layer is on stage
+   */
+  void RaiseLayer(Layer& layer);
+
+  /**
+   * Decrement the depth of the layer inside the stage
+   * @pre layer is on stage
+   */
+  void LowerLayer(Layer& layer);
+
+  /**
+   * Raises the layer to the top of the stage
+   * @pre layer is on stage
+   * @param layer to move
+   */
+  void RaiseLayerToTop( const Layer& layer );
+
+  /**
+   * Lowers the layer to the bottom of the stage
+   * @pre layer is on stage
+   * @param layer to move
+   */
+  void LowerLayerToBottom( const Layer& layer );
+
+  /**
+   * Moves the layer above the target layer on the stage
+   * @pre layer is on stage
+   * @pre target is on stage
+   * @param layer to move
+   * @param target to move above of
+   */
+  void MoveLayerAbove( const Layer& layer, const Layer& target );
+
+  /**
+   * Moves the layer below the target layer on the stage
+   * @pre layer is on stage
+   * @pre target is on stage
+   * @param layer to move
+   * @param target to move below of
+   */
+  void MoveLayerBelow( const Layer& layer, const Layer& target );
+
+private:
+
+  /**
+   * Protected constructor; see also LayerList::New().
+   * @param[in] updateManager to send messages.
+   * @param[in] systemLevel True if the layers are added via the SystemOverlay API.
+   */
+  LayerList( SceneGraph::UpdateManager& updateManager, bool systemLevel );
+
+  /**
+   * A private helper method to set the depth for each layer.
+   * Layers have depth which is the same as their ordinal number in the stage container
+   * This method propagates any changes in the layer depths onto the scene graph side
+   */
+  void SetLayerDepths();
+
+private:
+
+  SceneGraph::UpdateManager& mUpdateManager;
+
+  bool mIsSystemLevel; ///< True if the layers are added via the SystemOverlay API.
+
+  typedef std::vector<Layer*> LayerContainer;
+
+  // Layers are not owned by the LayerList.
+  // Each layer is responsible for registering & unregistering before the end of its life-time.
+  LayerContainer mLayers;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_LAYER_LIST_H__
diff --git a/dali/internal/event/animation/animation-impl.cpp b/dali/internal/event/animation/animation-impl.cpp
new file mode 100644 (file)
index 0000000..0c92623
--- /dev/null
@@ -0,0 +1,936 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/public-api/object/property-map.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/time-period.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/animation/animation-playlist.h>
+#include <dali/internal/event/animation/animator-connector.h>
+#include <dali/internal/event/common/notification-manager.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+using Dali::Internal::SceneGraph::UpdateManager;
+using Dali::Internal::SceneGraph::AnimatorBase;
+using Dali::Internal::SceneGraph::Shader;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+static bool SHOW_VALUE = true;
+static bool HIDE_VALUE = false;
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_FINISHED = "finished";
+
+// Actions
+
+const char* const ACTION_PLAY =     "play";
+const char* const ACTION_STOP =     "stop";
+const char* const ACTION_PAUSE =    "pause";
+
+BaseHandle Create()
+{
+  return Dali::Animation::New(0.f);
+}
+
+TypeRegistration mType( typeid( Dali::Animation ), typeid( Dali::BaseHandle ), Create );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &Animation::DoConnectSignal );
+
+TypeAction action1( mType, ACTION_PLAY,  &Animation::DoAction );
+TypeAction action2( mType, ACTION_STOP,  &Animation::DoAction );
+TypeAction action3( mType, ACTION_PAUSE, &Animation::DoAction );
+
+const Dali::Animation::EndAction DEFAULT_END_ACTION( Dali::Animation::Bake );
+const Dali::Animation::EndAction DEFAULT_DISCONNECT_ACTION( Dali::Animation::BakeFinal );
+const Dali::Animation::Interpolation DEFAULT_INTERPOLATION( Dali::Animation::Linear );
+const Dali::AlphaFunction DEFAULT_ALPHA_FUNCTION( Dali::AlphaFunction::DEFAULT );
+
+} // anon namespace
+
+
+AnimationPtr Animation::New(float durationSeconds)
+{
+  Stage* stage = Stage::GetCurrent();
+
+  if( stage )
+  {
+    AnimationPlaylist& playlist = stage->GetAnimationPlaylist();
+
+    if( durationSeconds < 0.0f )
+    {
+      DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
+      durationSeconds = 0.0f;
+    }
+
+    AnimationPtr animation = new Animation( *stage, playlist, durationSeconds, DEFAULT_END_ACTION, DEFAULT_DISCONNECT_ACTION, DEFAULT_ALPHA_FUNCTION );
+
+    // Second-phase construction
+    animation->Initialize();
+
+    return animation;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+Animation::Animation( EventThreadServices& eventThreadServices, AnimationPlaylist& playlist, float durationSeconds, EndAction endAction, EndAction disconnectAction, AlphaFunction defaultAlpha )
+: mEventThreadServices( eventThreadServices ),
+  mPlaylist( playlist ),
+  mAnimation( NULL ),
+  mNotificationCount( 0 ),
+  mFinishedCallback( NULL ),
+  mFinishedCallbackObject( NULL ),
+  mDurationSeconds( durationSeconds ),
+  mSpeedFactor(1.0f),
+  mIsLooping( false ),
+  mPlayRange( Vector2(0.0f,1.0f)),
+  mEndAction( endAction ),
+  mDisconnectAction( disconnectAction ),
+  mDefaultAlpha( defaultAlpha )
+{
+}
+
+void Animation::Initialize()
+{
+  // Connect to the animation playlist
+  mPlaylist.AnimationCreated( *this );
+
+  CreateSceneObject();
+
+  RegisterObject();
+}
+
+Animation::~Animation()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if ( Stage::IsInstalled() )
+  {
+    // Disconnect from the animation playlist
+    mPlaylist.AnimationDestroyed( *this );
+
+    DestroySceneObject();
+
+    UnregisterObject();
+  }
+}
+
+void Animation::CreateSceneObject()
+{
+  DALI_ASSERT_DEBUG( mAnimation == NULL );
+
+  // Create a new animation, temporarily owned
+  SceneGraph::Animation* animation = SceneGraph::Animation::New( mDurationSeconds, mSpeedFactor, mPlayRange, mIsLooping, mEndAction, mDisconnectAction );
+
+  // Keep a const pointer to the animation.
+  mAnimation = animation;
+
+  // Transfer animation ownership to the update manager through a message
+  AddAnimationMessage( mEventThreadServices.GetUpdateManager(), animation );
+}
+
+void Animation::DestroySceneObject()
+{
+  if ( mAnimation != NULL )
+  {
+    // Remove animation using a message to the update manager
+    RemoveAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
+    mAnimation = NULL;
+  }
+}
+
+void Animation::SetDuration(float seconds)
+{
+  if( seconds < 0.0f )
+  {
+    DALI_LOG_WARNING("duration should be greater than 0.0f.\n");
+    seconds = 0.0f;
+  }
+
+  // Cache for public getters
+  mDurationSeconds = seconds;
+
+  // mAnimation is being used in a separate thread; queue a message to set the value
+  SetDurationMessage( mEventThreadServices, *mAnimation, seconds );
+}
+
+float Animation::GetDuration() const
+{
+  // This is not animatable; the cached value is up-to-date.
+  return mDurationSeconds;
+}
+
+void Animation::SetLooping(bool looping)
+{
+  // Cache for public getters
+  mIsLooping = looping;
+
+  // mAnimation is being used in a separate thread; queue a message to set the value
+  SetLoopingMessage( mEventThreadServices, *mAnimation, looping );
+}
+
+bool Animation::IsLooping() const
+{
+  // This is not animatable; the cached value is up-to-date.
+  return mIsLooping;
+}
+
+void Animation::SetEndAction(EndAction action)
+{
+  // Cache for public getters
+  mEndAction = action;
+
+  // mAnimation is being used in a separate thread; queue a message to set the value
+  SetEndActionMessage( mEventThreadServices, *mAnimation, action );
+}
+
+Dali::Animation::EndAction Animation::GetEndAction() const
+{
+  // This is not animatable; the cached value is up-to-date.
+  return mEndAction;
+}
+
+void Animation::SetDisconnectAction(EndAction action)
+{
+  // Cache for public getters
+  mDisconnectAction = action;
+
+  // mAnimation is being used in a separate thread; queue a message to set the value
+  SetDisconnectActionMessage( mEventThreadServices, *mAnimation, action );
+}
+
+Dali::Animation::EndAction Animation::GetDisconnectAction() const
+{
+  // This is not animatable; the cached value is up-to-date.
+  return mDisconnectAction;
+}
+
+void Animation::Play()
+{
+  // Update the current playlist
+  mPlaylist.OnPlay( *this );
+
+  // mAnimation is being used in a separate thread; queue a Play message
+  PlayAnimationMessage( mEventThreadServices, *mAnimation );
+}
+
+void Animation::PlayFrom( float progress )
+{
+  if( progress >= mPlayRange.x && progress <= mPlayRange.y )
+  {
+    // Update the current playlist
+    mPlaylist.OnPlay( *this );
+
+    // mAnimation is being used in a separate thread; queue a Play message
+    PlayAnimationFromMessage( mEventThreadServices, *mAnimation, progress );
+  }
+}
+
+void Animation::Pause()
+{
+  // mAnimation is being used in a separate thread; queue a Pause message
+  PauseAnimationMessage( mEventThreadServices, *mAnimation );
+}
+
+void Animation::Stop()
+{
+  // mAnimation is being used in a separate thread; queue a Stop message
+  StopAnimationMessage( mEventThreadServices.GetUpdateManager(), *mAnimation );
+}
+
+void Animation::Clear()
+{
+  DALI_ASSERT_DEBUG(mAnimation);
+
+  // Remove all the connectors
+  mConnectors.Clear();
+
+  // Replace the old scene-object with a new one
+  DestroySceneObject();
+  CreateSceneObject();
+
+  // Reset the notification count, since the new scene-object has never been played
+  mNotificationCount = 0;
+
+  // Update the current playlist
+  mPlaylist.OnClear( *this );
+}
+
+void Animation::AnimateBy(Property& target, Property::Value& relativeValue)
+{
+  AnimateBy(target, relativeValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
+}
+
+void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha)
+{
+  AnimateBy(target, relativeValue, alpha, TimePeriod(mDurationSeconds));
+}
+
+void Animation::AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period)
+{
+  AnimateBy(target, relativeValue, mDefaultAlpha, period);
+}
+
+void Animation::AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period)
+{
+  Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
+
+  ExtendDuration( period );
+
+  switch ( relativeValue.GetType() )
+  {
+    case Property::BOOLEAN:
+    {
+      AddAnimatorConnector( AnimatorConnector<bool>::New( object,
+                                                          target.propertyIndex,
+                                                          target.componentIndex,
+                                                          new AnimateByBoolean(relativeValue.Get<bool>()),
+                                                          alpha,
+                                                          period ) );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      AddAnimatorConnector( AnimatorConnector<int>::New( object,
+                                                         target.propertyIndex,
+                                                         target.componentIndex,
+                                                         new AnimateByInteger(relativeValue.Get<int>()),
+                                                         alpha,
+                                                         period ) );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      AddAnimatorConnector( AnimatorConnector<float>::New( object,
+                                                           target.propertyIndex,
+                                                           target.componentIndex,
+                                                           new AnimateByFloat(relativeValue.Get<float>()),
+                                                           alpha,
+                                                           period ) );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new AnimateByVector2(relativeValue.Get<Vector2>()),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new AnimateByVector3(relativeValue.Get<Vector3>()),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new AnimateByVector4(relativeValue.Get<Vector4>()),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      AngleAxis angleAxis = relativeValue.Get<AngleAxis>();
+
+      AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
+                                                                target.propertyIndex,
+                                                                target.componentIndex,
+                                                                new RotateByAngleAxis(angleAxis.angle, angleAxis.axis),
+                                                                alpha,
+                                                                period ) );
+      break;
+    }
+
+    default:
+      DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
+      break;
+  }
+}
+
+void Animation::AnimateTo(Property& target, Property::Value& destinationValue)
+{
+  AnimateTo(target, destinationValue, mDefaultAlpha, TimePeriod(mDurationSeconds));
+}
+
+void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha)
+{
+  AnimateTo(target, destinationValue, alpha, TimePeriod(mDurationSeconds));
+}
+
+void Animation::AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period)
+{
+  AnimateTo(target, destinationValue, mDefaultAlpha, period);
+}
+
+void Animation::AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
+{
+  Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
+
+  AnimateTo( object, target.propertyIndex, target.componentIndex, destinationValue, alpha, period );
+}
+
+void Animation::AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period)
+{
+  Property::Type type = targetObject.GetPropertyType(targetPropertyIndex);
+  if(componentIndex != Property::INVALID_COMPONENT_INDEX)
+  {
+    if( type == Property::VECTOR2
+        || type == Property::VECTOR3
+        || type == Property::VECTOR4 )
+    {
+      type = Property::FLOAT;
+    }
+  }
+  DALI_ASSERT_ALWAYS( type == destinationValue.GetType() && "DestinationValue does not match Target Property type" );
+
+  ExtendDuration( period );
+
+  switch (destinationValue.GetType())
+  {
+    case Property::BOOLEAN:
+    {
+      AddAnimatorConnector( AnimatorConnector<bool>::New( targetObject,
+                                                          targetPropertyIndex,
+                                                          componentIndex,
+                                                          new AnimateToBoolean( destinationValue.Get<bool>() ),
+                                                          alpha,
+                                                          period ) );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      AddAnimatorConnector( AnimatorConnector<int>::New( targetObject,
+                                                         targetPropertyIndex,
+                                                         componentIndex,
+                                                         new AnimateToInteger( destinationValue.Get<int>() ),
+                                                         alpha,
+                                                         period ) );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      if ( ( Dali::Actor::Property::SIZE_WIDTH == targetPropertyIndex )||
+           ( Dali::Actor::Property::SIZE_HEIGHT == targetPropertyIndex ) )
+      {
+        // Test whether this is actually an Actor
+        Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
+        if ( maybeActor )
+        {
+          // Notify the actor that its size is being animated
+          maybeActor->NotifySizeAnimation( *this, destinationValue.Get<float>(), targetPropertyIndex );
+        }
+      }
+      AddAnimatorConnector( AnimatorConnector<float>::New( targetObject,
+                                                           targetPropertyIndex,
+                                                           componentIndex,
+                                                           new AnimateToFloat( destinationValue.Get<float>() ),
+                                                           alpha,
+                                                           period ) );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      AddAnimatorConnector( AnimatorConnector<Vector2>::New( targetObject,
+                                                             targetPropertyIndex,
+                                                             componentIndex,
+                                                             new AnimateToVector2( destinationValue.Get<Vector2>() ),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      if ( Dali::Actor::Property::SIZE == targetPropertyIndex )
+      {
+        // Test whether this is actually an Actor
+        Actor* maybeActor = dynamic_cast<Actor*>( &targetObject );
+        if ( maybeActor )
+        {
+          // Notify the actor that its size is being animated
+          maybeActor->NotifySizeAnimation( *this, destinationValue.Get<Vector3>() );
+        }
+      }
+
+      AddAnimatorConnector( AnimatorConnector<Vector3>::New( targetObject,
+                                                             targetPropertyIndex,
+                                                             componentIndex,
+                                                             new AnimateToVector3( destinationValue.Get<Vector3>() ),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      AddAnimatorConnector( AnimatorConnector<Vector4>::New( targetObject,
+                                                             targetPropertyIndex,
+                                                             componentIndex,
+                                                             new AnimateToVector4( destinationValue.Get<Vector4>() ),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      AddAnimatorConnector( AnimatorConnector<Quaternion>::New( targetObject,
+                                                                targetPropertyIndex,
+                                                                componentIndex,
+                                                                new RotateToQuaternion( destinationValue.Get<Quaternion>() ),
+                                                                alpha,
+                                                                period ) );
+      break;
+    }
+
+    default:
+      DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
+      break;
+  }
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames)
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION );
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation )
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, TimePeriod(mDurationSeconds), interpolation );
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period)
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+{
+  AnimateBetween(target, keyFrames, mDefaultAlpha, period, interpolation);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha)
+{
+  AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+{
+  AnimateBetween(target, keyFrames, alpha, TimePeriod(mDurationSeconds), interpolation);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
+{
+  AnimateBetween(target, keyFrames, alpha, period, DEFAULT_INTERPOLATION);
+}
+
+void Animation::AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
+{
+  Object& object = dynamic_cast<Object&>( GetImplementation(target.object) );
+
+  ExtendDuration( period );
+
+  switch(keyFrames.GetType())
+  {
+    case Dali::Property::BOOLEAN:
+    {
+      const KeyFrameBoolean* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameBooleanPtr kfCopy = KeyFrameBoolean::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<bool>::New( object,
+                                                          target.propertyIndex,
+                                                          target.componentIndex,
+                                                          new KeyFrameBooleanFunctor(kfCopy),
+                                                          alpha,
+                                                          period ) );
+      break;
+    }
+
+    case Dali::Property::INTEGER:
+    {
+      const KeyFrameInteger* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameIntegerPtr kfCopy = KeyFrameInteger::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<int>::New( object,
+                                                         target.propertyIndex,
+                                                         target.componentIndex,
+                                                         new KeyFrameIntegerFunctor(kfCopy,interpolation),
+                                                         alpha,
+                                                         period ) );
+      break;
+    }
+
+    case Dali::Property::FLOAT:
+    {
+      const KeyFrameNumber* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameNumberPtr kfCopy = KeyFrameNumber::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<float>::New( object,
+                                                           target.propertyIndex,
+                                                           target.componentIndex,
+                                                           new KeyFrameNumberFunctor(kfCopy,interpolation),
+                                                           alpha,
+                                                           period ) );
+      break;
+    }
+
+    case Dali::Property::VECTOR2:
+    {
+      const KeyFrameVector2* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameVector2Ptr kfCopy = KeyFrameVector2::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<Vector2>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new KeyFrameVector2Functor(kfCopy,interpolation),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Dali::Property::VECTOR3:
+    {
+      const KeyFrameVector3* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameVector3Ptr kfCopy = KeyFrameVector3::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<Vector3>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new KeyFrameVector3Functor(kfCopy,interpolation),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Dali::Property::VECTOR4:
+    {
+      const KeyFrameVector4* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameVector4Ptr kfCopy = KeyFrameVector4::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<Vector4>::New( object,
+                                                             target.propertyIndex,
+                                                             target.componentIndex,
+                                                             new KeyFrameVector4Functor(kfCopy,interpolation),
+                                                             alpha,
+                                                             period ) );
+      break;
+    }
+
+    case Dali::Property::ROTATION:
+    {
+      const KeyFrameQuaternion* kf;
+      GetSpecialization(keyFrames, kf);
+      KeyFrameQuaternionPtr kfCopy = KeyFrameQuaternion::Clone(*kf);
+      AddAnimatorConnector( AnimatorConnector<Quaternion>::New( object,
+                                                                target.propertyIndex,
+                                                                target.componentIndex,
+                                                                new KeyFrameQuaternionFunctor(kfCopy),
+                                                                alpha,
+                                                                period ) );
+      break;
+    }
+
+    default: // not all property types are animateable
+      break;
+  }
+}
+
+bool Animation::HasFinished()
+{
+  bool hasFinished(false);
+  const int playCount(mAnimation->GetPlayCount());
+
+  // If the play count has been incremented, then another notification is required
+  if (playCount > mNotificationCount)
+  {
+    // Note that only one signal is emitted, if the animation has been played repeatedly
+    mNotificationCount = playCount;
+
+    hasFinished = true;
+  }
+
+  return hasFinished;
+}
+
+Dali::Animation::AnimationSignalType& Animation::FinishedSignal()
+{
+  return mFinishedSignal;
+}
+
+void Animation::EmitSignalFinish()
+{
+  if ( !mFinishedSignal.Empty() )
+  {
+    Dali::Animation handle( this );
+    mFinishedSignal.Emit( handle );
+  }
+
+  // This callback is used internally, to avoid the overhead of using a signal.
+  if ( mFinishedCallback )
+  {
+    mFinishedCallback( mFinishedCallbackObject );
+  }
+}
+
+bool Animation::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  Animation* animation = dynamic_cast<Animation*>(object);
+
+  if( 0 == signalName.compare( SIGNAL_FINISHED ) )
+  {
+    animation->FinishedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void Animation::SetFinishedCallback( FinishedCallback callback, Object* object )
+{
+  mFinishedCallback = callback;
+  mFinishedCallbackObject = object;
+}
+
+void Animation::AddAnimatorConnector( AnimatorConnectorBase* connector )
+{
+  DALI_ASSERT_DEBUG( NULL != connector );
+
+  connector->SetParent(*this);
+
+  mConnectors.PushBack( connector );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward )
+{
+  Animate( actor, path, forward, mDefaultAlpha, TimePeriod(mDurationSeconds) );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha )
+{
+  Animate( actor, path, forward, alpha, TimePeriod(mDurationSeconds) );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period )
+{
+  Animate( actor, path, forward, mDefaultAlpha, period );
+}
+
+void Animation::Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+{
+  ExtendDuration( period );
+
+  PathPtr pathCopy = Path::Clone(path);
+
+  //Position animation
+  AddAnimatorConnector( AnimatorConnector<Vector3>::New( actor,
+                                                         Dali::Actor::Property::POSITION,
+                                                         Property::INVALID_COMPONENT_INDEX,
+                                                         new PathPositionFunctor( pathCopy ),
+                                                         alpha,
+                                                         period ) );
+
+  //If forward is zero, PathRotationFunctor will always return the unit quaternion
+  if( forward != Vector3::ZERO )
+  {
+    //Rotation animation
+    AddAnimatorConnector( AnimatorConnector<Quaternion>::New( actor,
+                                                              Dali::Actor::Property::ORIENTATION,
+                                                              Property::INVALID_COMPONENT_INDEX,
+                                                              new PathRotationFunctor( pathCopy, forward ),
+                                                              alpha,
+                                                              period ) );
+  }
+}
+
+void Animation::Show(Actor& actor, float delaySeconds)
+{
+  ExtendDuration( TimePeriod(delaySeconds, 0) );
+
+  AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
+                                                      Dali::Actor::Property::VISIBLE,
+                                                      Property::INVALID_COMPONENT_INDEX,
+                                                      new AnimateToBoolean(SHOW_VALUE),
+                                                      mDefaultAlpha,
+                                                      TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
+}
+
+void Animation::Hide(Actor& actor, float delaySeconds)
+{
+  ExtendDuration( TimePeriod(delaySeconds, 0) );
+
+  AddAnimatorConnector( AnimatorConnector<bool>::New( actor,
+                                                      Dali::Actor::Property::VISIBLE,
+                                                      Property::INVALID_COMPONENT_INDEX,
+                                                      new AnimateToBoolean(HIDE_VALUE),
+                                                      mDefaultAlpha,
+                                                      TimePeriod(delaySeconds, 0.0f/*immediate*/) ) );
+}
+
+bool Animation::DoAction( BaseObject* object, const std::string& actionName, const Property::Map& attributes )
+{
+  bool done = false;
+  Animation* animation = dynamic_cast<Animation*>( object );
+
+  if( animation )
+  {
+    if( 0 == actionName.compare( ACTION_PLAY ) )
+    {
+      if( Property::Value* value = attributes.Find("duration", Property::FLOAT) )
+      {
+        animation->SetDuration( value->Get<float>() );
+      }
+
+      animation->Play();
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_STOP ) )
+    {
+      animation->Stop();
+      done = true;
+    }
+    else if( 0 == actionName.compare( ACTION_PAUSE ) )
+    {
+      animation->Pause();
+      done = true;
+    }
+  }
+
+  return done;
+}
+
+void Animation::SetCurrentProgress(float progress)
+{
+  if( mAnimation && progress >= mPlayRange.x && progress <= mPlayRange.y )
+  {
+    // mAnimation is being used in a separate thread; queue a message to set the current progress
+    SetCurrentProgressMessage( mEventThreadServices, *mAnimation, progress );
+  }
+}
+
+float Animation::GetCurrentProgress()
+{
+  if( mAnimation )
+  {
+    return mAnimation->GetCurrentProgress();
+  }
+
+  return 0.0f;
+}
+
+void Animation::ExtendDuration( const TimePeriod& timePeriod )
+{
+  float duration = timePeriod.delaySeconds + timePeriod.durationSeconds;
+
+  if( duration > mDurationSeconds )
+  {
+    SetDuration( duration );
+  }
+}
+
+void Animation::SetSpeedFactor( float factor )
+{
+  if( mAnimation )
+  {
+    mSpeedFactor = factor;
+    SetSpeedFactorMessage( mEventThreadServices, *mAnimation, factor );
+  }
+}
+
+float Animation::GetSpeedFactor() const
+{
+  return mSpeedFactor;
+}
+
+void Animation::SetPlayRange( const Vector2& range)
+{
+  //Make sure the range specified is between 0.0 and 1.0
+  if( range.x >= 0.0f && range.x <= 1.0f && range.y >= 0.0f && range.y <= 1.0f )
+  {
+    Vector2 orderedRange( range );
+    //If the range is not in order swap values
+    if( range.x > range.y )
+    {
+      orderedRange = Vector2(range.y, range.x);
+    }
+
+    // Cache for public getters
+    mPlayRange = orderedRange;
+
+    // mAnimation is being used in a separate thread; queue a message to set play range
+    SetPlayRangeMessage( mEventThreadServices, *mAnimation, orderedRange );
+  }
+}
+
+Vector2 Animation::GetPlayRange() const
+{
+  return mPlayRange;
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/animation/animation-impl.h b/dali/internal/event/animation/animation-impl.h
new file mode 100644 (file)
index 0000000..6272042
--- /dev/null
@@ -0,0 +1,481 @@
+#ifndef __DALI_INTERNAL_ANIMATION_H__
+#define __DALI_INTERNAL_ANIMATION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/internal/event/animation/animator-connector-base.h>
+#include <dali/internal/event/animation/key-frames-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class Animation;
+class UpdateManager;
+}
+
+class Actor;
+class Animation;
+class AnimationPlaylist;
+class Object;
+class ShaderEffect;
+
+typedef IntrusivePtr<Animation> AnimationPtr;
+typedef std::vector<AnimationPtr> AnimationContainer;
+
+typedef AnimationContainer::iterator AnimationIter;
+typedef AnimationContainer::const_iterator AnimationConstIter;
+
+/**
+ * Animation is a proxy for a SceneGraph::Animation object.
+ * The UpdateManager owns the Animation object, but the lifetime of the animation is
+ * indirectly controlled by the Animation.
+ */
+class Animation : public BaseObject
+{
+public:
+
+  typedef Dali::Animation::EndAction EndAction;
+  typedef Dali::Animation::Interpolation Interpolation;
+
+  typedef void (*FinishedCallback)(Object* object);
+
+  /**
+   * Create a new Animation object.
+   * @param[in] durationSeconds The duration of the animation.
+   * @return A smart-pointer to the newly allocated Animation.
+   */
+  static AnimationPtr New(float durationSeconds);
+
+  /**
+   * @copydoc Dali::Animation::SetDuration()
+   */
+  void SetDuration(float seconds);
+
+  /**
+   * @copydoc Dali::Animation::GetDuration()
+   */
+  float GetDuration() const;
+
+  /**
+   * @copydoc Dali::Animation::SetLooping()
+   */
+  void SetLooping(bool looping);
+
+  /**
+   * @copydoc Dali::Animation::IsLooping()
+   */
+  bool IsLooping() const;
+
+  /**
+   * @copydoc Dali::Animation::SetEndAction()
+   */
+  void SetEndAction(EndAction action);
+
+  /**
+   * @copydoc Dali::Animation::GetEndAction()
+   */
+  EndAction GetEndAction() const;
+
+  /**
+   * @copydoc Dali::Animation::SetDisconnectAction()
+   */
+  void SetDisconnectAction(EndAction action);
+
+  /**
+   * @copydoc Dali::Animation::GetDisconnectAction()
+   */
+  EndAction GetDisconnectAction() const;
+
+  /**
+   * @copydoc Dali::Animation::SetDefaultAlphaFunction()
+   */
+  void SetDefaultAlphaFunction(AlphaFunction alpha)
+  {
+    mDefaultAlpha = alpha;
+  }
+
+  /**
+   * @copydoc Dali::Animation::GetDefaultAlphaFunction()
+   */
+  AlphaFunction GetDefaultAlphaFunction() const
+  {
+    return mDefaultAlpha;
+  }
+
+  /**
+   * @copydoc Dali::Animation::Play()
+   */
+  void Play();
+
+  /**
+   * @copydoc Dali::Animation::PlayFrom()
+   */
+  void PlayFrom( float progress );
+
+  /**
+   * @copydoc Dali::Animation::Pause()
+   */
+  void Pause();
+
+  /**
+   * @copydoc Dali::Animation::Stop()
+   */
+  void Stop();
+
+  /**
+   * @copydoc Dali::Animation::Clear()
+   */
+  void Clear();
+
+  /**
+   * Query whether a Finished signal should be emitted for this animation.
+   * This should only be called by NotificationManager, before signals are emitted.
+   * @post HasFinished() will return false on subsequent calls, until the animation is replayed to completion.
+   */
+  bool HasFinished();
+
+  /**
+   * @copydoc Dali::Animation::FinishedSignal()
+   */
+  Dali::Animation::AnimationSignalType& FinishedSignal();
+
+  /**
+   * Emit the Finished signal
+   */
+  void EmitSignalFinish();
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+  /**
+   * Performs actions as requested using the action name.
+   * @param[in] object The object on which to perform the action.
+   * @param[in] actionName The action to perform.
+   * @param[in] attributes The attributes with which to perfrom this action.
+   * @return true if action was done
+   */
+  static bool DoAction(BaseObject* object, const std::string& actionName, const Property::Map& attributes);
+
+  /**
+   * This callback is intended for internal use only, to avoid the overhead of using a signal.
+   * @param[in] callback The callback function to connect.
+   * @param[in] object The internal object requesting the callback, or NULL.
+   */
+  void SetFinishedCallback( FinishedCallback callback, Object* object );
+
+  /**
+   * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue)
+   */
+  void AnimateBy(Property& target, Property::Value& relativeValue);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
+   */
+  void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
+   */
+  void AnimateBy(Property& target, Property::Value& relativeValue, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
+   */
+  void AnimateBy(Property& target, Property::Value& relativeValue, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue)
+   */
+  void AnimateTo(Property& target, Property::Value& destinationValue);
+
+  /**
+   * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
+   */
+  void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha);
+
+  /**
+   * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
+   */
+  void AnimateTo(Property& target, Property::Value& destinationValue, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
+   */
+  void AnimateTo(Property& target, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * Animate a property to a destination value.
+   * @param [in] targetObject The target object to animate.
+   * @param [in] targetPropertyIndex The index of the target property.
+   * @param [in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4
+   * @param [in] destinationValue The destination value.
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateTo(Object& targetObject, Property::Index targetPropertyIndex, int componentIndex, Property::Value& destinationValue, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, Interpolation interpolation );
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation )
+   */
+  void AnimateBetween(Property target, const KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation );
+
+  // Actor-specific convenience functions
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, TimePeriod period );
+
+  /**
+   * @copydoc Dali::Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+   */
+  void Animate( Actor& actor, const Path& path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @copydoc Dali::Animation::Show()
+   */
+  void Show(Actor& actor, float delaySeconds);
+
+  /**
+   * @copydoc Dali::Animation::Hide()
+   */
+  void Hide(Actor& actor, float delaySeconds);
+
+  /*
+   * @copydoc Dali::Animation::SetCurrentProgress()
+   */
+  void SetCurrentProgress(float progress);
+
+  /*
+   * @copydoc Dali::Animation::GetCurrentProgress()
+   */
+  float GetCurrentProgress();
+
+  /*
+   * @copydoc Dali::Animation::SetSpeedFactor()
+   */
+  void SetSpeedFactor( float factor );
+
+  /*
+   * @copydoc Dali::Animation::GetSpeedFactor()
+   */
+  float GetSpeedFactor() const;
+
+  /*
+   * @copydoc Dali::Animation::SetPlayRange()
+   */
+  void SetPlayRange( const Vector2& range );
+
+  /*
+   * @copydoc Dali::Animation::GetPlayRange
+   */
+  Vector2 GetPlayRange() const;
+
+public: // For connecting animators to animations
+
+  /**
+   * Add an animator connector.
+   * @param[in] connector The animator connector.
+   */
+  void AddAnimatorConnector( AnimatorConnectorBase* connector );
+
+  /**
+   * Retrieve the SceneGraph::Animation object.
+   * @return The animation.
+   */
+  const SceneGraph::Animation* GetSceneObject()
+  {
+    return mAnimation;
+  }
+
+  /**
+   * Retrieve the event thread services object
+   * @return The interface for sending messages to the scene graph
+   */
+  EventThreadServices& GetEventThreadServices()
+  {
+    return mEventThreadServices;
+  }
+
+protected:
+
+  /**
+   * Construct a new Animation.
+   * @param[in] eventThreadServices The interface for sending messages to the scene graph
+   * @param[in] playlist The list of currently playing animations.
+   * @param[in] durationSeconds The duration of the animation in seconds.
+   * @param[in] endAction The action to perform when the animation ends.
+   * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
+   * @param[in] defaultAlpha The default alpha function to apply to animators.
+   */
+  Animation( EventThreadServices& eventThreadServices,
+             AnimationPlaylist& playlist,
+             float durationSeconds,
+             EndAction endAction,
+             EndAction disconnectAction,
+             AlphaFunction defaultAlpha);
+
+  /**
+   * Second-phase constructor.
+   */
+  void Initialize();
+
+  /**
+   * Helper to create a scene-graph animation
+   */
+  void CreateSceneObject();
+
+  /**
+   * Helper to create a scene-graph animation
+   */
+  void DestroySceneObject();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Animation();
+
+private:
+
+  /**
+   * Extends the duration when an animator is added with TimePeriod that exceeds current duration.
+   * @param[in] timePeriod The time period for an animator.
+   */
+  void ExtendDuration( const TimePeriod& timePeriod );
+
+  // Undefined
+  Animation(const Animation&);
+
+  // Undefined
+  Animation& operator=(const Animation& rhs);
+
+private:
+  EventThreadServices& mEventThreadServices;
+  AnimationPlaylist& mPlaylist;
+
+  const SceneGraph::Animation* mAnimation;
+
+  int mNotificationCount; ///< Keep track of how many Finished signals have been emitted.
+
+  Dali::Animation::AnimationSignalType mFinishedSignal;
+
+  FinishedCallback mFinishedCallback;
+  Object* mFinishedCallbackObject;
+
+  AnimatorConnectorContainer mConnectors; ///< Owned by the Animation
+
+  // Cached for public getters
+  float mDurationSeconds;
+  float mSpeedFactor;
+  bool mIsLooping;
+  Vector2 mPlayRange;
+  EndAction mEndAction;
+  EndAction mDisconnectAction;
+  AlphaFunction mDefaultAlpha;
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Animation& GetImplementation(Dali::Animation& animation)
+{
+  DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
+
+  BaseObject& handle = animation.GetBaseObject();
+
+  return static_cast<Internal::Animation&>(handle);
+}
+
+inline const Internal::Animation& GetImplementation(const Dali::Animation& animation)
+{
+  DALI_ASSERT_ALWAYS( animation && "Animation handle is empty" );
+
+  const BaseObject& handle = animation.GetBaseObject();
+
+  return static_cast<const Internal::Animation&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ANIMATION_H__
diff --git a/dali/internal/event/animation/animation-playlist-declarations.h b/dali/internal/event/animation/animation-playlist-declarations.h
new file mode 100644 (file)
index 0000000..a180d94
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__
+#define __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class AnimationPlaylist;
+
+typedef OwnerPointer<AnimationPlaylist> AnimationPlaylistOwner;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ANIMATION_PLAYLIST_DECLARATIONS_H__
+
diff --git a/dali/internal/event/animation/animation-playlist.cpp b/dali/internal/event/animation/animation-playlist.cpp
new file mode 100644 (file)
index 0000000..ef3644b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/animation-playlist.h>
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/internal/event/animation/animation-impl.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+AnimationPlaylist* AnimationPlaylist::New()
+{
+  return new AnimationPlaylist();
+}
+
+AnimationPlaylist::AnimationPlaylist()
+{
+}
+
+AnimationPlaylist::~AnimationPlaylist()
+{
+}
+
+void AnimationPlaylist::AnimationCreated( Animation& animation )
+{
+  mAnimations.PushBack( &animation );
+}
+
+void AnimationPlaylist::AnimationDestroyed( Animation& animation )
+{
+  Dali::Vector< Animation* >::Iterator iter = std::find( mAnimations.Begin(), mAnimations.End(), &animation );
+  DALI_ASSERT_ALWAYS( iter != mAnimations.End() && "Animation not found" );
+
+  mAnimations.Remove( iter );
+}
+
+void AnimationPlaylist::OnPlay( Animation& animation )
+{
+  mPlaylist.push_back( Dali::Animation(&animation) );
+}
+
+void AnimationPlaylist::OnClear( Animation& animation )
+{
+  std::vector< Dali::Animation >::iterator iter = std::find( mPlaylist.begin(), mPlaylist.end(), Dali::Animation(&animation) );
+  std::vector< Dali::Animation >::iterator last = mPlaylist.end();
+  if( iter != last )
+  {
+    --last; // move to real last
+    std::swap( *iter, *last ); // swap
+    mPlaylist.resize( mPlaylist.size() - 1u );
+  }
+}
+
+void AnimationPlaylist::NotifyCompleted()
+{
+  std::vector< Dali::Animation > finishedAnimations;
+
+  // Since animations can be unreferenced during the signal emissions, iterators into animationPointers may be invalidated.
+  // First copy and reference the finished animations, then emit signals
+  for ( Dali::Vector< Animation* >::Iterator iter = mAnimations.Begin(); iter != mAnimations.End(); ++iter )
+  {
+    Animation* animation = *iter;
+
+    if ( animation->HasFinished() )
+    {
+      finishedAnimations.push_back( Dali::Animation(animation) );
+
+      // The animation may be present in mPlaylist - remove if necessary
+      // Note that the animation "Finish" signal is emitted after Stop() has been called
+      std::vector< Dali::Animation >::iterator iter = std::find( mPlaylist.begin(), mPlaylist.end(), Dali::Animation(animation) );
+      mPlaylist.erase( iter );
+    }
+  }
+
+  // Now it's safe to emit the signals
+  for ( std::vector< Dali::Animation >::iterator iter = finishedAnimations.begin(); iter != finishedAnimations.end(); ++iter )
+  {
+    Dali::Animation& handle = *iter;
+
+    GetImplementation(handle).EmitSignalFinish();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/animation/animation-playlist.h b/dali/internal/event/animation/animation-playlist.h
new file mode 100644 (file)
index 0000000..504bc5f
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __DALI_INTERNAL_ANIMATION_PLAYLIST_H__
+#define __DALI_INTERNAL_ANIMATION_PLAYLIST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/internal/event/common/complete-notification-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Animation;
+
+/**
+ * AnimationPlaylist provides notifications to applications when animations are finished.
+ * It reference-counts playing animations, to allow "fire and forget" behaviour.
+ */
+class AnimationPlaylist : public CompleteNotificationInterface
+{
+public:
+
+  /**
+   * Create an AnimationPlaylist.
+   * @return A newly allocated animation playlist.
+   */
+  static AnimationPlaylist* New();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimationPlaylist();
+
+  /**
+   * Called when an animation is constructed.
+   */
+  void AnimationCreated( Animation& animation );
+
+  /**
+   * Called when an animation is destroyed.
+   */
+  void AnimationDestroyed( Animation& animation );
+
+  /**
+   * Called when an animation is playing.
+   * @post The animation will be referenced by AnimationPlaylist, until the "Finished" signal is emitted.
+   */
+  void OnPlay( Animation& animation );
+
+  /**
+   * Called when an animation is cleared.
+   * @post The animation will no longer be referenced by AnimationPlaylist.
+   */
+  void OnClear( Animation& animation );
+
+private:
+
+  /**
+   * Create an AnimationPlaylist.
+   */
+  AnimationPlaylist();
+
+  // Undefined
+  AnimationPlaylist(const AnimationPlaylist&);
+
+  // Undefined
+  AnimationPlaylist& operator=(const AnimationPlaylist& rhs);
+
+private: // from CompleteNotificationInterface
+
+  /**
+   * @copydoc CompleteNotificationInterface::NotifyCompleted()
+   */
+  virtual void NotifyCompleted();
+
+private:
+
+  Dali::Vector< Animation* > mAnimations; ///< All existing animations (not owned)
+  std::vector< Dali::Animation > mPlaylist; ///< The currently playing animations (owned through handle)
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_NOTIFICATION_MANAGER_H__
+
diff --git a/dali/internal/event/animation/animator-connector-base.h b/dali/internal/event/animation/animator-connector-base.h
new file mode 100644 (file)
index 0000000..90ff6f5
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__
+#define __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/time-period.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Animation;
+class AnimatorConnectorBase;
+
+typedef OwnerPointer<AnimatorConnectorBase> AnimatorConnectorPtr;
+
+typedef OwnerContainer< AnimatorConnectorBase* > AnimatorConnectorContainer;
+
+typedef AnimatorConnectorContainer::Iterator AnimatorConnectorIter;
+typedef AnimatorConnectorContainer::ConstIterator AnimatorConnectorConstIter;
+
+/**
+ * An abstract base class for animator connectors.
+ */
+class AnimatorConnectorBase
+{
+public:
+
+  /**
+   * Constructor.
+   */
+  AnimatorConnectorBase(AlphaFunction alpha, const TimePeriod& period)
+  : mParent(NULL),
+    mAlphaFunction(alpha),
+    mTimePeriod(period)
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatorConnectorBase()
+  {
+  }
+
+  /**
+   * Set the parent of the AnimatorConnector.
+   * @pre The connector does not already have a parent.
+   * @param [in] parent The parent object.
+   */
+  virtual void SetParent(Animation& parent) = 0;
+
+  /**
+   * Retrieve the parent of the AnimatorConnector.
+   * @return The parent object, or NULL.
+   */
+  Animation* GetParent()
+  {
+    return mParent;
+  }
+
+protected:
+
+  Animation* mParent; ///< The parent owns the connector.
+
+  AlphaFunction mAlphaFunction;
+  TimePeriod mTimePeriod;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_BASE_H__
diff --git a/dali/internal/event/animation/animator-connector.h b/dali/internal/event/animation/animator-connector.h
new file mode 100644 (file)
index 0000000..9440f91
--- /dev/null
@@ -0,0 +1,370 @@
+#ifndef __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
+#define __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/animation/animator-connector-base.h>
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/property-component-accessor.h>
+#include <dali/internal/update/animation/scene-graph-animator.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * AnimatorConnector is used to connect SceneGraph::Animators for newly created scene-graph objects.
+ *
+ * The scene-graph objects are created by a Object e.g. Actor is a proxy for SceneGraph::Node.
+ * AnimatorConnector observes the proxy object, in order to detect when a scene-graph object is created.
+ *
+ * SceneGraph::Animators weakly reference scene objects, and are automatically deleted when orphaned.
+ * Therefore the AnimatorConnector is NOT responsible for disconnecting animators.
+ */
+template < typename PropertyType >
+class AnimatorConnector : public AnimatorConnectorBase, public Object::Observer
+{
+public:
+
+  typedef SceneGraph::Animator< PropertyType, PropertyAccessor<PropertyType> > AnimatorType;
+  typedef SceneGraph::AnimatableProperty< PropertyType > PropertyInterfaceType;
+
+  /**
+   * Construct a new animator connector.
+   * @param[in] object The object for a scene-graph object to animate.
+   * @param[in] propertyIndex The index of a property provided by the object.
+   * @param[in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4 (INVALID_PROPERTY_COMPONENTINDEX to use the whole property)
+   * @param[in] animatorFunction A function used to animate the property.
+   * @param[in] alpha The alpha function to apply.
+   * @param[in] period The time period of the animator.
+   * @return A pointer to a newly allocated animator connector.
+   */
+  static AnimatorConnectorBase* New( Object& object,
+                                     Property::Index propertyIndex,
+                                     int componentIndex,
+                                     AnimatorFunctionBase* animatorFunction,
+                                     AlphaFunction alpha,
+                                     const TimePeriod& period )
+  {
+    return new AnimatorConnector< PropertyType >( object,
+                                                  propertyIndex,
+                                                  componentIndex,
+                                                  animatorFunction,
+                                                  alpha,
+                                                  period );
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatorConnector()
+  {
+    if( mObject )
+    {
+      mObject->RemoveObserver( *this );
+    }
+
+    //If there is not a SceneGraph::Animator, the AnimatorConnector is responsible for deleting the mAnimatorFunction
+    //otherwise, the animator function ownership is transferred to the SceneGraph::Animator
+    if( !mAnimator )
+    {
+      delete mAnimatorFunction;
+      mAnimatorFunction = 0;
+    }
+  }
+
+  /**
+   * From AnimatorConnectorBase.
+   * This is only expected to be called once, when added to an Animation.
+   */
+  void SetParent( Animation& parent )
+  {
+    DALI_ASSERT_ALWAYS( mParent == NULL && "AnimationConnector already has a parent" );
+    mParent = &parent;
+
+    if( mObject && mObject->GetSceneObject() )
+    {
+      CreateAnimator();
+    }
+  }
+
+private:
+
+  /**
+   * Private constructor; see also AnimatorConnector::New().
+   */
+  AnimatorConnector( Object& object,
+                     Property::Index propertyIndex,
+                     int componentIndex,
+                     Internal::AnimatorFunctionBase* animatorFunction,
+                     AlphaFunction alpha,
+                     const TimePeriod& period )
+  : AnimatorConnectorBase( alpha, period ),
+    mObject( &object ),
+    mAnimator(0),
+    mPropertyIndex( propertyIndex ),
+    mComponentIndex( componentIndex ),
+    mAnimatorFunction( animatorFunction )
+  {
+    object.AddObserver( *this );
+  }
+
+  // Undefined
+  AnimatorConnector( const AnimatorConnector& );
+
+  // Undefined
+  AnimatorConnector& operator=( const AnimatorConnector& rhs );
+
+  /**
+   * From Object::Observer
+   */
+  virtual void SceneObjectAdded( Object& object )
+  {
+    //If the animator has not been created yet, create it now.
+    if( !mAnimator )
+    {
+      CreateAnimator();
+    }
+  }
+
+  /**
+   * From Object::Observer
+   */
+  virtual void SceneObjectRemoved( Object& object )
+  {
+  }
+
+  /**
+   * From Object::Observer
+   */
+  virtual void ObjectDestroyed( Object& object )
+  {
+    mObject = NULL;
+  }
+
+   /**
+   * Helper function to create a Scenegraph::Animator and add it to its correspondent SceneGraph::Animation.
+   * @note This function will only be called the first time the object is added to the scene or at creation time if
+   * the object was already in the scene
+   */
+  void CreateAnimator()
+  {
+    DALI_ASSERT_DEBUG( mAnimator == NULL );
+    DALI_ASSERT_DEBUG( mAnimatorFunction != NULL );
+    DALI_ASSERT_DEBUG( mParent != NULL );
+
+    //Get the PropertyOwner the animator is going to animate
+    const SceneGraph::PropertyOwner* propertyOwner = mObject->GetSceneObject();
+
+    //Get SceneGraph::BaseProperty
+    const SceneGraph::PropertyBase* baseProperty = mObject->GetSceneObjectAnimatableProperty( mPropertyIndex );
+
+    //Check if property is a component of another property
+    const int componentIndex = mObject->GetPropertyComponentIndex( mPropertyIndex );
+    if( componentIndex != Property::INVALID_COMPONENT_INDEX )
+    {
+      mComponentIndex = componentIndex;
+    }
+
+    if( mComponentIndex == Property::INVALID_COMPONENT_INDEX )
+    {
+      ///Animating the whole property
+
+      //Cast to AnimatableProperty
+      const PropertyInterfaceType* animatableProperty = dynamic_cast< const PropertyInterfaceType* >( baseProperty );
+
+      //Dynamic cast will fail if BaseProperty is not an AnimatableProperty
+      DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+
+      //Create the animator
+      mAnimator = AnimatorType::New( *propertyOwner, *animatableProperty, mAnimatorFunction, mAlphaFunction, mTimePeriod );
+
+    }
+    else
+    {
+      ///Animating a component of the property
+      if ( PropertyTypes::Get< Vector2 >() == baseProperty->GetType() )
+      {
+        // Animate float component of Vector2 property
+
+        // Cast to AnimatableProperty of type Vector2
+        const SceneGraph::AnimatableProperty<Vector2>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector2>* >( baseProperty );
+
+        //Dynamic cast will fail if BaseProperty is not a Vector2 AnimatableProperty
+        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+
+        switch( mComponentIndex )
+        {
+          case 0:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector2> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 1:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector2> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          default:
+          {
+            break;
+          }
+        }
+      }
+      else if ( PropertyTypes::Get< Vector3 >() == baseProperty->GetType() )
+      {
+        // Animate float component of Vector3 property
+
+        // Cast to AnimatableProperty of type Vector3
+        const SceneGraph::AnimatableProperty<Vector3>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector3>* >( baseProperty );
+
+        //Dynamic cast will fail if BaseProperty is not a Vector3 AnimatableProperty
+        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+
+        switch( mComponentIndex )
+        {
+          case 0:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector3> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 1:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector3> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 2:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector3> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          default:
+          {
+            break;
+          }
+        }
+      }
+      else if ( PropertyTypes::Get< Vector4 >() == baseProperty->GetType() )
+      {
+        // Animate float component of Vector4 property
+
+        // Cast to AnimatableProperty of type Vector4
+        const SceneGraph::AnimatableProperty<Vector4>* animatableProperty = dynamic_cast< const SceneGraph::AnimatableProperty<Vector4>* >( baseProperty );
+
+        //Dynamic cast will fail if BaseProperty is not a Vector4 AnimatableProperty
+        DALI_ASSERT_DEBUG( animatableProperty != NULL && "Animating non-animatable property" );
+
+        switch( mComponentIndex )
+        {
+          case 0:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorX<Vector4> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 1:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorY<Vector4> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 2:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorZ<Vector4> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+          case 3:
+          {
+            mAnimator = SceneGraph::Animator< float, PropertyComponentAccessorW<Vector4> >::New( *propertyOwner,
+                                                                                                 *animatableProperty,
+                                                                                                 mAnimatorFunction,
+                                                                                                 mAlphaFunction,
+                                                                                                 mTimePeriod );
+            break;
+          }
+
+          default:
+          {
+            break;
+          }
+        }
+      }
+    }
+
+    DALI_ASSERT_DEBUG( mAnimator != NULL );
+
+    // Add the new SceneGraph::Animator to its correspondent SceneGraph::Animation via message
+    const SceneGraph::Animation* animation = mParent->GetSceneObject();
+    DALI_ASSERT_DEBUG( NULL != animation );
+    AddAnimatorMessage( mParent->GetEventThreadServices(), *animation, *mAnimator );
+  }
+
+protected:
+
+  Object* mObject; ///< Not owned by the animator connector. Valid until ObjectDestroyed() is called.
+  SceneGraph::AnimatorBase* mAnimator;
+
+  Property::Index mPropertyIndex;
+  int mComponentIndex;
+
+  Internal::AnimatorFunctionBase* mAnimatorFunction;  ///< Owned by the animator connector until an Scenegraph::Animator is created
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ANIMATOR_CONNECTOR_H__
diff --git a/dali/internal/event/animation/constrainer.cpp b/dali/internal/event/animation/constrainer.cpp
new file mode 100644 (file)
index 0000000..7e4f6a2
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/constraint-source-impl.h>
+#include <dali/public-api/animation/constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+Constrainer::Constrainer()
+:Object()
+{
+}
+
+Constrainer::~Constrainer()
+{
+  //Remove all the constraints created by the object
+  size_t tag = reinterpret_cast<size_t>( this );
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    //Remove Constrainer from the observers list of the object
+    (*iter)->RemoveObserver( *this );
+
+    //Remove constraints
+    (*iter)->RemoveConstraints( tag );
+  }
+}
+
+void Constrainer::ObjectDestroyed( Object& object )
+{
+  //Remove object from the list of observed
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      mObservedObjects.Erase(iter);
+      return;
+    }
+  }
+}
+
+void Constrainer::Remove( Dali::Handle& target )
+{
+  size_t tag = reinterpret_cast<size_t>( this );
+  Object& object = GetImplementation(target);
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      //Stop observing the object
+      (*iter)->RemoveObserver( *this );
+
+      //Remove constraints created in the object
+      target.RemoveConstraints( tag );
+
+      //Remove object from the vector of observed objects
+      mObservedObjects.Erase(iter);
+    }
+  }
+}
+
+void Constrainer::Observe( Dali::Handle& handle )
+{
+  Object& object = GetImplementation(handle);
+
+  //Add the object to the list of observed objects if it is not in it already
+  const ObjectIter end = mObservedObjects.End();
+  ObjectIter iter = mObservedObjects.Begin();
+  for(; iter != end; ++iter )
+  {
+    if( *iter == &object )
+    {
+      break;
+    }
+  }
+
+  if( iter == end )
+  {
+    //Start observing the object
+    object.AddObserver( *this );
+
+    //Add object in the observed objects vector
+    mObservedObjects.PushBack( &object );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/animation/constrainer.h b/dali/internal/event/animation/constrainer.h
new file mode 100644 (file)
index 0000000..3b56212
--- /dev/null
@@ -0,0 +1,174 @@
+#ifndef __DALI_INTERNAL_CONSTRAINER_H__
+#define __DALI_INTERNAL_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Dali::Vector<Object*>         ObjectContainer;
+typedef ObjectContainer::Iterator     ObjectIter;
+
+/**
+ * An abstract base class for constrainers.
+ * Constrainer base class is responsible or observing constrained objects and remove all the constraints created
+ * when it is destroyed
+ */
+class Constrainer : public Object, public Object::Observer
+{
+public:
+
+  /**
+   * Constructor.
+   */
+  Constrainer();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Constrainer();
+
+public: // Object methods
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const{}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const{return  Property::INVALID_INDEX;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const{return false;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const{return Property::NONE;}
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ){}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const{return Property::Value();}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{return 0;}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{return 0;}
+
+public: // Object::Observer methods
+
+  /**
+   * @copydoc Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded( Object& object ){}
+
+  /**
+   * @copydoc Object::Observer::SceneObjectRemoved()
+   */
+  virtual void SceneObjectRemoved( Object& object ){}
+
+  /**
+   * @copydoc Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed( Object& object );
+
+public:
+
+  /**
+   * @brief Applies the constraint to the target property
+
+   * @param[in] target Property to be constrained
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  virtual void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap) = 0;
+
+  /**
+   * @brief Removes the constraint in the target object
+   *
+   * @param[in] target A handle to an object constrained by the Constrainer
+   */
+  void Remove( Dali::Handle& target );
+
+protected:
+
+  /**
+   * @brief Adds an object to the list of observed objects
+   *
+   * @param[in] handle A handle to the object to be observed
+   */
+  void Observe( Dali::Handle& handle );
+
+private:
+
+  ObjectContainer   mObservedObjects;   ///< The list of object which have been constrained by the Constrainer
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/constraint-base.cpp b/dali/internal/event/animation/constraint-base.cpp
new file mode 100644 (file)
index 0000000..f781543
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/constraint-base.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner-messages.h>
+
+using Dali::Internal::SceneGraph::AnimatableProperty;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ConstraintBase::ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources )
+: mEventThreadServices( *Stage::GetCurrent() ),
+  mTargetObject( &object ),
+  mSceneGraphConstraint( NULL ),
+  mSources( sources ),
+  mObservedObjects(),
+  mTargetPropertyIndex( targetPropertyIndex ),
+  mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
+  mTag( 0 ),
+  mApplied( false ),
+  mSourceDestroyed( false )
+{
+  ObserveObject( object );
+}
+
+ConstraintBase::~ConstraintBase()
+{
+  StopObservation();
+
+  RemoveInternal();
+}
+
+void ConstraintBase::AddSource( Source source )
+{
+  mSources.push_back( source );
+
+  // Observe the object providing this property
+  if ( OBJECT_PROPERTY == source.sourceType )
+  {
+    if ( source.object != NULL )
+    {
+      ObserveObject( *source.object );
+    }
+    else
+    {
+      DALI_LOG_ERROR( "Constraint source object not found" );
+    }
+  }
+}
+
+void ConstraintBase::Apply()
+{
+  if ( mTargetObject && !mApplied && !mSourceDestroyed )
+  {
+    mApplied = true;
+    ConnectConstraint();
+
+    mTargetObject->ApplyConstraint( *this );
+  }
+}
+
+void ConstraintBase::Remove()
+{
+  RemoveInternal();
+
+  if( mTargetObject )
+  {
+    mTargetObject->RemoveConstraint( *this );
+  }
+}
+
+void ConstraintBase::RemoveInternal()
+{
+  if ( mApplied )
+  {
+    mApplied = false;
+
+    // Guard against constraint sending messages during core destruction
+    if( Stage::IsInstalled() )
+    {
+      const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
+
+      if ( propertyOwner &&
+           mSceneGraphConstraint )
+      {
+        // Remove from scene-graph
+        RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
+
+        // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
+        mSceneGraphConstraint = NULL;
+      }
+    }
+  }
+}
+
+Object* ConstraintBase::GetParent()
+{
+  return mTargetObject;
+}
+
+Dali::Handle ConstraintBase::GetTargetObject()
+{
+  return Dali::Handle( mTargetObject );
+}
+
+Property::Index ConstraintBase::GetTargetProperty()
+{
+  return mTargetPropertyIndex;
+}
+
+void ConstraintBase::SetRemoveAction( ConstraintBase::RemoveAction action )
+{
+  mRemoveAction = action;
+}
+
+ConstraintBase::RemoveAction ConstraintBase::GetRemoveAction() const
+{
+  return mRemoveAction;
+}
+
+void ConstraintBase::SetTag(const unsigned int tag)
+{
+  mTag = tag;
+}
+
+unsigned int ConstraintBase::GetTag() const
+{
+  return mTag;
+}
+
+void ConstraintBase::SceneObjectAdded( Object& object )
+{
+  if ( mApplied &&
+       ( NULL == mSceneGraphConstraint ) &&
+       mTargetObject )
+  {
+    ConnectConstraint();
+  }
+}
+
+void ConstraintBase::SceneObjectRemoved( Object& object )
+{
+  if ( mSceneGraphConstraint )
+  {
+    // An input property owning source has been deleted, need to tell the scene-graph-constraint owner to remove it
+    if ( &object != mTargetObject )
+    {
+      const SceneGraph::PropertyOwner* propertyOwner = mTargetObject ? mTargetObject->GetSceneObject() : NULL;
+
+      if( propertyOwner )
+      {
+        // Remove from scene-graph
+        RemoveConstraintMessage( GetEventThreadServices(), *propertyOwner, *(mSceneGraphConstraint) );
+      }
+    }
+
+    // mSceneGraphConstraint will be deleted in update-thread, remove dangling pointer
+    mSceneGraphConstraint = NULL;
+  }
+}
+
+void ConstraintBase::ObjectDestroyed( Object& object )
+{
+  // Remove object pointer from observation set
+  ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
+  DALI_ASSERT_DEBUG( mObservedObjects.End() != iter );
+  mObservedObjects.Erase( iter );
+
+  // Constraint is not useful anymore as an input-source has been destroyed
+  mSourceDestroyed = true;
+
+  // Stop observing the remaining objects
+  StopObservation();
+
+  // Clear our sources as well
+  mSources.clear();
+
+  // Discard all object & scene-graph pointers
+  mSceneGraphConstraint = NULL;
+  mTargetObject = NULL;
+}
+
+void ConstraintBase::ObserveObject( Object& object )
+{
+  ObjectIter iter = std::find( mObservedObjects.Begin(), mObservedObjects.End(), &object );
+  if ( mObservedObjects.End() == iter )
+  {
+    object.AddObserver( *this );
+    mObservedObjects.PushBack( &object );
+  }
+}
+
+void ConstraintBase::StopObservation()
+{
+  const ObjectIter end = mObservedObjects.End();
+  for( ObjectIter iter = mObservedObjects.Begin(); iter != end; ++iter )
+  {
+    (*iter)->RemoveObserver( *this );
+  }
+
+  mObservedObjects.Clear();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/animation/constraint-base.h b/dali/internal/event/animation/constraint-base.h
new file mode 100644 (file)
index 0000000..5b006ed
--- /dev/null
@@ -0,0 +1,238 @@
+#ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__
+#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/internal/event/animation/constraint-source-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class EventThreadServices;
+class Object;
+typedef Dali::Vector<Object*>     ObjectContainer;
+typedef ObjectContainer::Iterator ObjectIter;
+
+namespace SceneGraph
+{
+class ConstraintBase;
+
+template <typename T>
+class AnimatableProperty;
+}
+
+/**
+ * An abstract base class for active constraints.
+ */
+class ConstraintBase : public BaseObject, public Object::Observer
+{
+public:
+
+  typedef Dali::Constraint::RemoveAction RemoveAction;
+
+  /**
+   * Constructor.
+   * @param[in] object The property owning object.
+   * @param[in] messageController Used to send messages to the update-thread.
+   * @param[in] targetPropertyIndex The index of the property being constrained.
+   * @param[in] sources The sources of the input properties.
+   */
+  ConstraintBase( Object& object, Property::Index targetPropertyIndex, SourceContainer& sources );
+
+  /**
+   * Clone this constraint for another object.
+   * @param[in]  object  The object to clone this constraint for
+   * @return A new constraint.
+   */
+  virtual ConstraintBase* Clone( Object& object ) = 0;
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~ConstraintBase();
+
+  /**
+   * Adds a constraint source to the constraint
+   *
+   * @param[in] source The constraint source input to add
+   */
+  void AddSource( Source source );
+
+  /**
+   * @copydoc Dali::Constraint::Apply()
+   */
+  void Apply();
+
+  /**
+   * @copydoc Dali::Constraint::Remove()
+   */
+  void Remove();
+
+  /**
+   * Called when the Constraint is removed.
+   *
+   * @note This removes the scene-object as well but then does not call back into the target-object.
+   */
+  void RemoveInternal();
+
+  /**
+   * Retrieve the parent of the constraint.
+   * @return The parent object, or NULL.
+   */
+  Object* GetParent();
+
+  /**
+   * @copydoc Dali::Constraint::GetTargetObject()
+   */
+  Dali::Handle GetTargetObject();
+
+  /**
+   * @copydoc Dali::Constraint::GetTargetProperty()
+   */
+  Property::Index GetTargetProperty();
+
+  /**
+   * @copydoc Dali::Constraint::SetRemoveAction()
+   */
+  void SetRemoveAction(RemoveAction action);
+
+  /**
+   * @copydoc Dali::Constraint::GetRemoveAction()
+   */
+  RemoveAction GetRemoveAction() const;
+
+  /**
+   * @copydoc Dali::Constraint::SetTag()
+   */
+  void SetTag(const unsigned int tag);
+
+  /**
+   * @copydoc Dali::Constraint::GetTag()
+   */
+  unsigned int GetTag() const;
+
+private: // Object::Observer methods
+
+  /**
+   * @copydoc Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded( Object& object );
+
+  /**
+   * @copydoc Object::Observer::SceneObjectRemoved()
+   */
+  virtual void SceneObjectRemoved( Object& object );
+
+  /**
+   * @copydoc Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed( Object& object );
+
+private:
+
+  /**
+   * Helper to observe an object, if not already observing it
+   */
+  void ObserveObject( Object& object );
+
+  /**
+   * Helper to stop observing objects
+   */
+  void StopObservation();
+
+  // To be implemented in derived classes
+
+  /**
+   * Create and connect a constraint for a scene-object.
+   */
+  virtual void ConnectConstraint() = 0;
+
+protected:
+
+  /**
+   * Get the event thread services object - used for sending messages to the scene graph
+   * Assert if called from the wrong thread.
+   * This is intentionally inline for performance reasons.
+   *
+   * @return The event thread services object
+   */
+  inline EventThreadServices& GetEventThreadServices()
+  {
+    DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() );
+    return mEventThreadServices;
+  }
+
+  /**
+   * Get the event thread services object - used for sending messages to the scene graph
+   * Assert if called from the wrong thread
+   * This is intentionally inline for performance reasons.
+   *
+   * @return The event thread services object
+   */
+  inline const EventThreadServices& GetEventThreadServices() const
+  {
+    DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() );
+    return mEventThreadServices;
+  }
+
+protected:
+  EventThreadServices& mEventThreadServices;
+  Object* mTargetObject; ///< The object owns the constraint.
+  const SceneGraph::ConstraintBase* mSceneGraphConstraint;
+  SourceContainer mSources;
+  ObjectContainer mObservedObjects; // We don't observe the same object twice
+  Property::Index mTargetPropertyIndex;
+  RemoveAction mRemoveAction;
+  unsigned int mTag;
+  bool mApplied:1; ///< Whether the constraint has been applied
+  bool mSourceDestroyed:1; ///< Is set to true if any of our input source objects are destroyed
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ConstraintBase& GetImplementation(Dali::Constraint& constraint)
+{
+  DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" );
+
+  BaseObject& handle = constraint.GetBaseObject();
+
+  return static_cast<Internal::ConstraintBase&>(handle);
+}
+
+inline const Internal::ConstraintBase& GetImplementation(const Dali::Constraint& constraint)
+{
+  DALI_ASSERT_ALWAYS( constraint && "Constraint handle is empty" );
+
+  const BaseObject& handle = constraint.GetBaseObject();
+
+  return static_cast<const Internal::ConstraintBase&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_BASE_H__
diff --git a/dali/internal/event/animation/constraint-impl.h b/dali/internal/event/animation/constraint-impl.h
new file mode 100644 (file)
index 0000000..45d17ab
--- /dev/null
@@ -0,0 +1,578 @@
+#ifndef __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
+#define __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/animation/constraint-base.h>
+#include <dali/internal/event/animation/constraint-source-impl.h>
+#include <dali/internal/event/animation/property-constraint-ptr.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/update/animation/scene-graph-constraint.h>
+#include <dali/internal/update/animation/property-accessor.h>
+#include <dali/internal/update/animation/property-component-accessor.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Helper to add only unique entries to the propertyOwner container
+ * @param propertyOwners to add the entries to
+ * @param object to add
+ */
+inline void AddUnique( SceneGraph::PropertyOwnerContainer& propertyOwners, SceneGraph::PropertyOwner* object )
+{
+  const SceneGraph::PropertyOwnerIter iter = std::find( propertyOwners.Begin(), propertyOwners.End(), object );
+  if( iter == propertyOwners.End() )
+  {
+    // each owner should only be added once
+    propertyOwners.PushBack( object );
+  }
+}
+
+/**
+ * Connects a constraint which takes another property as an input.
+ */
+template < typename PropertyType >
+class Constraint : public ConstraintBase
+{
+public:
+
+  typedef SceneGraph::Constraint< PropertyType, PropertyAccessor<PropertyType> > SceneGraphConstraint;
+  typedef const SceneGraph::AnimatableProperty<PropertyType>* ScenePropertyPtr;
+  typedef typename PropertyConstraintPtr<PropertyType>::Type ConstraintFunctionPtr;
+
+  /**
+   * Construct a new constraint.
+   * @param[in] object The property-owning object.
+   * @param[in] targetIndex The index of the property to constrain.
+   * @param[in] sources The sources of the input properties passed to func.
+   * @param[in] func The constraint function.
+   * @return A newly allocated active-constraint.
+   */
+  static ConstraintBase* New( Object& object,
+                              Property::Index targetIndex,
+                              SourceContainer& sources,
+                              ConstraintFunctionPtr func )
+  {
+    return new Constraint< PropertyType >( object, targetIndex, sources, func );
+  }
+
+  /**
+   * @copydoc ConstraintBase::Clone()
+   */
+  virtual ConstraintBase* Clone( Object& object )
+  {
+    DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
+
+    ConstraintBase* clone( NULL );
+
+    ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
+
+    clone = new Constraint< PropertyType >( object,
+                                            mTargetIndex,
+                                            mSources,
+                                            funcPtr );
+
+    clone->SetRemoveAction(mRemoveAction);
+    clone->SetTag( mTag );
+
+    return clone;
+  }
+
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Constraint()
+  {
+    // This is not responsible for removing constraints.
+  }
+
+private:
+
+  /**
+   * Private constructor; see also Constraint::New().
+   */
+  Constraint( Object& object,
+              Property::Index targetIndex,
+              SourceContainer& sources,
+              ConstraintFunctionPtr& func )
+  : ConstraintBase( object, targetIndex, sources ),
+    mTargetIndex( targetIndex ),
+    mUserFunction( func )
+  {
+  }
+
+  // Undefined
+  Constraint( const Constraint& );
+
+  // Undefined
+  Constraint& operator=( const Constraint& rhs );
+
+  /**
+   * Create and connect a constraint for a scene-object.
+   */
+  void ConnectConstraint()
+  {
+    // Should not come here if target-object has been destroyed
+    DALI_ASSERT_DEBUG( NULL != mTargetObject );
+
+    // Guard against double connections
+    DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
+
+    // Short-circuit until the target scene-object exists
+    SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
+    if ( NULL == targetObject )
+    {
+      return;
+    }
+
+    // Build a container of property-owners, providing the scene-graph properties
+    SceneGraph::PropertyOwnerContainer propertyOwners;
+    propertyOwners.PushBack( targetObject );
+
+    // Build the constraint function; this requires a scene-graph property from each source
+    ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
+
+    if ( func )
+    {
+      // Create the SceneGraphConstraint, and connect to the scene-graph
+
+      const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+
+      // The targetProperty should exist, when targetObject exists
+      DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
+
+      // Connect the constraint
+      SceneGraph::ConstraintBase* sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
+                                                                                     propertyOwners,
+                                                                                     func );
+      DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+      sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+      // object is being used in a separate thread; queue a message to apply the constraint
+      ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+      // Keep a raw-pointer to the scene-graph constraint
+      mSceneGraphConstraint = sceneGraphConstraint;
+    }
+  }
+
+  /**
+   * Helper for ConnectConstraint. Creates a connected constraint-function.
+   * Also populates the property-owner container, for each input connected to the constraint-function.
+   * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
+   * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
+   */
+  PropertyConstraint<PropertyType>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
+  {
+    PropertyConstraint<PropertyType>* func = mUserFunction->Clone();
+
+    for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
+    {
+      Source& source = *iter;
+
+      PropertyInputImpl* inputProperty( NULL );
+      int componentIndex( Property::INVALID_COMPONENT_INDEX );
+
+      if ( OBJECT_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
+
+        // The property owner will not exist, if the target object is off-stage
+        if( NULL != owner )
+        {
+          AddUnique( propertyOwners, owner );
+          inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
+          componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
+
+          // The scene-object property should exist, when the property owner exists
+          DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+        }
+      }
+      else if ( LOCAL_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
+        componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
+
+        // The target scene-object should provide this property
+        DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+      }
+      else
+      {
+        DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
+
+        Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
+
+        // This will not exist, if the target object is off-stage
+        if ( NULL != objectParent )
+        {
+          DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+          SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
+
+          // The property owner will not exist, if the parent object is off-stage
+          if ( NULL != owner )
+          {
+            AddUnique( propertyOwners, owner );
+            inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
+            componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
+
+            // The scene-object property should exist, when the property owner exists
+            DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+          }
+        }
+      }
+
+      if ( NULL == inputProperty )
+      {
+        delete func;
+        func = NULL;
+
+        // Exit if a scene-graph object is not available from one of the sources
+        break;
+      }
+
+      func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
+    }
+
+    return func;
+  }
+
+protected:
+
+  Property::Index mTargetIndex;
+
+  ConstraintFunctionPtr mUserFunction;
+};
+
+/**
+ * Variant which allows float components to be animated individually.
+ */
+template <>
+class Constraint<float> : public ConstraintBase
+{
+public:
+
+  typedef typename PropertyConstraintPtr<float>::Type ConstraintFunctionPtr;
+
+  /**
+   * Construct a new constraint.
+   * @param[in] object The property-owning object.
+   * @param[in] targetIndex The index of the property to constrain.
+   * @param[in] sources The sources of the input properties passed to func.
+   * @param[in] func The constraint function.
+   * @return A newly allocated constraint.
+   */
+  static ConstraintBase* New( Object& object,
+                              Property::Index targetIndex,
+                              SourceContainer& sources,
+                              ConstraintFunctionPtr func )
+  {
+    return new Constraint< float >( object, targetIndex, sources, func );
+  }
+
+  /**
+   * @copydoc ConstraintBase::Clone()
+   */
+  virtual ConstraintBase* Clone( Object& object )
+  {
+    DALI_ASSERT_ALWAYS( !mSourceDestroyed && "An input source object has been destroyed" );
+
+    ConstraintBase* clone( NULL );
+
+    ConstraintFunctionPtr funcPtr( mUserFunction->Clone() );
+
+    clone = new Constraint< float >( object,
+                                     mTargetIndex,
+                                     mSources,
+                                     funcPtr );
+
+    clone->SetRemoveAction(mRemoveAction);
+    clone->SetTag( mTag );
+
+    return clone;
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Constraint()
+  {
+    // This is not responsible for removing constraints.
+  }
+
+private:
+
+  /**
+   * Private constructor; see also Constraint::New().
+   */
+  Constraint( Object& object,
+              Property::Index targetIndex,
+              SourceContainer& sources,
+              ConstraintFunctionPtr& func )
+  : ConstraintBase( object, targetIndex, sources ),
+    mTargetIndex( targetIndex ),
+    mUserFunction( func )
+  {
+  }
+
+  // Undefined
+  Constraint( const Constraint& );
+
+  // Undefined
+  Constraint& operator=( const Constraint& rhs );
+
+  /**
+   * Create and connect a constraint for a scene-object.
+   */
+  void ConnectConstraint()
+  {
+    // Should not come here if target-object has been destroyed
+    DALI_ASSERT_DEBUG( NULL != mTargetObject );
+
+    // Guard against double connections
+    DALI_ASSERT_DEBUG( NULL == mSceneGraphConstraint );
+
+    // Short-circuit until the target scene-object exists
+    SceneGraph::PropertyOwner* targetObject = const_cast< SceneGraph::PropertyOwner* >( mTargetObject->GetSceneObject() );
+    if ( NULL == targetObject )
+    {
+      return;
+    }
+
+    // Build a container of property-owners, providing the scene-graph properties
+    SceneGraph::PropertyOwnerContainer propertyOwners;
+    propertyOwners.PushBack( targetObject );
+
+    // Build the constraint function; this requires a scene-graph property from each source
+    ConstraintFunctionPtr func( ConnectConstraintFunction( propertyOwners ) );
+
+    if ( func )
+    {
+      // Create the SceneGraphConstraint, and connect to the scene-graph
+
+      const SceneGraph::PropertyBase* targetProperty = mTargetObject->GetSceneObjectAnimatableProperty( mTargetIndex );
+
+      // The targetProperty should exist, when targetObject exists
+      DALI_ASSERT_ALWAYS( NULL != targetProperty && "Constraint target property does not exist" );
+
+      const int componentIndex = mTargetObject->GetPropertyComponentIndex( mTargetIndex );
+
+      SceneGraph::ConstraintBase* sceneGraphConstraint( NULL );
+
+      if ( Property::INVALID_COMPONENT_INDEX == componentIndex )
+      {
+        // Not a Vector2, Vector3 or Vector4 component, expecting float type
+        DALI_ASSERT_DEBUG( PropertyTypes::Get< float >() == targetProperty->GetType() );
+
+        typedef SceneGraph::Constraint< float, PropertyAccessor<float> > SceneGraphConstraint;
+
+        sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty,
+                                                           propertyOwners,
+                                                           func );
+      }
+      else
+      {
+        // Expecting Vector2, Vector3 or Vector4 type
+
+        if ( PropertyTypes::Get< Vector2 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector2 property
+
+          if ( 0 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector2> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 1 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector2> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+        }
+        else if ( PropertyTypes::Get< Vector3 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector3 property
+
+          if ( 0 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector3> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 1 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector3> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 2 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector3> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+        }
+        else if ( PropertyTypes::Get< Vector4 >() == targetProperty->GetType() )
+        {
+          // Constrain float component of Vector4 property
+
+          if ( 0 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorX<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 1 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorY<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 2 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorZ<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+          else if ( 3 == componentIndex )
+          {
+            typedef SceneGraph::Constraint< float, PropertyComponentAccessorW<Vector4> > SceneGraphConstraint;
+            sceneGraphConstraint = SceneGraphConstraint::New( *targetProperty, propertyOwners, func );
+          }
+        }
+      }
+
+      DALI_ASSERT_DEBUG( NULL != sceneGraphConstraint );
+      sceneGraphConstraint->SetRemoveAction( mRemoveAction );
+
+        // object is being used in a separate thread; queue a message to apply the constraint
+      ApplyConstraintMessage( GetEventThreadServices(), *targetObject, *sceneGraphConstraint );
+
+      // Keep a raw-pointer to the scene-graph constraint
+      mSceneGraphConstraint = sceneGraphConstraint;
+    }
+  }
+
+  /**
+   * Helper for ConnectConstraint. Creates a connected constraint-function.
+   * Also populates the property-owner container, for each input connected to the constraint-function.
+   * @param[out] propertyOwners The container of property-owners providing the scene-graph properties.
+   * @return A connected constraint-function, or NULL if the scene-graph properties are not available.
+   */
+  PropertyConstraint<float>* ConnectConstraintFunction( SceneGraph::PropertyOwnerContainer& propertyOwners )
+  {
+    PropertyConstraint<float>* func = mUserFunction->Clone();
+
+    for ( SourceIter iter = mSources.begin(); mSources.end() != iter; ++iter )
+    {
+      Source& source = *iter;
+
+      PropertyInputImpl* inputProperty( NULL );
+      int componentIndex( Property::INVALID_COMPONENT_INDEX );
+
+      if ( OBJECT_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( source.object->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( source.object->GetSceneObject() );
+
+        // The property owner will not exist, if the target object is off-stage
+        if( NULL != owner )
+        {
+          AddUnique( propertyOwners, owner );
+          inputProperty = const_cast< PropertyInputImpl* >( source.object->GetSceneObjectInputProperty( source.propertyIndex ) );
+          componentIndex = source.object->GetPropertyComponentIndex( source.propertyIndex );
+
+          // The scene-object property should exist, when the property owner exists
+          DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+        }
+      }
+      else if ( LOCAL_PROPERTY == source.sourceType )
+      {
+        DALI_ASSERT_ALWAYS( mTargetObject->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+        inputProperty = const_cast< PropertyInputImpl* >( mTargetObject->GetSceneObjectInputProperty( source.propertyIndex ) );
+        componentIndex = mTargetObject->GetPropertyComponentIndex( source.propertyIndex );
+
+        // The target scene-object should provide this property
+        DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+      }
+      else
+      {
+        DALI_ASSERT_ALWAYS( PARENT_PROPERTY == source.sourceType && "Constraint source property type is invalid" );
+
+        Object* objectParent = dynamic_cast< Actor& >( *mTargetObject ).GetParent();
+
+        // This will not exist, if the target object is off-stage
+        if ( NULL != objectParent )
+        {
+          DALI_ASSERT_ALWAYS( objectParent->IsPropertyAConstraintInput( source.propertyIndex ) );
+
+          SceneGraph::PropertyOwner* owner = const_cast< SceneGraph::PropertyOwner* >( objectParent->GetSceneObject() );
+
+          // The property owner will not exist, if the parent object is off-stage
+          if ( NULL != owner )
+          {
+            AddUnique( propertyOwners, owner );
+            inputProperty = const_cast< PropertyInputImpl* >( objectParent->GetSceneObjectInputProperty( source.propertyIndex ) );
+            componentIndex = objectParent->GetPropertyComponentIndex( source.propertyIndex );
+
+            // The scene-object property should exist, when the property owner exists
+            DALI_ASSERT_ALWAYS( NULL != inputProperty && "Constraint source property does not exist" );
+          }
+        }
+      }
+
+      if ( NULL == inputProperty )
+      {
+        delete func;
+        func = NULL;
+
+        // Exit if a scene-graph object is not available from one of the sources
+        break;
+      }
+
+      func->SetInput( ( iter - mSources.begin() ), componentIndex, *inputProperty );
+    }
+
+    return func;
+  }
+
+protected:
+
+  Property::Index mTargetIndex;
+
+  ConstraintFunctionPtr mUserFunction;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTIVE_CONSTRAINT_H__
diff --git a/dali/internal/event/animation/constraint-source-impl.h b/dali/internal/event/animation/constraint-source-impl.h
new file mode 100644 (file)
index 0000000..8e1d2c1
--- /dev/null
@@ -0,0 +1,78 @@
+#ifndef __DALI_INTERNAL_CONSTRAINT_SOURCE_H__
+#define __DALI_INTERNAL_CONSTRAINT_SOURCE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/animation/constraint-source.h>
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+struct Source;
+typedef std::vector<Source> SourceContainer;
+typedef SourceContainer::iterator SourceIter;
+
+/**
+ * The source of an input property for a constraint.
+ */
+struct Source
+{
+  /**
+   * Default constructor
+   */
+  Source()
+  : sourceType( OBJECT_PROPERTY ),
+    propertyIndex( Property::INVALID_INDEX ),
+    object( NULL )
+  {
+  }
+
+  /**
+   * Create a constraint source from a public handle.
+   * The internal object is not referenced by the Internal::Source; therefore
+   * the owner of this object is responsible for observing the Object's lifetime.
+   */
+  Source( Dali::ConstraintSource& source )
+  : sourceType( source.sourceType ),
+    propertyIndex( source.propertyIndex ),
+    object( NULL )
+  {
+    if ( source.object )
+    {
+      object = &dynamic_cast< Object& > ( GetImplementation(source.object) );
+    }
+  }
+
+  SourceType sourceType; ///< The source type
+
+  Property::Index propertyIndex; ///< The index of the source property
+
+  Object* object; ///< The target object; only valid if sourceType == OBJECT_PROPERTY
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONSTRAINT_SOURCE_H__
diff --git a/dali/internal/event/animation/key-frame-channel.h b/dali/internal/event/animation/key-frame-channel.h
new file mode 100644 (file)
index 0000000..bba814f
--- /dev/null
@@ -0,0 +1,206 @@
+#ifndef __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__
+#define __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/progress-value.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+class KeyFrameChannelBase
+{
+public:
+  enum KeyFrameChannelId
+  {
+    Translate, Rotate, Scale,
+  };
+
+  KeyFrameChannelBase(KeyFrameChannelId channel_id)
+  : mChannelId(channel_id)
+  {
+  }
+
+  virtual ~KeyFrameChannelBase()
+  {
+  }
+
+  KeyFrameChannelId GetId() const
+  {
+    return mChannelId;
+  }
+
+  virtual bool IsActive(float progress) = 0;
+
+protected:
+  KeyFrameChannelId       mChannelId;
+};
+
+
+template <typename V>
+class KeyFrameChannel : public KeyFrameChannelBase
+{
+public:
+  typedef std::vector<ProgressValue<V> > ProgressValues;
+
+  KeyFrameChannel(KeyFrameChannelId channel_id, ProgressValues& values )
+  : KeyFrameChannelBase(channel_id),
+    mValues(values)
+  {
+  }
+
+
+  virtual ~KeyFrameChannel()
+  {
+  }
+
+  bool IsActive (float progress);
+
+  V GetValue(float progress, Dali::Animation::Interpolation interpolation) const;
+
+  bool FindInterval(typename ProgressValues::iterator& start,
+                    typename ProgressValues::iterator& end,
+                    float progress) const;
+
+  ProgressValues& mValues;
+};
+
+template <class V>
+bool KeyFrameChannel<V>::IsActive (float progress)
+{
+  bool active = false;
+  if(!mValues.empty())
+  {
+    ProgressValue<V>& first = mValues.front();
+
+    if( progress >= first.GetProgress() )
+    {
+      active = true;
+    }
+  }
+  return active;
+}
+
+/**
+ * Use a linear search to find the interval containing progress
+ * TODO: Use binary search instead
+ */
+template <class V>
+bool KeyFrameChannel<V>::FindInterval(
+  typename ProgressValues::iterator& start,
+  typename ProgressValues::iterator& end,
+  float progress) const
+{
+  bool found = false;
+  typename std::vector<ProgressValue<V> >::iterator iter = mValues.begin();
+  typename std::vector<ProgressValue<V> >::iterator prevIter = iter;
+
+  while(iter != mValues.end() && iter->GetProgress() <= progress)
+  {
+    prevIter = iter;
+    ++iter;
+  }
+
+  if(iter == mValues.end())
+  {
+    --prevIter;
+    --iter;
+  }
+
+  if(prevIter->GetProgress() <= progress
+     &&
+     iter->GetProgress() > progress)
+  {
+    found = true;
+    start = prevIter;
+    end   = iter;
+  }
+
+  return found;
+}
+
+template <class V>
+V KeyFrameChannel<V>::GetValue (float progress, Dali::Animation::Interpolation interpolation) const
+{
+  ProgressValue<V>&  firstPV =  mValues.front();
+
+  typename std::vector<ProgressValue<V> >::iterator start;
+  typename std::vector<ProgressValue<V> >::iterator end;
+
+  V interpolatedV = firstPV.GetValue();
+  if(progress >= mValues.back().GetProgress() )
+  {
+    interpolatedV = mValues.back().GetValue(); // This should probably be last value...
+  }
+  else if(FindInterval(start, end, progress))
+  {
+    float frameProgress = (progress - start->GetProgress()) / (end->GetProgress() - start->GetProgress());
+
+    if( interpolation == Dali::Animation::Linear )
+    {
+      Interpolate(interpolatedV, start->GetValue(), end->GetValue(), frameProgress);
+    }
+    else
+    {
+      //Calculate prev and next values
+      V prev;
+      if( start != mValues.begin() )
+      {
+        prev = (start-1)->GetValue();
+      }
+      else
+      {
+        //Project next value through start point
+        prev = start->GetValue() + (start->GetValue()-(start+1)->GetValue());
+      }
+
+      V next;
+      if( end != mValues.end()-1)
+      {
+        next = (end+1)->GetValue();
+      }
+      else
+      {
+        //Project prev value through end point
+        next = end->GetValue() + (end->GetValue()-(end-1)->GetValue());
+      }
+
+      CubicInterpolate(interpolatedV, prev, start->GetValue(), end->GetValue(), next, frameProgress);
+    }
+  }
+
+  return interpolatedV;
+}
+
+typedef KeyFrameChannel<float>      KeyFrameChannelNumber;
+typedef KeyFrameChannel<Vector2>    KeyFrameChannelVector2;
+typedef KeyFrameChannel<Vector3>    KeyFrameChannelVector3;
+typedef KeyFrameChannel<Vector4>    KeyFrameChannelVector4;
+typedef KeyFrameChannel<Quaternion> KeyFrameChannelQuaternion;
+typedef KeyFrameChannel<AngleAxis>  KeyFrameChannelAngleAxis;
+
+
+} // Internal
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_KEY_FRAME_CHANNEL_H__
diff --git a/dali/internal/event/animation/key-frames-impl.cpp b/dali/internal/event/animation/key-frames-impl.cpp
new file mode 100644 (file)
index 0000000..4e0c3ed
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/key-frames-impl.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+KeyFrames* KeyFrames::New()
+{
+  return new KeyFrames();
+}
+
+KeyFrames::KeyFrames()
+  : mType(Property::NONE),
+    mKeyFrames(NULL)
+{
+}
+
+KeyFrames::~KeyFrames()
+{
+}
+
+
+void KeyFrames::CreateKeyFramesSpec(Property::Type type)
+{
+  mType = type;
+  // Now we have a type, can create specific implementation
+  switch(type)
+  {
+    case Property::BOOLEAN:
+    {
+      mKeyFrames = Internal::KeyFrameBoolean::New();
+      break;
+    }
+    case Property::INTEGER:
+    {
+      mKeyFrames = Internal::KeyFrameInteger::New();
+      break;
+    }
+    case Property::FLOAT:
+    {
+      mKeyFrames = Internal::KeyFrameNumber::New();
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      mKeyFrames = Internal::KeyFrameVector2::New();
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      mKeyFrames = Internal::KeyFrameVector3::New();
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      mKeyFrames = Internal::KeyFrameVector4::New();
+      break;
+    }
+    case Property::ROTATION:
+    {
+      mKeyFrames = Internal::KeyFrameQuaternion::New();
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_DEBUG(!"Type not supported");
+      break;
+    }
+  }
+}
+
+Property::Type KeyFrames::GetType() const
+{
+  return mType;
+}
+
+void KeyFrames::Add(float time, Property::Value value, AlphaFunction alpha)
+{
+  if(mType == Property::NONE)
+  {
+    CreateKeyFramesSpec(value.GetType());
+  }
+
+  // Once we have created a type, can only add values of the same type
+  DALI_ASSERT_ALWAYS( mType == value.GetType() && "Can only add values of the same type to a KeyFrame" );
+
+  DALI_ASSERT_DEBUG(mKeyFrames);
+
+  switch(mType)
+  {
+    case Property::BOOLEAN:
+    {
+      Internal::KeyFrameBoolean* kf = static_cast<Internal::KeyFrameBoolean*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<bool>(), alpha);
+      break;
+    }
+    case Property::INTEGER:
+    {
+      Internal::KeyFrameInteger* kf = static_cast<Internal::KeyFrameInteger*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<int>(), alpha);
+      break;
+    }
+    case Property::FLOAT:
+    {
+      Internal::KeyFrameNumber* kf = static_cast<Internal::KeyFrameNumber*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<float>(), alpha);
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      Internal::KeyFrameVector2* kf = static_cast<Internal::KeyFrameVector2*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<Vector2>(), alpha);
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      Internal::KeyFrameVector3* kf = static_cast<Internal::KeyFrameVector3*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<Vector3>(), alpha);
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      Internal::KeyFrameVector4* kf = static_cast<Internal::KeyFrameVector4*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<Vector4>(), alpha);
+      break;
+    }
+    case Property::ROTATION:
+    {
+      Internal::KeyFrameQuaternion* kf = static_cast<Internal::KeyFrameQuaternion*>(mKeyFrames.Get());
+      kf->AddKeyFrame(time, value.Get<Quaternion>(), alpha);
+      break;
+    }
+    default:
+      DALI_ASSERT_DEBUG(!"Type not supported");
+      break;
+  }
+}
+
+KeyFrameSpec* KeyFrames::GetKeyFramesBase() const
+{
+  return mKeyFrames.Get();
+}
+
+} // Internal
+} // Dali
diff --git a/dali/internal/event/animation/key-frames-impl.h b/dali/internal/event/animation/key-frames-impl.h
new file mode 100644 (file)
index 0000000..90a865e
--- /dev/null
@@ -0,0 +1,358 @@
+#ifndef __DALI_INTERNAL_KEY_FRAMES_H__
+#define __DALI_INTERNAL_KEY_FRAMES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/internal/event/animation/progress-value.h>
+#include <dali/internal/event/animation/key-frame-channel.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class KeyFrameSpec;
+class KeyFrames;
+typedef IntrusivePtr<KeyFrames> KeyFramesPtr;
+
+
+/**
+ * KeyFrames class is responsible for creating and building a specialized KeyFrame class
+ * from the Property::Value type used in Add.
+ */
+class KeyFrames : public BaseObject
+{
+public:
+  static KeyFrames* New();
+
+  /**
+   * Instantiate an empty KeyFrames object
+   */
+  KeyFrames();
+
+protected:
+  virtual ~KeyFrames();
+
+private:
+  /**
+   * Don't allow copy constructor
+   */
+  KeyFrames(const KeyFrames& rhs);
+
+  /**
+   * Don't allow copy operator
+   */
+  KeyFrames& operator=(const KeyFrames& rhs);
+
+  /**
+   * Create a specialization from the given type, and store it to the mSpec
+   * member variable
+   */
+  void CreateKeyFramesSpec(Property::Type type);
+
+public:
+  /**
+   * Get the type of this key frame.
+   * An empty key frame will return Property::NONE, wheras an initialised
+   * key frame object will return the type of it's first element.
+   * @return the Property::Type of the key frame values
+   */
+  Property::Type GetType() const;
+
+  /**
+   * Add a key frame. The first key frame to be added denotes the type
+   * of all subsequent key frames. If a value with a different type is
+   * added, it will throw a run time assert.
+   * @param[in] time The time (between 0 and 1)
+   * @param[in] value The value of the keyframe at the given time
+   * @param[in] alpha An alpha function to blend between this key frame and the
+   * next key frame.
+   */
+  void Add(float time, Property::Value value, AlphaFunction alpha);
+
+  /**
+   * Return the key frames without specialization. The GetSpecialization methods
+   * below will convert to the specialized objects.
+   */
+  KeyFrameSpec* GetKeyFramesBase() const;
+
+private:
+  Dali::Property::Type mType; // Type of the specialization
+  IntrusivePtr<KeyFrameSpec> mKeyFrames;   // Pointer to the specialized key frame object
+};
+
+
+/**
+ * This is the base class for the individual template specializations, allowing a ptr to be
+ * stored in the handle object above. It inherits from RefObject to allow smart pointers
+ * to be used for the specializations. Note that the derived template class below
+ * allows for a copy constructor so that the specialization object can be cloned before
+ * being passed to the scene-graph for animation.
+ */
+class KeyFrameSpec : public RefObject
+{
+public:
+
+  KeyFrameSpec() {}
+
+  virtual unsigned int GetNumberOfKeyFrames() const = 0;
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~KeyFrameSpec() {}
+};
+
+
+/**
+ * The base template class for each key frame specialization. It stores a vector of
+ * ProgressValue pairs in mPVs, and uses the existing interface for KeyFrameChannel
+ * to point at this vector.
+ * TODO: Incorporate KeyFrameChannel into this base template
+ */
+template<typename V>
+class KeyFrameBaseSpec : public KeyFrameSpec
+{
+private:
+  typedef ProgressValue<V> PV;
+  typedef std::vector<PV> PVContainer;
+
+  PVContainer                    mPVs;       // The ProgressValue pairs
+  KeyFrameChannel<V>*            mKeyFrames; // The key frame interpolator
+
+public:
+  static KeyFrameBaseSpec<V>* New()
+  {
+    return new KeyFrameBaseSpec<V>();
+  }
+
+  static KeyFrameBaseSpec<V>* Clone(const KeyFrameBaseSpec<V>& keyFrames)
+  {
+    return new KeyFrameBaseSpec<V>(keyFrames);
+  }
+
+  /**
+   * Constructor
+   */
+  KeyFrameBaseSpec<V>()
+  {
+    mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
+  }
+
+protected:
+  /**
+   * Copy Constructor
+   * Allow cloning of this object
+   */
+  KeyFrameBaseSpec<V>(const KeyFrameBaseSpec<V>& keyFrames)
+  : mPVs(keyFrames.mPVs)
+  {
+    mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
+  }
+
+  KeyFrameBaseSpec<V>& operator=( const KeyFrameBaseSpec<V>& keyFrames )
+  {
+    mPVs.clear();
+    mPVs = keyFrames.mPVs;
+    delete mKeyFrames;
+    mKeyFrames = new KeyFrameChannel<V>(KeyFrameChannelBase::Translate, mPVs);
+    return *this;
+  }
+
+  /**
+   * Destructor. Ensure progress value pairs are cleared down
+   */
+  virtual ~KeyFrameBaseSpec<V>()
+  {
+    delete mKeyFrames;
+    mPVs.clear();
+  }
+
+public:
+  /**
+   * Add a key frame to the progress value vector. Key frames should be added
+   * in time order (this method does not sort the vector by time)
+   * @param[in] t - progress
+   * @param[in] v - value
+   * @param[in] alpha - Alpha function for blending to the next keyframe
+   */
+  void AddKeyFrame(float t, V v, AlphaFunction alpha)
+  {
+    // TODO:: Support alpha
+    mPVs.push_back(PV(t, v));
+  }
+
+  /**
+   * Get the number of key frames
+   * @return The size of the progress value vector
+   */
+  virtual unsigned int GetNumberOfKeyFrames() const
+  {
+    return mPVs.size();
+  }
+
+  /**
+   * Get a key frame.
+   * @param[in] index The index of the key frame to fetch
+   * @param[out] time The progress of the given key frame
+   * @param[out] value The value of the given key frame
+   */
+  virtual void GetKeyFrame(unsigned int index, float& time, V& value) const
+  {
+    DALI_ASSERT_ALWAYS( index < mPVs.size() && "KeyFrame index is out of bounds" );
+    time  = mPVs[index].mProgress;
+    value = mPVs[index].mValue;
+  }
+
+  /**
+   * Return whether the progress is valid for the range of keyframes. (The first
+   * keyframe doesn't have to start at 0, and the last doesn't have to end at 1.0)
+   * @param[in] progress The progress to test
+   * @return True if the progress is valid for this object
+   */
+  bool IsActive(float progress) const
+  {
+    return mKeyFrames->IsActive(progress);
+  }
+
+  /**
+   * Return an interpolated value for the given progress.
+   * @param[in] progress The progress to test
+   * @return The interpolated value
+   */
+  V GetValue(float progress, Dali::Animation::Interpolation interpolation) const
+  {
+    return mKeyFrames->GetValue(progress, interpolation);
+  }
+};
+
+typedef KeyFrameBaseSpec<float>          KeyFrameNumber;
+typedef KeyFrameBaseSpec<bool>           KeyFrameBoolean;
+typedef KeyFrameBaseSpec<int>            KeyFrameInteger;
+typedef KeyFrameBaseSpec<Vector2>        KeyFrameVector2;
+typedef KeyFrameBaseSpec<Vector3>        KeyFrameVector3;
+typedef KeyFrameBaseSpec<Vector4>        KeyFrameVector4;
+typedef KeyFrameBaseSpec<Quaternion>     KeyFrameQuaternion;
+
+typedef IntrusivePtr<KeyFrameBoolean>         KeyFrameBooleanPtr;
+typedef IntrusivePtr<KeyFrameNumber>          KeyFrameNumberPtr;
+typedef IntrusivePtr<KeyFrameInteger>         KeyFrameIntegerPtr;
+typedef IntrusivePtr<KeyFrameVector2>         KeyFrameVector2Ptr;
+typedef IntrusivePtr<KeyFrameVector3>         KeyFrameVector3Ptr;
+typedef IntrusivePtr<KeyFrameVector4>         KeyFrameVector4Ptr;
+typedef IntrusivePtr<KeyFrameQuaternion>      KeyFrameQuaternionPtr;
+
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameBoolean*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameBoolean*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameBoolean*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameBoolean*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameNumber*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameNumber*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameNumber*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameNumber*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameInteger*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameInteger*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameInteger*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameInteger*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector2*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameVector2*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector2*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameVector2*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector3*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameVector3*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector3*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameVector3*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameVector4*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameVector4*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameVector4*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameVector4*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(Internal::KeyFrames& keyFrames, Internal::KeyFrameQuaternion*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<Internal::KeyFrameQuaternion*>(keyFrames.GetKeyFramesBase());
+}
+
+inline void GetSpecialization(const Internal::KeyFrames& keyFrames, const Internal::KeyFrameQuaternion*& keyFrameSpec)
+{
+  keyFrameSpec = static_cast<const Internal::KeyFrameQuaternion*>(keyFrames.GetKeyFramesBase());
+}
+
+} // Internal
+
+
+// Get impl of handle
+inline Internal::KeyFrames& GetImplementation(Dali::KeyFrames& keyFrames)
+{
+  DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" );
+  Dali::RefObject& object = keyFrames.GetBaseObject();
+  return static_cast<Internal::KeyFrames&>(object);
+}
+
+inline const Internal::KeyFrames& GetImplementation(const Dali::KeyFrames& keyFrames)
+{
+  DALI_ASSERT_ALWAYS( keyFrames && "KeyFrames handle is empty" );
+  const Dali::RefObject& object = keyFrames.GetBaseObject();
+  return static_cast<const Internal::KeyFrames&>(object);
+}
+
+
+} // Dali
+
+#endif //__DALI_INTERNAL_KEY_FRAMES_H__
diff --git a/dali/internal/event/animation/linear-constrainer-impl.cpp b/dali/internal/event/animation/linear-constrainer-impl.cpp
new file mode 100644 (file)
index 0000000..11ef59e
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/linear-constrainer-impl.h>
+
+//EXTRENAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/object/property-array.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+//              Name            Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "value",        ARRAY,     true,    false,       false,        Dali::LinearConstrainer::Property::VALUE )
+DALI_PROPERTY( "progress",     ARRAY,     true,    false,       false,        Dali::LinearConstrainer::Property::PROGRESS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+} //Unnamed namespace
+
+LinearConstrainer* LinearConstrainer::New()
+{
+  return new LinearConstrainer();
+}
+
+LinearConstrainer::LinearConstrainer()
+: Constrainer()
+{
+}
+
+LinearConstrainer::~LinearConstrainer()
+{
+}
+
+unsigned int LinearConstrainer::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void LinearConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* LinearConstrainer::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out of range
+  return NULL;
+}
+
+Property::Index LinearConstrainer::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) )
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type LinearConstrainer::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range
+  return Property::NONE;
+}
+
+Property::Value LinearConstrainer::GetDefaultProperty( Property::Index index ) const
+{
+  if( index == Dali::LinearConstrainer::Property::VALUE )
+  {
+    Property::Value value( Property::ARRAY );
+    Property::Array* array = value.GetArray();
+    size_t count( mValue.Size() );
+
+    if( array )
+    {
+      array->Reserve( count );
+      for( size_t i( 0 ); i != count; ++i )
+      {
+        array->PushBack( mValue[i] );
+      }
+    }
+    return value;
+  }
+  else if( index == Dali::LinearConstrainer::Property::PROGRESS )
+  {
+    Property::Value value( Property::ARRAY );
+    Property::Array* array = value.GetArray();
+    size_t count( mValue.Size() );
+
+    if( array )
+    {
+      array->Reserve( count );
+      for( size_t i( 0 ); i != count; ++i )
+      {
+        array->PushBack( mProgress[i] );
+      }
+    }
+    return value;
+  }
+
+  return Property::Value();
+}
+
+void LinearConstrainer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  const Property::Array* array = propertyValue.GetArray();
+  if( array )
+  {
+    size_t propertyArrayCount = array->Count();
+    if( index == Dali::LinearConstrainer::Property::VALUE  )
+    {
+      mValue.Clear(); // remove old values
+      mValue.Resize( propertyArrayCount );
+      for( size_t i(0); i != propertyArrayCount; ++i )
+      {
+        array->GetElementAt( i ).Get( mValue[ i ] );
+      }
+    }
+    else if( index == Dali::LinearConstrainer::Property::PROGRESS  )
+    {
+      mProgress.Clear(); // remove old values
+      mProgress.Resize( propertyArrayCount );
+      for( size_t i(0); i != propertyArrayCount; ++i )
+      {
+        array->GetElementAt( i ).Get( mProgress[ i ] );
+      }
+    }
+  }
+}
+
+bool LinearConstrainer::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+
+  return false;
+}
+
+bool LinearConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+
+  return false;
+}
+
+bool LinearConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+
+  return false;
+}
+
+void LinearConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap)
+{
+  Dali::Constraint constraint = Dali::Constraint::New<float>( target.object, target.propertyIndex, LinearConstraintFunctor( mValue, mProgress, range, wrap ) );
+  constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+  constraint.SetTag( reinterpret_cast<size_t>( this ) );
+  constraint.SetRemoveAction( Dali::Constraint::Discard );
+  constraint.Apply();
+
+
+  //Start observing the object
+  Observe( target.object );
+}
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/event/animation/linear-constrainer-impl.h b/dali/internal/event/animation/linear-constrainer-impl.h
new file mode 100644 (file)
index 0000000..d9d607d
--- /dev/null
@@ -0,0 +1,257 @@
+#ifndef __DALI_INTERNAL_LINEAR_CONSTRAINER_H__
+#define __DALI_INTERNAL_LINEAR_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/constrainer.h>
+#include <dali/public-api/animation/linear-constrainer.h>
+#include <dali/public-api/math/math-utils.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef IntrusivePtr<LinearConstrainer> LinearConstrainerPtr;
+
+/**
+ * @brief Constraint functor to constraint properties given a linear map.
+ */
+struct LinearConstraintFunctor
+{
+  /**
+   * @brief Constructor.
+   *
+   * @param[in] value The list of values for the linear map (f(x) of the linear map)
+   * @param[in] progress Progress for each of the values normalized to [0,1] ( x of the linear map)
+   * @param[in] range The range of values in the input property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   *
+   * @note If progress is an empty vector, the values will be assumed to be equally spaced in the x-axis
+   */
+  LinearConstraintFunctor( Dali::Vector<float>& value, Dali::Vector<float>& progress, const Vector2& range, const Vector2& wrap )
+  :mValue(value),
+   mProgress(progress),
+   mRange(range),
+   mWrap(wrap)
+  {}
+
+  /**
+   * @brief Functor operator for float properties
+   *
+   * @param[in,out] position Current value of the property
+   * @param[in]     inputs Contains the input property used as the parameter for the path
+   *
+   * @return The value of the linear map at the given parameter.
+   */
+  void operator()( float& value,
+                   const PropertyInputContainer& inputs)
+  {
+    size_t valueCount(  mValue.Size() );
+    if( valueCount == 0 )
+    {
+      //No values.
+    }
+    else if(valueCount == 1 )
+    {
+      value = mValue[0];
+    }
+    else
+    {
+      float inputWrapped = inputs[0]->GetFloat();
+      if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+      {
+        inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+      }
+
+      float t = (( inputWrapped - mRange.x ) / ( mRange.y-mRange.x ));
+
+      //Find min and max values and local t between them
+      size_t min(0);
+      size_t max(0);
+      float tLocal(0.0f);
+      if( mProgress.Size() < valueCount )
+      {
+        float step = 1.0f / (valueCount-1.0f);
+        float tLocation = t/step;
+        if( tLocation < 0)
+        {
+          min = 0;
+          max = 1;
+        }
+        else if( tLocation >= valueCount-1 )
+        {
+          min = max = valueCount-1;
+        }
+        else
+        {
+          min = static_cast<size_t>(tLocation);
+          max = min+1;
+        }
+
+        tLocal =(t - min*step) / step;
+      }
+      else
+      {
+        while( t >= mProgress[min] && min < valueCount-1 )
+        {
+          min++;
+        }
+
+        min--;
+        max = min+1;
+
+        if( min >= valueCount-1)
+        {
+          min = max = valueCount-1;
+          tLocal = 0.0f;
+        }
+        else
+        {
+          tLocal =(t - mProgress[min]) / ( mProgress[max]-mProgress[min]);
+        }
+      }
+
+      //Linear interpolation
+      value = (mValue[max]-mValue[min])*tLocal + mValue[min];
+    }
+  }
+
+
+  Dali::Vector<float> mValue;     ///< values for the linear map
+  Dali::Vector<float> mProgress;  ///< Progress for each of the values normalized to [0,1]
+  Vector2             mRange;     ///< The range of values in the input property which will be mapped to 0..1
+  Vector2             mWrap;      ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1]
+};
+
+/**
+ * @brief A LinearConstrainer used to constraint properties given a linear map
+ */
+class LinearConstrainer : public Constrainer
+{
+public:
+
+  /**
+   * Create a new LinearConstrainer
+   * @return A smart-pointer to the newly allocated LinearConstrainer.
+   */
+  static LinearConstrainer* New();
+
+protected:
+
+  /**
+   * virtual destructor
+   */
+  virtual ~LinearConstrainer();
+
+private:
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+   /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+public:
+
+  /**
+   * @copydoc Dali::PathConstrainer::Apply
+   */
+  void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap );
+
+private:
+
+  //Constructor
+  LinearConstrainer();
+
+  // Undefined
+  LinearConstrainer(const LinearConstrainer&);
+
+  // Undefined
+  LinearConstrainer& operator=(const LinearConstrainer& rhs);
+
+  Dali::Vector<float> mValue;     ///< values for the linear map
+  Dali::Vector<float> mProgress;  ///< Progress for each of the values normalized to [0,1]
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::LinearConstrainer& GetImplementation(Dali::LinearConstrainer& linearConstrainer)
+{
+  DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" );
+  Dali::RefObject& object = linearConstrainer.GetBaseObject();
+  return static_cast<Internal::LinearConstrainer&>(object);
+}
+
+inline const Internal::LinearConstrainer& GetImplementation(const Dali::LinearConstrainer& linearConstrainer)
+{
+  DALI_ASSERT_ALWAYS( linearConstrainer && "LinearConstrainer handle is empty" );
+  const Dali::RefObject& object = linearConstrainer.GetBaseObject();
+  return static_cast<const Internal::LinearConstrainer&>(object);
+}
+
+} // Dali
+
+#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/path-constrainer-impl.cpp b/dali/internal/event/animation/path-constrainer-impl.cpp
new file mode 100644 (file)
index 0000000..8097cc9
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/path-constrainer-impl.h>
+
+//EXTRENAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/object/property-array.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+//              Name             Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "forward",       VECTOR3,   true,    false,       false,        Dali::PathConstrainer::Property::FORWARD )
+DALI_PROPERTY( "points",         ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::POINTS )
+DALI_PROPERTY( "control-points", ARRAY,    true,    false,       false,        Dali::PathConstrainer::Property::CONTROL_POINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+} //Unnamed namespace
+
+PathConstrainer* PathConstrainer::New()
+{
+  return new PathConstrainer();
+}
+
+PathConstrainer::PathConstrainer()
+: Constrainer(),
+  mPath( Path::New() )
+{
+}
+
+PathConstrainer::~PathConstrainer()
+{
+}
+
+unsigned int PathConstrainer::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void PathConstrainer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* PathConstrainer::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out of range
+  return NULL;
+}
+
+Property::Index PathConstrainer::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type PathConstrainer::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range
+  return Property::NONE;
+}
+
+Property::Value PathConstrainer::GetDefaultProperty( Property::Index index ) const
+{
+  if( index == Dali::PathConstrainer::Property::FORWARD )
+  {
+    return Property::Value( mForward );
+  }
+  else
+  {
+    if( index == Dali::PathConstrainer::Property::POINTS )
+    {
+      Property::Value value( Property::ARRAY );
+      Property::Array* array = value.GetArray();
+      const Dali::Vector<Vector3>& point = mPath->GetPoints();
+      Property::Array::SizeType pointCount = point.Size();
+
+      if( array )
+      {
+        array->Reserve( pointCount );
+        for( Property::Array::SizeType i = 0; i < pointCount; ++i )
+        {
+          array->PushBack( point[i] );
+        }
+      }
+      return value;
+    }
+    else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
+    {
+      Property::Value value( Property::ARRAY );
+      Property::Array* array = value.GetArray();
+      const Dali::Vector<Vector3>& point = mPath->GetControlPoints();
+      Property::Array::SizeType pointCount = point.Size();
+
+      if( array )
+      {
+        array->Reserve( pointCount );
+        for( Property::Array::SizeType i = 0; i < pointCount; ++i )
+        {
+          array->PushBack( point[i] );
+        }
+      }
+      return value;
+    }
+  }
+
+  return Property::Value();
+}
+
+void PathConstrainer::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  if( index == Dali::PathConstrainer::Property::FORWARD )
+  {
+    propertyValue.Get(mForward);
+  }
+  else if( index == Dali::PathConstrainer::Property::POINTS  )
+  {
+    const Property::Array* array = propertyValue.GetArray();
+    mPath->ClearPoints();
+    if( array )
+    {
+      for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i )
+      {
+        Vector3 point;
+        array->GetElementAt( i ).Get( point );
+        mPath->AddPoint( point );
+      }
+    }
+  }
+  else if( index == Dali::PathConstrainer::Property::CONTROL_POINTS )
+  {
+    const Property::Array* array = propertyValue.GetArray();
+    mPath->ClearControlPoints();
+    if( array )
+    {
+      for( Property::Array::SizeType i = 0, count = array->Count(); i < count; ++i )
+      {
+        Vector3 point;
+        array->GetElementAt( i ).Get( point );
+        mPath->AddControlPoint( point );
+      }
+    }
+  }
+}
+
+bool PathConstrainer::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+
+  return false;
+}
+
+bool PathConstrainer::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+
+  return false;
+}
+
+bool PathConstrainer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+
+  return false;
+}
+
+void PathConstrainer::Apply( Property target, Property source, const Vector2& range, const Vector2& wrap)
+{
+  Dali::Property::Type propertyType = target.object.GetPropertyType( target.propertyIndex);
+  if( propertyType == Dali::Property::VECTOR3)
+  {
+    // If property type is Vector3, constrain its value to the position of the path
+    Dali::Constraint constraint = Dali::Constraint::New<Vector3>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, wrap ) );
+    constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    constraint.Apply();
+  }
+  else if( propertyType == Dali::Property::ROTATION )
+  {
+    // If property type is Rotation, constrain its value to align the forward vector to the tangent of the path
+    Dali::Constraint constraint = Dali::Constraint::New<Quaternion>( target.object, target.propertyIndex, PathConstraintFunctor( mPath, range, mForward, wrap) );
+    constraint.AddSource( Dali::Source(source.object, source.propertyIndex ) );
+
+    constraint.SetTag( reinterpret_cast<size_t>( this ) );
+    constraint.SetRemoveAction( Dali::Constraint::Discard );
+    constraint.Apply();
+  }
+
+  //Start observing the object
+  Observe( target.object );
+}
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/event/animation/path-constrainer-impl.h b/dali/internal/event/animation/path-constrainer-impl.h
new file mode 100644 (file)
index 0000000..e988321
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef __DALI_INTERNAL_PATH_CONSTRAINER_H__
+#define __DALI_INTERNAL_PATH_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/constrainer.h>
+#include <dali/devel-api/animation/path-constrainer.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef IntrusivePtr<PathConstrainer> PathConstrainerPtr;
+
+/**
+ * @brief Constraint functor to constraint properties to paths.
+ *
+ * Vector3 properties will be constrained to the position of the path and
+ * Rotation properties will be constrained to follow the tangent of the path
+ * given a forward vector in object's local space.
+ */
+struct PathConstraintFunctor
+{
+  /**
+   * @brief Constructor.
+   *
+   * @param[in] path The path used in the constraint
+   * @param[in] range The range of values in the input property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  PathConstraintFunctor(PathPtr path, const Vector2& range, const Vector2& wrap ):mPath(path),mRange(range),mWrap(wrap){}
+
+  /**
+   * @brief Constructor.
+   *
+   * @param[in] path The path used in the constraint
+   * @param[in] range The range of values in the input property which will be mapped to 0..1
+   * @param[in] forward Vector in object space which will be aligned with the tangent of the path
+   * @param[in] wrap Wrapping domain. Input property value will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  PathConstraintFunctor(PathPtr path, const Vector2& range,const Vector3& forward, const Vector2& wrap ):mPath(path),mForward(forward),mRange(range),mWrap(wrap){}
+
+  /**
+   * @brief Functor operator for Vector3 properties
+   *
+   * @param[in,out] position Current value of the property
+   * @param[in]     inputs Contains the input property used as the parameter for the path
+   *
+   * @return The position of the path at the given parameter.
+   */
+  void operator()( Vector3& position,
+                   const PropertyInputContainer& inputs)
+  {
+    float inputWrapped = inputs[0]->GetFloat();
+    if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+    {
+      inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+    }
+
+    float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x );
+
+    Vector3 tangent;
+    mPath->Sample( t, position, tangent );
+  }
+
+  /**
+   * @brief Functor operator for Quaternion properties
+   *
+   * @param[in,out] current Current value of the property
+   * @param[in]     inputs Contains the input property used as the parameter for the path
+   *
+   * @return The rotation which will align the forward vector and the tangent of the path at the given parameter.
+   */
+  void operator()( Quaternion& current,
+                   const PropertyInputContainer& inputs)
+  {
+    float inputWrapped = inputs[0]->GetFloat();
+    if( inputWrapped < mWrap.x || inputWrapped > mWrap.y )
+    {
+      inputWrapped = WrapInDomain(inputWrapped, mWrap.x, mWrap.y);
+    }
+
+    float t = ( inputWrapped - mRange.x ) / ( mRange.y-mRange.x );
+
+    Vector3 position, tangent;
+    mPath->Sample( t, position, tangent );
+    current = Quaternion( mForward, tangent );
+  }
+
+  PathPtr     mPath;      ///< The path used
+  Vector3     mForward;   ///< Vector in object space which will be aligned with the tangent of the path
+  Vector2     mRange;     ///< The range of values in the input property which will be mapped to 0..1
+  Vector2     mWrap;      ///< Wrapping domain. Input property will be wrapped in this domain before being mapped to [0,1]
+};
+
+/**
+ * @brief A PathConstrainer used to constraint properties to a path
+ */
+class PathConstrainer : public Constrainer
+{
+public:
+
+  /**
+   * Create a new PathConstrainer
+   * @return A smart-pointer to the newly allocated PathConstrainer.
+   */
+  static PathConstrainer* New();
+
+protected:
+
+  /**
+   * virtual destructor
+   */
+  virtual ~PathConstrainer();
+
+private:
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+   /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+public:
+
+  /**
+   * @copydoc Dali::PathConstrainer::Apply
+   */
+  void Apply( Property target, Property source, const Vector2& range, const Vector2& wrap );
+
+private:
+
+  //Constructor
+  PathConstrainer();
+
+  // Undefined
+  PathConstrainer(const PathConstrainer&);
+
+  // Undefined
+  PathConstrainer& operator=(const PathConstrainer& rhs);
+
+  PathPtr mPath;    ///< The path used in the constraints
+  Vector3 mForward; ///< Vector in object space which will be aligned with the tangent of the path
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::PathConstrainer& GetImplementation(Dali::PathConstrainer& pathConstrainer)
+{
+  DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" );
+  Dali::RefObject& object = pathConstrainer.GetBaseObject();
+  return static_cast<Internal::PathConstrainer&>(object);
+}
+
+inline const Internal::PathConstrainer& GetImplementation(const Dali::PathConstrainer& pathConstrainer)
+{
+  DALI_ASSERT_ALWAYS( pathConstrainer && "PathConstrainer handle is empty" );
+  const Dali::RefObject& object = pathConstrainer.GetBaseObject();
+  return static_cast<const Internal::PathConstrainer&>(object);
+}
+
+} // Dali
+
+#endif //__DALI_INTERNAL_PATH_CONSTRAINER_H__
diff --git a/dali/internal/event/animation/path-impl.cpp b/dali/internal/event/animation/path-impl.cpp
new file mode 100644 (file)
index 0000000..ad34ce7
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/animation/path-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/public-api/object/property-array.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+//              Name             Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "points",         ARRAY, true, false, false,   Dali::Path::Property::POINTS         )
+DALI_PROPERTY( "control-points", ARRAY, true, false, false,   Dali::Path::Property::CONTROL_POINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+/**
+ * These coefficient arise from the cubic polynomial equations for
+ * a bezier curve.
+ *
+ * A bezier curve is defined by a cubic polynomial. Given two end points p0 and p1
+ * and two control points cp0 and cp1, the bezier curve will be defined by a polynomial in the form
+ * f(x) = a3*x^3 + a2*x^2 + a1*x + a0 with this restrictions:
+ * f(0) = p0
+ * f(1) = p1
+ * f'(0) = 3*(cp0 - p0)
+ * f'(1) = 3*(p1-cp1)
+ */
+const float BezierBasisCoeff[] = {  -1.0f,  3.0f, -3.0f, 1.0f,
+                                     3.0f, -6.0f,  3.0f, 0.0f,
+                                    -3.0f,  3.0f,  0.0f, 0.0f,
+                                     1.0f,  0.0f,  0.0f, 0.0f  };
+
+const Dali::Matrix BezierBasis = Dali::Matrix( BezierBasisCoeff );
+
+} //Unnamed namespace
+
+Path* Path::New()
+{
+  return new Path();
+}
+
+Path::Path()
+: Object()
+{
+}
+
+Path::~Path()
+{
+}
+
+Path* Path::Clone(const Path& path)
+{
+  Path* clone = new Path();
+  clone->SetPoints( path.GetPoints() );
+  clone->SetControlPoints( path.GetControlPoints() );
+
+  return clone;
+}
+
+unsigned int Path::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void Path::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* Path::GetDefaultPropertyName(Property::Index index) const
+{
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  // index out of range
+  return NULL;
+}
+
+Property::Index Path::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+Property::Type Path::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range
+  return Property::NONE;
+}
+
+Property::Value Path::GetDefaultProperty( Property::Index index ) const
+{
+  if( index == Dali::Path::Property::POINTS )
+  {
+    Property::Value value( Property::ARRAY );
+    Property::Array* array = value.GetArray();
+    Property::Array::SizeType pointCount = mPoint.Count();
+
+    if( array )
+    {
+      array->Reserve( pointCount );
+      for( Property::Array::SizeType i = 0; i < pointCount; ++i )
+      {
+        array->PushBack( mPoint[i] );
+      }
+    }
+    return value;
+  }
+  else if( index == Dali::Path::Property::CONTROL_POINTS )
+  {
+    Property::Value value( Property::ARRAY );
+    Property::Array* array = value.GetArray();
+    Property::Array::SizeType  controlpointCount = mControlPoint.Count();
+
+    if( array )
+    {
+      array->Reserve( controlpointCount );
+      for( Property::Array::SizeType i = 0; i < controlpointCount; ++i )
+      {
+        array->PushBack( mControlPoint[i] );
+      }
+    }
+    return value;
+  }
+
+  return Property::Value();
+}
+
+void Path::SetDefaultProperty(Property::Index index, const Property::Value& propertyValue)
+{
+  const Property::Array* array = propertyValue.GetArray();
+  if( array )
+  {
+    Property::Array::SizeType propertyArrayCount = array->Count();
+    if( index == Dali::Path::Property::POINTS )
+    {
+      mPoint.Reserve( propertyArrayCount );
+      for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i )
+      {
+        Vector3 point;
+        array->GetElementAt( i ).Get( point );
+        mPoint.PushBack( point );
+      }
+    }
+    else if( index == Dali::Path::Property::CONTROL_POINTS )
+    {
+      mControlPoint.Reserve( propertyArrayCount );
+      for( Property::Array::SizeType i = 0; i < propertyArrayCount; ++i )
+      {
+        Vector3 point;
+        array->GetElementAt( i ).Get( point );
+        mControlPoint.PushBack( point );
+      }
+    }
+  }
+}
+
+bool Path::IsDefaultPropertyWritable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].writable;
+  }
+
+  return false;
+}
+
+bool Path::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].animatable;
+  }
+
+  return false;
+}
+
+bool Path::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+  }
+
+  return false;
+}
+
+void Path::AddPoint(const Vector3& point )
+{
+  mPoint.PushBack( point );
+}
+
+void Path::AddControlPoint(const Vector3& point )
+{
+  mControlPoint.PushBack( point );
+}
+
+unsigned int Path::GetNumberOfSegments() const
+{
+  return (mPoint.Size()>1)?mPoint.Size()-1:0;
+}
+
+void Path::GenerateControlPoints( float curvature )
+{
+  unsigned int numSegments = GetNumberOfSegments();
+  DALI_ASSERT_ALWAYS( numSegments > 0 && "Need at least 1 segment to generate control points" ); // need at least 1 segment
+
+  mControlPoint.Resize( numSegments * 2);
+
+  //Generate two control points for each segment
+  for( unsigned int i(0); i<numSegments; ++i )
+  {
+    //Segment end-points
+    Vector3 p1 = mPoint[i];
+    Vector3 p2 = mPoint[i+1];
+
+    Vector3 p0;
+    if( i == 0 )
+    {
+      //There's no previous point. We chose a point in the line defined by the two end points  at
+      //a 1/8th of the distance between them.
+      p0 = p1 - (p2 - p1)/8.0f;
+    }
+    else
+    {
+      //Previous point
+      p0 = mPoint[i-1];
+    }
+
+    Vector3 p3;
+    if( i == numSegments - 1)
+    {
+      //There's no next point. We chose a point in the line defined by the two end points  at
+      //a 1/8th of the distance between them.
+      p3 = p2 - (p1 - p2)/8.0f;
+    }
+    else
+    {
+      //Next point
+      p3 = mPoint[i+2];
+    }
+
+    Vector3 p0p1 = p1 - p0;
+    Vector3 p1p2 = p2 - p1;
+    Vector3 p2p3 = p3 - p2;
+
+    float length = p1p2.Length();
+
+    Vector3 tangentOut = ( p0p1*length + p1p2*p0p1.Length() ) * 0.5f;
+    tangentOut.Normalize();
+
+    Vector3 tangentIn = ( p1p2*p2p3.Length() + p2p3*length ) * 0.5f;
+    tangentIn.Normalize();
+
+    //Use curvature to scale the tangents
+    length *= curvature;
+    mControlPoint[2*i] =   p1 + tangentOut*length;
+    mControlPoint[2*i+1] = p2 - tangentIn*length;
+  }
+}
+
+void Path::FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const
+{
+  //Find segment and local progress
+  unsigned int numSegs = GetNumberOfSegments();
+
+  if( t <= 0.0f || numSegs == 0 )
+  {
+    segment = 0;
+    tLocal = 0.0f;
+  }
+  else if( t >= 1.0f )
+  {
+    segment = numSegs-1;
+    tLocal = 1.0f;
+  }
+  else
+  {
+    segment = t * numSegs;
+    float segLength = 1.0f / numSegs;
+    float segStart  = (float)segment * segLength;
+    tLocal = (t - segStart) * numSegs;
+  }
+}
+
+void Path::Sample( float t, Vector3& position, Vector3& tangent ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  //Get points and control points in the segment
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    position = point0;
+    tangent = ( controlPoint0 - point0 ) * 3.0f;
+    tangent.Normalize();
+  }
+  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    position = point1;
+    tangent = ( point1 - controlPoint1 ) * 3.0f;
+    tangent.Normalize();
+  }
+  else
+  {
+    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+
+    Vector4 A = BezierBasis * cVect;
+    position.x = sVect.Dot4(A);
+    tangent.x  = sVectDerivative.Dot(Vector3(A));
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+
+    A = BezierBasis * cVect;
+    position.y = sVect.Dot4(A);
+    tangent.y  = sVectDerivative.Dot(Vector3(A));
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+
+    A = BezierBasis * cVect;
+    position.z = sVect.Dot4(A);
+    tangent.z  = sVectDerivative.Dot(Vector3(A));
+
+    tangent.Normalize();
+  }
+}
+
+Vector3 Path::SamplePosition( float t ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  Vector3 position;
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    position = point0;
+  }
+  else if( (1.0 - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    position = point1;
+  }
+  else
+  {
+    const Vector4 sVect(tLocal*tLocal*tLocal, tLocal*tLocal, tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+    position.x = sVect.Dot4(BezierBasis * cVect);
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+    position.y = sVect.Dot4(BezierBasis * cVect);
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+    position.z = sVect.Dot4(BezierBasis * cVect);
+  }
+
+  return position;
+}
+
+Vector3 Path::SampleTangent( float t ) const
+{
+  DALI_ASSERT_ALWAYS(mPoint.Size() > 1 && mControlPoint.Size() == (mPoint.Size()-1)*2 && "Spline not fully initialized" );
+
+  unsigned int segment;
+  float tLocal;
+  FindSegmentAndProgress( t, segment, tLocal );
+
+  const Vector3& controlPoint0 = mControlPoint[2*segment];
+  const Vector3& controlPoint1 = mControlPoint[2*segment+1];
+  const Vector3& point0 = mPoint[segment];
+  const Vector3& point1 = mPoint[segment+1];
+
+  Vector3 tangent;
+  if(tLocal < Math::MACHINE_EPSILON_1)
+  {
+    tangent = ( controlPoint0 - point0 ) * 3.0f;
+  }
+  else if( (1.0f - tLocal) < Math::MACHINE_EPSILON_1)
+  {
+    tangent = ( point1 - controlPoint1 ) * 3.0f;
+  }
+  else
+  {
+    const Vector3 sVectDerivative(3.0f*tLocal*tLocal, 2.0f*tLocal, 1.0f );
+
+    //X
+    Vector4  cVect( point0.x, controlPoint0.x, controlPoint1.x,  point1.x);
+    tangent.x  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+    //Y
+    cVect.x  = point0.y;
+    cVect.y  = controlPoint0.y;
+    cVect.z  = controlPoint1.y;
+    cVect.w  = point1.y;
+    tangent.y  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+
+    //Z
+    cVect.x  = point0.z;
+    cVect.y  = controlPoint0.z;
+    cVect.z  = controlPoint1.z;
+    cVect.w  = point1.z;
+    tangent.z  = sVectDerivative.Dot(Vector3(BezierBasis * cVect));
+  }
+
+  tangent.Normalize();
+  return tangent;
+}
+
+Vector3& Path::GetPoint( size_t index )
+{
+  DALI_ASSERT_ALWAYS( index < mPoint.Size() && "Path: Point index out of bounds" );
+
+  return mPoint[index];
+}
+
+Vector3& Path::GetControlPoint( size_t index )
+{
+  DALI_ASSERT_ALWAYS( index < mControlPoint.Size() && "Path: Control Point index out of bounds" );
+
+  return mControlPoint[index];
+}
+
+size_t Path::GetPointCount() const
+{
+  return mPoint.Size();
+}
+
+void Path::ClearPoints()
+{
+  mPoint.Clear();
+}
+
+void Path::ClearControlPoints()
+{
+  mControlPoint.Clear();
+}
+
+} // Internal
+} // Dali
diff --git a/dali/internal/event/animation/path-impl.h b/dali/internal/event/animation/path-impl.h
new file mode 100644 (file)
index 0000000..26a1a01
--- /dev/null
@@ -0,0 +1,288 @@
+#ifndef __DALI_INTERNAL_PATH_H__
+#define __DALI_INTERNAL_PATH_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/path.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+typedef IntrusivePtr<Path> PathPtr;
+
+/**
+ * A 3D path
+ */
+class Path : public Object
+{
+public:
+
+  /**
+   * Construct a new path
+   */
+  static Path* New();
+
+  /**
+   * Constructor
+   */
+  Path();
+
+
+protected:
+  /**
+   * virtual destructor
+   */
+  virtual ~Path();
+
+private:
+  /**
+   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded(Object& object){}
+
+  /**
+   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectRemoved(Object& object){}
+
+  /**
+   * @copydoc Dali::Internal::Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed(Object& object){}
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+   /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const{ return NULL; }
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const{ return NULL; }
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const{ return NULL; }
+
+public:
+
+  /**
+   * Returns a clone to the given path
+   */
+  static Path* Clone(const Path& path);
+
+  /**
+   * @copydoc Dali::Path::AddPoint
+   */
+  void AddPoint(const Vector3& point );
+
+  /**
+   * @copydoc Dali::Path::AddControlPoint
+   */
+  void AddControlPoint(const Vector3& point );
+
+  /**
+   * @copydoc Dali::Path::GenerateControlPoints
+   */
+  void GenerateControlPoints( float curvature );
+
+  /**
+   * @copydoc Dali::Path::Sample
+   */
+  void Sample( float t, Vector3& position, Vector3& tangent ) const;
+
+  /**
+   * Sample position at point t.
+   *
+   * @param[in] progress  A floating point value between 0.0 and 1.0.
+   * @param[out] position The interpolated position at that progress.
+   */
+  Vector3 SamplePosition( float t ) const;
+
+  /**
+   * @brief Sample tangent at point t.
+   *
+   * @param[in] progress  A floating point value between 0.0 and 1.0.
+   * @param[out] tangent The interpolated tangent at that progress.
+   */
+  Vector3 SampleTangent( float t ) const;
+
+  /**
+   * @copydoc Dali::Path::GetPoint
+   */
+  Vector3& GetPoint( size_t index );
+
+  /**
+   * @copydoc Dali::Path::GetControlPoint
+   */
+  Vector3& GetControlPoint( size_t index );
+
+  /**
+   * @copydoc Dali::Path::GetPointCount
+   */
+  size_t GetPointCount() const;
+
+  /**
+   * Clears the points of the path
+   */
+  void ClearPoints();
+
+  /**
+   * Clears the control points of the path
+   */
+  void ClearControlPoints();
+
+  /**
+   * @brief Get mPoint property
+   *
+   * @return A const reference to mPoint vector
+   */
+  const Dali::Vector<Vector3>& GetPoints() const{ return mPoint; }
+
+  /*
+   * @brief Set mPoint
+   *
+   * @param[in] p New value for mPoint property
+   */
+  void SetPoints( const Dali::Vector<Vector3>& p ){ mPoint = p; }
+
+  /**
+   * @brief Get mCotrolPoint property
+   *
+   * @return A const reference to mControlPoint vector
+   */
+  const Dali::Vector<Vector3>& GetControlPoints() const{ return mControlPoint; }
+
+  /*
+   * @brief Set mControlPoint property
+   *
+   * @param[in] p New value for mControlPoint property
+   */
+  void SetControlPoints( const Dali::Vector<Vector3>& p ){ mControlPoint = p; }
+
+private:
+
+  /**
+   * Undefined
+   */
+  Path(const Path& p);
+
+  /**
+   * Undefined
+   */
+  Path& operator=(const Path& rhs);
+
+  /**
+   * Helper function to calculate the segment and local progress in that segment
+   * given a progress
+   *
+   * @param[in] t Progress
+   * @param[out] segment Segment for t
+   * @param[out] tLocal Local progress in the segment
+   *
+   */
+  void FindSegmentAndProgress( float t, unsigned int& segment, float& tLocal ) const;
+
+  /**
+   * Helper function to calculate to number of segments in the path
+   */
+  unsigned int GetNumberOfSegments() const;
+
+  Dali::Vector<Vector3> mPoint;            ///< Interpolation points
+  Dali::Vector<Vector3> mControlPoint;     ///< Control points
+};
+
+} // Internal
+
+// Get impl of handle
+inline Internal::Path& GetImplementation(Dali::Path& path)
+{
+  DALI_ASSERT_ALWAYS( path && "Path handle is empty" );
+  Dali::RefObject& object = path.GetBaseObject();
+  return static_cast<Internal::Path&>(object);
+}
+
+inline const Internal::Path& GetImplementation(const Dali::Path& path)
+{
+  DALI_ASSERT_ALWAYS( path && "Path handle is empty" );
+  const Dali::RefObject& object = path.GetBaseObject();
+  return static_cast<const Internal::Path&>(object);
+}
+
+
+} // Dali
+
+#endif //__DALI_INTERNAL_KEY_FRAMES_H__
diff --git a/dali/internal/event/animation/progress-value.h b/dali/internal/event/animation/progress-value.h
new file mode 100644 (file)
index 0000000..7de8d3c
--- /dev/null
@@ -0,0 +1,219 @@
+#ifndef __DALI_INTERNAL_PROGRESS_VALUE_H__
+#define __DALI_INTERNAL_PROGRESS_VALUE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/degree.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Progress / value pair for animating channels (properties) with keyframes
+ */
+template <typename T>
+class ProgressValue
+{
+public:
+  ProgressValue (float progress, T value)
+  : mProgress(progress),
+    mValue (value)
+  {
+  }
+
+  ~ProgressValue ()
+  {
+  }
+
+  float GetProgress () const
+  {
+    return mProgress;
+  }
+
+  const T& GetValue () const
+  {
+    return mValue;
+  }
+
+public:
+  float mProgress;   ///< Progress this value applies to animation channel
+  T mValue;          ///< value this animation channel should take
+};
+
+typedef ProgressValue<Quaternion>                       ProgressQuaternion;
+typedef std::vector<ProgressQuaternion>                 ProgressQuaternionContainer;
+
+typedef ProgressValue<AngleAxis>                        ProgressAngleAxis;
+typedef std::vector<AngleAxis>                          ProgressAngleAxisContainer;
+
+typedef ProgressValue<bool>                             ProgressBoolean;
+typedef std::vector<ProgressBoolean>                    ProgressBooleanContainer;
+
+typedef ProgressValue<int>                              ProgressInteger;
+typedef std::vector<ProgressInteger>                    ProgressIntegerContainer;
+
+typedef ProgressValue<float>                            ProgressNumber;
+typedef std::vector<ProgressNumber>                     ProgressNumberContainer;
+
+typedef ProgressValue<Vector2>                          ProgressVector2;
+typedef std::vector<ProgressVector2>                    ProgressVector2Container;
+
+typedef ProgressValue<Vector3>                          ProgressVector3;
+typedef std::vector<ProgressVector3>                    ProgressVector3Container;
+
+typedef ProgressValue<Vector4>                          ProgressVector4;
+typedef std::vector<ProgressVector4>                    ProgressVector4Container;
+
+inline void Interpolate (Quaternion& result, const Quaternion& a, const Quaternion& b, float progress)
+{
+  result = Quaternion::Slerp(a, b, progress);
+}
+
+inline void Interpolate (AngleAxis& result, const AngleAxis& a, const AngleAxis& b, float progress)
+{
+  Quaternion q1(a.angle, a.axis);
+  Quaternion q2(b.angle, b.axis);
+
+  Quaternion iq = Quaternion::Slerp(q1, q2, progress);
+  iq.ToAxisAngle(result.axis, result.angle);
+}
+
+
+inline void Interpolate (bool& result, bool a, bool b, float progress)
+{
+  result = progress < 0.5f ? a : b;
+}
+
+inline void Interpolate (int& result, int a, int b, float progress)
+{
+  result = static_cast<int>(a + (b - a) * progress + 0.5f);
+}
+
+inline void Interpolate (unsigned int& result, unsigned int a, unsigned int b, float progress)
+{
+  result = static_cast<unsigned int>(a + (b - a) * progress + 0.5f);
+}
+
+inline void Interpolate (float& result, float a, float b, float progress)
+{
+  result = a + (b-a) * progress;
+}
+
+inline void Interpolate (Vector2& result, const Vector2& a,  const Vector2& b, float progress)
+{
+  result = a + (b-a) * progress;
+}
+
+inline void Interpolate (Vector3& result, const Vector3& a, const Vector3& b, float progress)
+{
+  result = a + (b-a) * progress;
+}
+
+inline void Interpolate (Vector4& result, const Vector4& a, const Vector4& b, float progress)
+{
+  result = a + (b-a) * progress;
+}
+
+/* Cubic Interpolation (Catmull-Rom spline) between values p1 and p2. p0 and p3 are prev and next values
+ * and are used as control points to calculate tangent of the curve at interpolation points.
+ *
+ * f(t) = a3*t^3 + a2*t^2 + a1*t + a0
+ * Restrictions: f(0)=p1   f(1)=p2   f'(0)=(p2-p0)*0.5   f'(1)=(p3-p1)*0.5
+ */
+
+inline void CubicInterpolate( int& result, int p0, int p1, int p2, int p3, float progress )
+{
+  float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  float a1 = (p2-p0)*0.5f;
+
+  result = static_cast<int>( a3*progress*progress*progress + a2*progress*progress + a1*progress + p1 + 0.5f );
+}
+
+inline void CubicInterpolate( unsigned int& result, unsigned int p0, unsigned int p1, unsigned int p2, unsigned int p3, float progress )
+{
+  float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  float a1 = (p2-p0)*0.5f;
+
+  result = static_cast<unsigned int>( a3*progress*progress*progress + a2*progress*progress + a1*progress + p1 + 0.5f );
+}
+
+inline void CubicInterpolate( float& result, float p0, float p1, float  p2, float  p3, float progress )
+{
+  float a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  float a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  float a1 = (p2-p0)*0.5f;
+
+  result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector2& result, const Vector2& p0, const Vector2& p1, const Vector2&  p2, const Vector2&  p3, float progress )
+{
+  Vector2 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  Vector2 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  Vector2 a1 = (p2-p0)*0.5f;
+
+  result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector3& result, const Vector3& p0, const Vector3& p1, const Vector3&  p2, const Vector3&  p3, float progress )
+{
+  Vector3 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  Vector3 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  Vector3 a1 = (p2-p0)*0.5f;
+
+  result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( Vector4& result, const Vector4& p0, const Vector4& p1, const Vector4&  p2, const Vector4&  p3, float progress )
+{
+  Vector4 a3 = p3*0.5f - p2*1.5f + p1*1.5f - p0*0.5f;
+  Vector4 a2 = p0 - p1*2.5f + p2*2.0f - p3*0.5f;
+  Vector4 a1 = (p2-p0)*0.5f;
+
+  result = a3*progress*progress*progress + a2*progress*progress + a1*progress + p1;
+}
+
+inline void CubicInterpolate( bool& result, bool p0, bool p1, bool  p2, bool  p3, float progress )
+{
+  Interpolate( result, p1, p2, progress);
+}
+
+inline void CubicInterpolate( Quaternion& result, const Quaternion& p0, const Quaternion& p1, const Quaternion& p2, const Quaternion& p3, float progress )
+{
+  Interpolate( result, p1, p2, progress);
+}
+
+inline void CubicInterpolate( AngleAxis& result, const AngleAxis& p0, const AngleAxis& p1, const AngleAxis& p2, const AngleAxis& p3, float progress )
+{
+  Interpolate( result, p1, p2, progress);
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //__DALI_PROGRESS_VALUE_H__
diff --git a/dali/internal/event/animation/property-constraint-ptr.h b/dali/internal/event/animation/property-constraint-ptr.h
new file mode 100644 (file)
index 0000000..495607a
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__
+#define __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/property-constraint.h>
+#include <dali/internal/common/owner-pointer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+template <class P>
+struct PropertyConstraintPtr
+{
+  typedef OwnerPointer< PropertyConstraint<P> > Type;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_CONSTRAINT_PTR_H__
diff --git a/dali/internal/event/animation/property-constraint.h b/dali/internal/event/animation/property-constraint.h
new file mode 100644 (file)
index 0000000..196c229
--- /dev/null
@@ -0,0 +1,221 @@
+#ifndef __DALI_PROPERTY_CONSTRAINT_H__
+#define __DALI_PROPERTY_CONSTRAINT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/internal/event/animation/property-input-accessor.h>
+#include <dali/internal/event/animation/property-input-indexer.h>
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A class for connecting properties to a constraint function.
+ */
+template < typename PropertyType >
+class PropertyConstraint
+{
+public:
+
+  typedef std::vector < PropertyInputAccessor > InputContainer;
+  typedef typename InputContainer::iterator InputContainerIter;
+  typedef typename InputContainer::const_iterator InputContainerConstIter;
+
+  typedef std::vector< PropertyInputIndexer< PropertyInputAccessor > > InputIndexerContainer;
+
+  typedef Dali::Constraint::Function< PropertyType > ConstraintFunction;
+
+  /**
+   * Create a property constraint.
+   *
+   * @param[in]  func  A constraint function. Ownership of this callback-function is passed to this object.
+   */
+  PropertyConstraint( Dali::Constraint::Function< PropertyType >* func )
+  : mInputsInitialized( false ),
+    mFunction( func ),
+    mInputs()
+  {
+  }
+
+  /**
+   * Constructor.
+   * @param [in]  func    A constraint function. Ownership of this callback-function is passed to this object.
+   * @param [in]  inputs  Property inputs.
+   */
+  PropertyConstraint( Dali::Constraint::Function< PropertyType >* func,
+                      const InputContainer& inputs )
+  : mInputsInitialized( false ),
+    mFunction( func ),
+    mInputs( inputs )
+  {
+  }
+
+  /**
+   * Non virtual destructor.
+   */
+  ~PropertyConstraint()
+  {
+    delete mFunction;
+  }
+
+  /**
+   * Clone a property constraint.
+   *
+   * @return The clone of the property-constraint.
+   *
+   * @note This function will create a copy of the stored constraint function for the clone.
+   */
+  PropertyConstraint< PropertyType >* Clone()
+  {
+    return new PropertyConstraint< PropertyType >( reinterpret_cast< ConstraintFunction* >( mFunction->Clone() ), mInputs );
+  }
+
+  /**
+   * Set the input for one of the property constraint parameters.
+   * @param [in] index The parameter index.
+   * @param [in] input The interface for receiving a property value.
+   */
+  void SetInput( unsigned int index, int componentIndex, const PropertyInputImpl& input )
+  {
+    if ( index >= mInputs.size() )
+    {
+      mInputs.push_back( PropertyInputAccessor() );
+    }
+
+    mInputs[ index ].SetInput( input, componentIndex );
+  }
+
+  /**
+   * Retrieve the input for one of the property constraint parameters.
+   * @param [in] index The parameter index.
+   * @return The property input, or NULL if no input exists with this index.
+   */
+  const PropertyInputImpl* GetInput( unsigned int index ) const
+  {
+    if ( index < mInputs.size() )
+    {
+      return mInputs[ index ].GetInput();
+    }
+
+    return NULL;
+  }
+
+  /**
+   * Query whether all of the inputs have been initialized.
+   * @return True if all of the inputs have been initialized.
+   */
+  bool InputsInitialized()
+  {
+    if ( !mInputsInitialized )
+    {
+      // Check whether the inputs are initialized yet
+      unsigned int index( 0u );
+      for ( const PropertyInputImpl* input = GetInput( index );
+            NULL != input;
+            input = GetInput( ++index ) )
+      {
+        if ( !input->InputInitialized() )
+        {
+          return false;
+        }
+      }
+
+      // All inputs are now initialized
+      mInputsInitialized = true;
+    }
+
+    return true;
+  }
+
+  /**
+   * Query whether any of the inputs have changed
+   * @return True if any of the inputs have changed.
+   */
+  bool InputsChanged()
+  {
+    unsigned int index( 0u );
+    for ( const PropertyInputImpl* input = GetInput( index );
+          NULL != input;
+          input = GetInput( ++index ) )
+    {
+      if ( input->InputChanged() )
+      {
+        // At least one of the inputs has changed
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Apply the constraint.
+   * @param [in] bufferIndex The current update buffer index.
+   * @param [in,out] current The current property value, will be set to the constrained value upon return.
+   */
+  void Apply( BufferIndex bufferIndex, PropertyType& current )
+  {
+    InputIndexerContainer mInputIndices;
+    PropertyInputContainer mIndices;
+    const unsigned int noOfInputs = mInputs.size();
+
+    mInputIndices.reserve( noOfInputs );
+    mIndices.Reserve( noOfInputs );
+
+    const InputContainerConstIter endIter = mInputs.end();
+    unsigned int index = 0;
+    for ( InputContainerConstIter iter = mInputs.begin(); iter != endIter; ++iter, ++index )
+    {
+      DALI_ASSERT_DEBUG( NULL != iter->GetInput() );
+      mInputIndices.push_back( PropertyInputIndexer< PropertyInputAccessor >( bufferIndex, &*iter ) );
+      mIndices.PushBack( &mInputIndices[ index ] );
+    }
+
+    CallbackBase::Execute< PropertyType&, const PropertyInputContainer& >( *mFunction, current, mIndices );
+  }
+
+private:
+
+  // Undefined
+  PropertyConstraint( const PropertyConstraint& );
+
+  // Undefined
+  PropertyConstraint& operator=( const PropertyConstraint& rhs );
+
+private:
+
+  bool mInputsInitialized;
+
+  ConstraintFunction* mFunction;
+
+  InputContainer mInputs;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_CONSTRAINT_H__
diff --git a/dali/internal/event/animation/property-input-accessor.h b/dali/internal/event/animation/property-input-accessor.h
new file mode 100644 (file)
index 0000000..9c203a1
--- /dev/null
@@ -0,0 +1,227 @@
+#ifndef __DALI_PROPERTY_INPUT_ACCESSOR_H__
+#define __DALI_PROPERTY_INPUT_ACCESSOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class PropertyInputAccessor
+{
+public:
+
+  /**
+   * Create the PropertyInputAccessor.
+   */
+  PropertyInputAccessor()
+  : mInput( NULL ),
+    mComponentIndex( -1 )
+  {
+  }
+
+  /**
+   * Create the PropertyInputAccessor.
+   */
+  PropertyInputAccessor( const PropertyInputImpl* input, int componentIndex )
+  : mInput( input ),
+    mComponentIndex( componentIndex )
+  {
+  }
+
+  /**
+   * Copy from a PropertyInputAccessor
+   */
+  PropertyInputAccessor( const PropertyInputAccessor& accessor )
+  : mInput( accessor.mInput ),
+    mComponentIndex( accessor.mComponentIndex )
+  {
+  }
+
+  /**
+   * Copy from a PropertyInputAccessor
+   */
+  PropertyInputAccessor& operator=(const PropertyInputAccessor& accessor)
+  {
+    mInput = accessor.mInput;
+    mComponentIndex = accessor.mComponentIndex;
+    return *this;
+  }
+
+  /**
+   * Set the property input.
+   */
+  void SetInput( const PropertyInputImpl& input, int componentIndex )
+  {
+    mInput = &input;
+    mComponentIndex = componentIndex;
+  }
+
+  /**
+   * Retrieve the property input.
+   */
+  const PropertyInputImpl* GetInput() const
+  {
+    return mInput;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetType()
+   */
+  Property::Type GetType() const
+  {
+    return mInput->GetType();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputBoolean()
+   */
+  const bool& GetConstraintInputBoolean( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputBoolean( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputInteger() const
+   */
+  const int& GetConstraintInputInteger( BufferIndex updateBufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( mComponentIndex < 0 && "Did not expect valid component index" );
+
+    return mInput->GetConstraintInputInteger( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputFloat()
+   */
+  const float& GetConstraintInputFloat( BufferIndex updateBufferIndex ) const
+  {
+    // Invalid index is ok
+    if ( mComponentIndex < 0 )
+    {
+      // Not a Vector2, Vector3 or Vector4 component, expecting float type
+      return mInput->GetConstraintInputFloat( updateBufferIndex );
+    }
+    else if ( PropertyTypes::Get< Vector2 >() == mInput->GetType() )
+    {
+      if ( 0 == mComponentIndex )
+      {
+        return mInput->GetConstraintInputVector2( updateBufferIndex ).x;
+      }
+
+      DALI_ASSERT_DEBUG( 1 == mComponentIndex && "Invalid Vector2 component index" );
+      return mInput->GetConstraintInputVector2( updateBufferIndex ).y;
+    }
+    else if ( PropertyTypes::Get< Vector3 >() == mInput->GetType() )
+    {
+      if ( 0 == mComponentIndex )
+      {
+        return mInput->GetConstraintInputVector3( updateBufferIndex ).x;
+      }
+      else if ( 1 == mComponentIndex )
+      {
+        return mInput->GetConstraintInputVector3( updateBufferIndex ).y;
+      }
+
+      DALI_ASSERT_DEBUG( 2 == mComponentIndex && "Invalid Vector3 component index" );
+      return mInput->GetConstraintInputVector3( updateBufferIndex ).z;
+    }
+
+    // Expecting Vector4
+    if ( 0 == mComponentIndex )
+    {
+      return mInput->GetConstraintInputVector4( updateBufferIndex ).x;
+    }
+    else if ( 1 == mComponentIndex )
+    {
+      return mInput->GetConstraintInputVector4( updateBufferIndex ).y;
+    }
+    else if ( 2 == mComponentIndex )
+    {
+      return mInput->GetConstraintInputVector4( updateBufferIndex ).z;
+    }
+
+    DALI_ASSERT_DEBUG( 3 == mComponentIndex && "Invalid Vector4 component index" );
+    return mInput->GetConstraintInputVector4( updateBufferIndex ).w;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector2()
+   */
+  const Vector2& GetConstraintInputVector2( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputVector2( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector3()
+   */
+  const Vector3& GetConstraintInputVector3( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputVector3( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputVector4()
+   */
+  const Vector4& GetConstraintInputVector4( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputVector4( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputQuaternion()
+   */
+  const Quaternion& GetConstraintInputQuaternion( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputQuaternion( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputMatrix3()
+   */
+  const Matrix3& GetConstraintInputMatrix3( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputMatrix3( updateBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputMatrix()
+   */
+  const Matrix& GetConstraintInputMatrix( BufferIndex updateBufferIndex ) const
+  {
+    return mInput->GetConstraintInputMatrix( updateBufferIndex );
+  }
+
+public:
+
+  const PropertyInputImpl* mInput;
+  int mComponentIndex;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_INPUT_ACCESSOR_H__
diff --git a/dali/internal/event/animation/property-input-indexer.h b/dali/internal/event/animation/property-input-indexer.h
new file mode 100644 (file)
index 0000000..c19bf14
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef __DALI_PROPERTY_INPUT_INDEXER_H__
+#define __DALI_PROPERTY_INPUT_INDEXER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Helper object to map public-api PropertyInput methods to internal
+ * PropertyInputImpl methods (which require the current buffer index).
+ */
+template < typename AccessorType >
+class PropertyInputIndexer : public PropertyInput
+{
+public:
+
+  /**
+   * Create an indexer object.
+   * @param[in] bufferIndex The current buffer index.
+   * @param[in] input The internal property input.
+   */
+  PropertyInputIndexer( BufferIndex bufferIndex, const AccessorType* input )
+  : mBufferIndex( bufferIndex ),
+    mInput( input )
+  {
+  }
+
+  /**
+   * Copy constructor
+   */
+  PropertyInputIndexer( const PropertyInputIndexer& other )
+  : mBufferIndex( other.mBufferIndex ),
+    mInput( other.mInput )
+  {
+  }
+
+  /**
+   * Assignment operator
+   */
+  PropertyInputIndexer& operator=( const PropertyInputIndexer& other )
+  {
+    mBufferIndex = other.mBufferIndex;
+    mInput = other.mInput;
+
+    return *this;
+  }
+
+  /**
+   * Virtual Destructor
+   */
+  virtual ~PropertyInputIndexer()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetType()
+   */
+  virtual Property::Type GetType() const
+  {
+    return mInput->GetType();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetBoolean()
+   */
+  virtual const bool& GetBoolean() const
+  {
+    return mInput->GetConstraintInputBoolean( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetInteger()
+   */
+  virtual const int& GetInteger() const
+  {
+    return mInput->GetConstraintInputInteger( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetFloat()
+   */
+  virtual const float& GetFloat() const
+  {
+    return mInput->GetConstraintInputFloat( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetVector2()
+   */
+  virtual const Vector2& GetVector2() const
+  {
+    return mInput->GetConstraintInputVector2( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3() const
+  {
+    return mInput->GetConstraintInputVector3( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetVector4()
+   */
+  virtual const Vector4& GetVector4() const
+  {
+    return mInput->GetConstraintInputVector4( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetMatrix3()
+   */
+  virtual const Matrix3& GetMatrix3() const
+  {
+    return mInput->GetConstraintInputMatrix3( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::GetMatrix()
+   */
+  virtual const Matrix& GetMatrix() const
+  {
+    return mInput->GetConstraintInputMatrix( mBufferIndex );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInput::Quaternion()
+   */
+  virtual const Quaternion& GetQuaternion() const
+  {
+    return mInput->GetConstraintInputQuaternion( mBufferIndex );
+  }
+
+public:
+
+  unsigned int mBufferIndex;
+  const AccessorType* mInput;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_INPUT_INDEXER_H__
diff --git a/dali/internal/event/common/complete-notification-interface.h b/dali/internal/event/common/complete-notification-interface.h
new file mode 100644 (file)
index 0000000..af43f25
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__
+#define __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Provides notifications to the event-thread regarding the changes in previous update(s).
+ * For example after an animation finished, or after resources were loaded.
+ */
+class CompleteNotificationInterface
+{
+protected:
+
+  /**
+   * Constructor, not to be directly instantiated.
+   */
+  CompleteNotificationInterface()
+  {}
+
+  /**
+   * Virtual destructor as this is an interface, no deletion through this interface though.
+   */
+  virtual ~CompleteNotificationInterface()
+  {}
+
+public:
+
+  /**
+   * This method is called by Notification Manager
+   */
+  virtual void NotifyCompleted() = 0;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_COMPLETE_NOTIFICATION_INTERFACE_H__
+
diff --git a/dali/internal/event/common/connectable.h b/dali/internal/event/common/connectable.h
new file mode 100644 (file)
index 0000000..643e9b6
--- /dev/null
@@ -0,0 +1,60 @@
+#ifndef DALI_INTERNAL_CONNECTABLE_H
+#define DALI_INTERNAL_CONNECTABLE_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Internal
+{
+
+/**
+ * @brief Interface for objects that can be connected to the stage.
+ */
+class Connectable
+{
+public:
+
+  /**
+   * @brief Destructor
+   */
+  virtual ~Connectable() {}
+
+  /**
+   * @brief Check if the object is on stage
+   */
+  virtual bool OnStage() const = 0;
+
+  /**
+   * @brief Notify this objects that it has been connected to the stage.
+   */
+  virtual void Connect() = 0;
+
+  /**
+   * @brief Notify this objects that it has been disconnected to the stage.
+   */
+  virtual void Disconnect() = 0;
+
+};
+
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_CONNECTABLE_H
diff --git a/dali/internal/event/common/demangler.cpp b/dali/internal/event/common/demangler.cpp
new file mode 100644 (file)
index 0000000..5a2caed
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//
+// gcc and clang minimal demangling
+// Both follow Itanium C++ ABI
+//
+// We only decode namespaces and class typeid names for simplicity as its all we need.
+//
+// From http://mentorembedded.github.io/cxx-abi/abi.html#mangling-structure
+//
+// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
+//     ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+//
+// <prefix> ::= <prefix> <unqualified-name>
+//     ::= <template-prefix> <template-args>
+//          ::= <template-param>
+//          ::= <decltype>
+//     ::= # empty
+//     ::= <substitution>
+//          ::= <prefix> <data-member-prefix>
+//
+// <template-prefix> ::= <prefix> <template unqualified-name>
+//                   ::= <template-param>
+//                   ::= <substitution>
+// <unqualified-name> ::= <operator-name>
+//                    ::= <ctor-dtor-name>
+//                    ::= <source-name>
+//                    ::= <unnamed-type-name>
+//
+// <source-name> ::= <positive length number> <identifier>
+// <number> ::= [n] <non-negative decimal integer>
+// <identifier> ::= <unqualified source code identifier>
+//
+// So for example
+//
+// Dali::Internal::Actor would be
+//
+//   N4Dali8Internal5ActorE
+//
+
+// CLASS HEADER
+#include <dali/internal/event/common/demangler.h>
+
+namespace
+{
+
+// true if character represent a digit
+inline bool IsDigit(char c)
+{
+  return (c >= '0' && c <= '9');
+}
+
+// Gets the number of characters (number is in string)
+//   start The start position to look for a number
+//   result The number as an integer
+//   returns the number of characters used to define the number ie '12' is 2
+size_t GetNumberOfCharacters(const std::string& s, const size_t& start, int& result)
+{
+  size_t size = s.size();
+
+  size_t i = start;
+
+  int number = 0;
+
+  for( ; i < size; ++i )
+  {
+    char c = s.at(i);
+    if( !IsDigit( c ) )
+    {
+      break;
+    }
+    else
+    {
+      number = 10 * number + (c - '0');
+    }
+  }
+
+  if( i - start )
+  {
+    result = number;
+  }
+
+  return i - start;
+}
+
+} // anon namespace
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#if defined(__clang__) || defined(__GNUC__)
+
+// Demangle class name mangled according to the Itanium C++ ABI
+// Returns demangled names ie "N4Dali8Internal5ActorE" is ["Dali","Internal","Actor"]
+std::vector<std::string> DemangleNestedNames(const char *typeIdName)
+{
+  std::vector<std::string> ret;
+
+  const std::string mangledName(typeIdName);
+
+
+  size_t size = mangledName.size();
+
+  if( size >= 2 )
+  {
+    int number = 0;
+    size_t start = 0;
+
+    // If the class isnt nested in a namespace then it just starts with the
+    // number of characters
+    if(mangledName[0] == 'N' && mangledName[size-1]  == 'E')
+    {
+      start = 1;
+    }
+
+    while( size_t chars = GetNumberOfCharacters(mangledName, start, number) )
+    {
+      ret.push_back( mangledName.substr( start + chars, number ) );
+
+      start += chars + number;
+    }
+  }
+
+  return ret;
+}
+
+#else
+# error Unsupported Compiler
+#endif
+
+
+const std::string DemangleClassName(const char *typeIdName)
+{
+  std::string name;
+  std::vector<std::string> names = DemangleNestedNames(typeIdName);
+
+  if( names.size() )
+  {
+    name = names[ names.size() - 1 ];
+  }
+
+  return name;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/demangler.h b/dali/internal/event/common/demangler.h
new file mode 100644 (file)
index 0000000..9794099
--- /dev/null
@@ -0,0 +1,54 @@
+#ifndef __DALI_DEMANGLER_H__
+#define __DALI_DEMANGLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Demangle a nested typeid name into its component parts.
+ * A nested type name is one containing namespaces and class names only.
+ *   eg DemangleNestedNames(typeid(Dali::Actor).name());
+ * @param[in] typeIdName The type id name string to demangle.
+ * @returns the demangled list of names ie ["Dali","Actor"] or an empty list
+ */
+std::vector<std::string> DemangleNestedNames(const char *typeIdName);
+
+/**
+ * Demangle a nested typeid name to its class name.
+ * @param[in] typeIdName The type id name string to demangle.
+ * @returns the class name ie "Actor" or an empty string
+ */
+const std::string DemangleClassName(const char *typeIdName);
+
+}
+
+}
+
+
+#endif // header
diff --git a/dali/internal/event/common/event-thread-services.cpp b/dali/internal/event/common/event-thread-services.cpp
new file mode 100644 (file)
index 0000000..2f1ae09
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "event-thread-services.h"
+
+#include <dali/internal/event/common/thread-local-storage.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+bool EventThreadServices::IsCoreRunning()
+{
+  return ThreadLocalStorage::Created();
+}
+
+} // Internal
+} // Dali
diff --git a/dali/internal/event/common/event-thread-services.h b/dali/internal/event/common/event-thread-services.h
new file mode 100644 (file)
index 0000000..eb2d345
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __DALI_INTERNAL_EVENT_THREAD_SERVICES_H__
+#define __DALI_INTERNAL_EVENT_THREAD_SERVICES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+
+class BaseObject;
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+/**
+ * Abstract interface of services for event-thread objects.
+ * Used for registering objects, queueing messages during the event-thread for the next update.
+ * Allows the event-thread to read double-buffered property values.
+ */
+class EventThreadServices
+{
+public:
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~EventThreadServices()
+  { }
+
+  /**
+   * @brief Registers the object as created with the Object registry.
+   *
+   * @param[in] object to register
+   */
+  virtual void RegisterObject( BaseObject* object) = 0;
+
+  /**
+   * @brief Unregisters the object from Object registry.
+   *
+   * @param[in] object to unregister
+   */
+  virtual void UnregisterObject( BaseObject* object) = 0;
+
+  /**
+   * @brief Get a reference to the UpdateManager
+   *
+   * @return the update manager
+   */
+  virtual SceneGraph::UpdateManager& GetUpdateManager() = 0;
+
+  /**
+   * Reserve space for another message in the queue; this must then be initialized by the caller.
+   * The message will be read from the update-thread after the next FlushMessages is called.
+   * @post Calling this method may invalidate any previously returned slots.
+   * @param[in] size The message size with respect to the size of type "char".
+   * @param[in] updateScene A flag, when true denotes that the message will cause the scene-graph node tree to require an update.
+   * @return A pointer to the first char allocated for the message.
+   */
+  virtual unsigned int* ReserveMessageSlot( std::size_t size, bool updateScene = true ) = 0;
+
+  /**
+   * @return the current event-buffer index.
+   */
+  virtual BufferIndex GetEventBufferIndex() const  = 0;
+
+  /**
+   * @return true if core is still running and we can send messages
+   */
+  static bool IsCoreRunning();
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_EVENT_THREAD_SERVICES_H__
diff --git a/dali/internal/event/common/notification-manager.cpp b/dali/internal/event/common/notification-manager.cpp
new file mode 100644 (file)
index 0000000..7be7722
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/notification-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/devel-api/common/mutex.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/event/common/complete-notification-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+typedef Dali::Vector< CompleteNotificationInterface* > InterfaceContainer;
+
+/**
+ * helper to move elements from one container to another
+ * @param from where to move
+ * @param to move target
+ */
+void MoveElements( InterfaceContainer& from, InterfaceContainer& to )
+{
+  // check if there's something in from
+  const InterfaceContainer::SizeType fromCount = from.Count();
+  if( fromCount > 0u )
+  {
+    // check if to has some elements
+    const InterfaceContainer::SizeType toCount = to.Count();
+    if( toCount == 0u )
+    {
+      // to is empty so we can swap with from
+      to.Swap( from );
+    }
+    else
+    {
+      to.Reserve( toCount + fromCount );
+      for( InterfaceContainer::SizeType i = 0; i < fromCount; ++i )
+      {
+        to.PushBack( from[ i ] );
+      }
+      from.Clear();
+    }
+  }
+}
+}
+
+typedef Dali::Mutex MessageQueueMutex;
+typedef OwnerContainer< MessageBase* > MessageContainer;
+
+struct NotificationManager::Impl
+{
+  Impl()
+  {
+    // reserve space on the vectors to avoid reallocs
+    // applications typically have up-to 20-30 notifications at startup
+    updateCompletedMessageQueue.Reserve( 32 );
+    updateWorkingMessageQueue.Reserve( 32 );
+    eventMessageQueue.Reserve( 32 );
+
+    // only a few manager objects get complete notifications (animation, render list, property notifications, ...)
+    updateCompletedInterfaceQueue.Reserve( 4 );
+    updateWorkingInterfaceQueue.Reserve( 4 );
+    eventInterfaceQueue.Reserve( 4 );
+  }
+
+  ~Impl()
+  {
+  }
+
+  // queueMutex must be locked whilst accessing queue
+  MessageQueueMutex queueMutex;
+  // three queues for objects owned by notification manager
+  MessageContainer updateCompletedMessageQueue;
+  MessageContainer updateWorkingMessageQueue;
+  MessageContainer eventMessageQueue;
+  // three queues for objects referenced by notification manager
+  InterfaceContainer updateCompletedInterfaceQueue;
+  InterfaceContainer updateWorkingInterfaceQueue;
+  InterfaceContainer eventInterfaceQueue;
+};
+
+NotificationManager::NotificationManager()
+{
+  mImpl = new Impl();
+}
+
+NotificationManager::~NotificationManager()
+{
+  delete mImpl;
+}
+
+void NotificationManager::QueueCompleteNotification( CompleteNotificationInterface* instance )
+{
+  // queueMutex must be locked whilst accessing queues
+  MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+  mImpl->updateWorkingInterfaceQueue.PushBack( instance );
+}
+
+void NotificationManager::QueueMessage( MessageBase* message )
+{
+  DALI_ASSERT_DEBUG( NULL != message );
+
+  // queueMutex must be locked whilst accessing queues
+  MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+  mImpl->updateWorkingMessageQueue.PushBack( message );
+}
+
+void NotificationManager::UpdateCompleted()
+{
+  // queueMutex must be locked whilst accessing queues
+  MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+  // Move messages from update working queue to completed queue
+  // note that in theory its possible for update completed to have last frames
+  // events as well still hanging around. we need to keep them as well
+  mImpl->updateCompletedMessageQueue.MoveFrom( mImpl->updateWorkingMessageQueue );
+  // move pointers from interface queue
+  MoveElements( mImpl->updateWorkingInterfaceQueue, mImpl->updateCompletedInterfaceQueue );
+  // finally the lock is released
+}
+
+bool NotificationManager::MessagesToProcess()
+{
+  // queueMutex must be locked whilst accessing queues
+  MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+  return ( 0u < mImpl->updateCompletedMessageQueue.Count() ||
+         ( 0u < mImpl->updateCompletedInterfaceQueue.Count() ) );
+}
+
+void NotificationManager::ProcessMessages()
+{
+  // queueMutex must be locked whilst accessing queues
+  {
+    MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+    // Move messages from update completed queue to event queue
+    // note that in theory its possible for event queue to have
+    // last frames events as well still hanging around so need to keep them
+    mImpl->eventMessageQueue.MoveFrom( mImpl->updateCompletedMessageQueue );
+    MoveElements( mImpl->updateCompletedInterfaceQueue, mImpl->eventInterfaceQueue );
+  }
+  // end of scope, lock is released
+
+  MessageContainer::Iterator iter = mImpl->eventMessageQueue.Begin();
+  const MessageContainer::Iterator end = mImpl->eventMessageQueue.End();
+  for( ; iter != end; ++iter )
+  {
+    (*iter)->Process( 0u/*ignored*/ );
+  }
+  // release the processed messages from event side queue
+  mImpl->eventMessageQueue.Clear();
+
+  InterfaceContainer::Iterator iter2 = mImpl->eventInterfaceQueue.Begin();
+  const InterfaceContainer::Iterator end2 = mImpl->eventInterfaceQueue.End();
+  for( ; iter2 != end2; ++iter2 )
+  {
+    CompleteNotificationInterface* interface = *iter2;
+    if( interface )
+    {
+      interface->NotifyCompleted();
+    }
+  }
+  // just clear the container, we dont own the objects
+  mImpl->eventInterfaceQueue.Clear();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/notification-manager.h b/dali/internal/event/common/notification-manager.h
new file mode 100644 (file)
index 0000000..a83efb5
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef __DALI_INTERNAL_NOTIFICATION_MANAGER_H__
+#define __DALI_INTERNAL_NOTIFICATION_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class CompleteNotificationInterface;
+class MessageBase;
+
+/**
+ * Provides notifications to the event-thread regarding the changes in previous update(s).
+ * For example after an animation finished, or after resources were loaded.
+ */
+class NotificationManager
+{
+public:
+
+  /**
+   * Create an NotificationManager. Owned by Core in event thread side.
+   */
+  NotificationManager();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~NotificationManager();
+
+/// Update side interface, can only be called from Update-thread
+
+  /**
+   * Queue a scene message to an interface. This method is thread-safe.
+   * @param[in] instance to be notified about completion of the Update side event.
+   */
+  void QueueCompleteNotification( CompleteNotificationInterface* instance );
+
+  /**
+   * Queue a scene message. This method is thread-safe.
+   * @param[in] message A newly allocated message; NotificationManager takes ownership.
+   */
+  void QueueMessage( MessageBase* message );
+
+  /**
+   * Signal Notification Manager that update frame is completed so it can let event thread process the notifications
+   */
+  void UpdateCompleted();
+
+/// Event side interface, can only be called from Update-thread
+
+  /**
+   * Query whether the NotificationManager has messages to process.
+   * @return True if there are messages to process.
+   */
+  bool MessagesToProcess();
+
+  /**
+   * This function is called by Core when events are processed.
+   */
+  void ProcessMessages();
+
+private:
+
+  // Undefined
+  NotificationManager( const NotificationManager& notificationManager );
+
+  // Undefined
+  NotificationManager& operator=( const NotificationManager& notificationManager );
+
+private:
+
+  struct Impl;
+  Impl* mImpl;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_NOTIFICATION_MANAGER_H__
+
diff --git a/dali/internal/event/common/object-connector.h b/dali/internal/event/common/object-connector.h
new file mode 100644 (file)
index 0000000..576a829
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef DALI_INTERNAL_OBJECT_CONNECTOR_H
+#define DALI_INTERNAL_OBJECT_CONNECTOR_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Wrapper class which helps managing intrusive pointer assignments and Connect / Disconnect.
+ *
+ * Should be used with objects that implement Dali::Internal::Connectable
+ */
+template<typename Object>
+class ObjectConnector
+{
+public:
+  typedef IntrusivePtr<Object> ObjectPtr;
+
+  /**
+   * @brief Default constructor.
+   */
+  ObjectConnector() {}
+
+  /**
+   * @brief Destructor.
+   */
+  ~ObjectConnector() {}
+
+  /**
+   * @brief Copy constructor
+   */
+  ObjectConnector( const ObjectConnector& connector )
+  : mObject( connector.mObject )
+  {
+  }
+
+  /**
+   * @brief Assignment operator
+   */
+  ObjectConnector& operator=( const ObjectConnector& connector )
+  {
+    this->mObject = connector.mObject;
+    return *this;
+  }
+
+  /**
+   * @brief Returns a smart pointer to the object
+   * @return a smart pointer to the object
+   */
+  ObjectPtr Get() const
+  {
+    return mObject;
+  }
+
+  /**
+   * @brief Assigns the object, calling Connect and Disconnect methods accordingly, taking onStage into account.
+   * @param [in] object smart pointer to a object
+   * @param [in] onStage whether the object is used on stage or not
+   */
+  void Set( Object& object, bool onStage )
+  {
+    if ( mObject.Get() != &object )
+    {
+      // Disconnect from old object
+      if ( mObject && onStage )
+      {
+        mObject->Disconnect();
+      }
+
+      mObject = &object;
+
+      // Connect to new object
+      if ( mObject && onStage )
+      {
+        mObject->Connect();
+      }
+    }
+  }
+
+  /**
+   * @brief Manages connection reference count.
+   *
+   * Must be called from owner when connected to stage.
+   */
+  void OnStageConnect()
+  {
+    if ( mObject )
+    {
+      mObject->Connect();
+    }
+  }
+
+  /**
+   * @brief Manages connection reference count.
+   *
+   * Must be called from owner when disconnecting from stage.
+   */
+  void OnStageDisconnect()
+  {
+    if ( mObject )
+    {
+      mObject->Disconnect();
+    }
+  }
+
+private: //data
+  ObjectPtr mObject;  ///< intrusive pointer to the Object. ObjectConnector owns this.
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_OBJECT_CONNECTOR_H
diff --git a/dali/internal/event/common/object-impl-helper.h b/dali/internal/event/common/object-impl-helper.h
new file mode 100644 (file)
index 0000000..8b5032b
--- /dev/null
@@ -0,0 +1,322 @@
+#ifndef DALI_INTERNAL_OBJECT_IMPL_HELPER_H
+#define DALI_INTERNAL_OBJECT_IMPL_HELPER_H
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDEs
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h> // Dali::Property
+#include <dali/public-api/object/property-index-ranges.h> // DEFAULT_DERIVED_HANDLE_PROPERTY_START_INDEX
+#include <dali/internal/event/common/property-helper.h> // Dali::Internal::PropertyDetails
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class PropertyMetadata;
+class AnimatablePropertyMetadata;
+class CustomPropertyMetadata;
+class PropertyInputImpl;
+
+namespace SceneGraph
+{
+
+class PropertyBase;
+class PropertyOwner;
+
+
+} // namespace SceneGraph
+
+// Typedefs to allow object methods to be passed via parameter
+typedef AnimatablePropertyMetadata* (Object::*FindAnimatablePropertyMethod)( Property::Index index ) const;
+typedef CustomPropertyMetadata* (Object::*FindCustomPropertyMethod)( Property::Index index ) const;
+
+
+/**
+ * Helper template class to be used by class that implement Object
+ *
+ * Example:
+ *<pre>
+ * typename ObjectImplHelper<DEFAULT_PROPERTY_COUNT, DEFAULT_PROPERTY_DETAILS> MyObjectImpl;
+ *
+ * MyObjectImpl::GetDefaultPropertyCount();
+ * </pre>
+ */
+template<int DEFAULT_PROPERTY_COUNT>
+struct ObjectImplHelper
+{
+  const PropertyDetails* DEFAULT_PROPERTY_DETAILS;
+
+  unsigned int GetDefaultPropertyCount() const
+  {
+    return DEFAULT_PROPERTY_COUNT;
+  }
+
+  void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+  {
+    indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+    for( unsigned int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+    {
+      indices.PushBack( DEFAULT_OBJECT_PROPERTY_START_INDEX + i );
+    }
+  }
+
+  const char* GetDefaultPropertyName( Property::Index index ) const
+  {
+    const char* name = NULL;
+
+    if( index >= DEFAULT_OBJECT_PROPERTY_START_INDEX && index < DEFAULT_PROPERTY_COUNT )
+    {
+      name = DEFAULT_PROPERTY_DETAILS[index].name;
+    }
+
+    return name;
+  }
+
+  Property::Index GetDefaultPropertyIndex( const std::string& name ) const
+  {
+    Property::Index index = Property::INVALID_INDEX;
+
+    //@todo MESH_REWORK - Are we assuming that the index into the array is the
+    // same as the enumerated property? if enumIndex in the table was no longer
+    // debug only, wouldn't need to make this assumption.
+
+    // Look for name in default properties
+    for( unsigned int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+    {
+      const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+      if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+      {
+        index = i;
+        break;
+      }
+    }
+
+    return index;
+  }
+
+  bool IsDefaultPropertyWritable( Property::Index index ) const
+  {
+    bool isWritable = false;
+
+    if( index >= DEFAULT_OBJECT_PROPERTY_START_INDEX && index < DEFAULT_PROPERTY_COUNT )
+    {
+      isWritable = DEFAULT_PROPERTY_DETAILS[index].writable;
+    }
+
+    return isWritable;
+  }
+
+  bool IsDefaultPropertyAnimatable( Property::Index index ) const
+  {
+    bool isAnimatable = false;
+
+    if( index >= DEFAULT_OBJECT_PROPERTY_START_INDEX && index < DEFAULT_PROPERTY_COUNT )
+    {
+      isAnimatable =  DEFAULT_PROPERTY_DETAILS[index].animatable;
+    }
+
+    return isAnimatable;
+  }
+
+  bool IsDefaultPropertyAConstraintInput( Property::Index index ) const
+  {
+    bool isConstraintInput = false;
+
+    if( index >= DEFAULT_OBJECT_PROPERTY_START_INDEX && index < DEFAULT_PROPERTY_COUNT )
+    {
+      isConstraintInput = DEFAULT_PROPERTY_DETAILS[index].constraintInput;
+    }
+
+    return isConstraintInput;
+  }
+
+  Property::Type GetDefaultPropertyType( Property::Index index ) const
+  {
+    Property::Type type = Property::NONE;
+
+    if( index >= DEFAULT_OBJECT_PROPERTY_START_INDEX && index < DEFAULT_PROPERTY_COUNT )
+    {
+      type =  DEFAULT_PROPERTY_DETAILS[index].type;
+    }
+
+    return type;
+  }
+
+  // Get the (animatable) scene graph property. (All registered scene graph properties are animatable)
+  const SceneGraph::PropertyBase* GetRegisteredSceneGraphProperty(
+    const Object* object,
+    FindAnimatablePropertyMethod findAnimatablePropertyMethod,
+    FindCustomPropertyMethod findCustomPropertyMethod,
+    Property::Index index ) const
+  {
+    const SceneGraph::PropertyBase* property = NULL;
+    if ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX && index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX )
+    {
+      AnimatablePropertyMetadata* animatable = (object->*findAnimatablePropertyMethod)( index );
+      DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+      property = animatable->GetSceneGraphProperty();
+    }
+    else if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      CustomPropertyMetadata* custom = (object->*findCustomPropertyMethod)( index );
+      DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+      property = custom->GetSceneGraphProperty();
+    }
+    return property;
+  }
+
+  void SetSceneGraphProperty( EventThreadServices& eventThreadServices,
+                              const Object* object,
+                              Property::Index index,
+                              const PropertyMetadata& entry,
+                              const Property::Value& value ) const
+  {
+    const SceneGraph::PropertyOwner* sceneObject = object->GetSceneObject();
+
+    switch ( entry.type )
+    {
+      case Property::BOOLEAN:
+      {
+        const SceneGraph::AnimatableProperty<bool>* property = dynamic_cast< const SceneGraph::AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<bool>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<bool>::Bake, value.Get<bool>() );
+
+        break;
+      }
+
+      case Property::FLOAT:
+      {
+        const SceneGraph::AnimatableProperty<float>* property = dynamic_cast< const SceneGraph::AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<float>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<float>::Bake, value.Get<float>() );
+
+        break;
+      }
+
+      case Property::INTEGER:
+      {
+        const SceneGraph::AnimatableProperty<int>* property = dynamic_cast< const SceneGraph::AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<int>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<int>::Bake, value.Get<int>() );
+
+        break;
+      }
+
+      case Property::VECTOR2:
+      {
+        const SceneGraph::AnimatableProperty<Vector2>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Vector2>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector2>::Bake, value.Get<Vector2>() );
+
+        break;
+      }
+
+      case Property::VECTOR3:
+      {
+        const SceneGraph::AnimatableProperty<Vector3>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Vector3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector3>::Bake, value.Get<Vector3>() );
+
+        break;
+      }
+
+      case Property::VECTOR4:
+      {
+        const SceneGraph::AnimatableProperty<Vector4>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Vector4>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Vector4>::Bake, value.Get<Vector4>() );
+
+        break;
+      }
+
+      case Property::ROTATION:
+      {
+        const SceneGraph::AnimatableProperty<Quaternion>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Quaternion>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Quaternion>::Bake,  value.Get<Quaternion>() );
+
+        break;
+      }
+
+      case Property::MATRIX:
+      {
+        const SceneGraph::AnimatableProperty<Matrix>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Matrix>::Send( eventThreadServices, sceneObject, property,&SceneGraph::AnimatableProperty<Matrix>::Bake,  value.Get<Matrix>() );
+
+        break;
+      }
+
+      case Property::MATRIX3:
+      {
+        const SceneGraph::AnimatableProperty<Matrix3>* property = dynamic_cast< const SceneGraph::AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        // property is being used in a separate thread; queue a message to set the property
+        SceneGraph::AnimatablePropertyMessage<Matrix3>::Send( eventThreadServices, sceneObject, property, &SceneGraph::AnimatableProperty<Matrix3>::Bake,  value.Get<Matrix3>() );
+
+        break;
+      }
+
+      default:
+      {
+        DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should not come here
+        break;
+      }
+    }
+  }
+
+  int GetPropertyComponentIndex( Property::Index index ) const
+  {
+    // TODO: MESH_REWORK
+    DALI_ASSERT_ALWAYS( false && "TODO: MESH_REWORK" );
+    return 0;
+  }
+};
+
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_OBJECT_IMPL_HELPER_H
diff --git a/dali/internal/event/common/object-impl.cpp b/dali/internal/event/common/object-impl.cpp
new file mode 100644 (file)
index 0000000..f50fb07
--- /dev/null
@@ -0,0 +1,1288 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/object-impl.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner-messages.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/event/common/type-registry-impl.h>
+
+using Dali::Internal::SceneGraph::AnimatableProperty;
+using Dali::Internal::SceneGraph::PropertyBase;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+const int SUPPORTED_CAPABILITIES = Dali::Handle::DYNAMIC_PROPERTIES;  // Object provides this capability
+typedef Dali::Vector<Object::Observer*>::Iterator ObserverIter;
+typedef Dali::Vector<Object::Observer*>::ConstIterator ConstObserverIter;
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_OBJECT" );
+#endif
+
+
+} // unnamed namespace
+
+Object::Object()
+: mEventThreadServices( *Stage::GetCurrent() ),
+  mTypeInfo( NULL ),
+  mConstraints( NULL ),
+  mPropertyNotifications( NULL )
+{
+}
+
+void Object::AddObserver(Observer& observer)
+{
+  // make sure an observer doesn't observe the same object twice
+  // otherwise it will get multiple calls to OnSceneObjectAdd(), OnSceneObjectRemove() and ObjectDestroyed()
+  DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer));
+
+  mObservers.PushBack( &observer );
+}
+
+void Object::RemoveObserver(Observer& observer)
+{
+  // Find the observer...
+  const ConstObserverIter endIter =  mObservers.End();
+  for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  {
+    if( (*iter) == &observer)
+    {
+      mObservers.Erase( iter );
+      break;
+    }
+  }
+  DALI_ASSERT_DEBUG(endIter != mObservers.End());
+}
+
+void Object::OnSceneObjectAdd()
+{
+  // Notification for observers
+  for( ConstObserverIter iter = mObservers.Begin(),  endIter =  mObservers.End(); iter != endIter; ++iter)
+  {
+    (*iter)->SceneObjectAdded(*this);
+  }
+
+  // enable property notifications in scene graph
+  EnablePropertyNotifications();
+}
+
+void Object::OnSceneObjectRemove()
+{
+  // Notification for observers
+  for( ConstObserverIter iter = mObservers.Begin(), endIter = mObservers.End(); iter != endIter; ++iter )
+  {
+    (*iter)->SceneObjectRemoved(*this);
+  }
+
+  // disable property notifications in scene graph
+  DisablePropertyNotifications();
+}
+
+int Object::GetPropertyComponentIndex( Property::Index index ) const
+{
+  int componentIndex = Property::INVALID_COMPONENT_INDEX;
+
+  const TypeInfo* typeInfo( GetTypeInfo() );
+  if ( typeInfo )
+  {
+    componentIndex = typeInfo->GetComponentIndex(index);
+  }
+
+  // For animatable property, check whether it is registered already and register it if not yet.
+  if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) && ( NULL == RegisterAnimatableProperty(index) ) )
+  {
+    componentIndex = Property::INVALID_COMPONENT_INDEX;
+  }
+
+  return componentIndex;
+}
+
+bool Object::Supports( Capability capability ) const
+{
+  return (capability & SUPPORTED_CAPABILITIES);
+}
+
+unsigned int Object::GetPropertyCount() const
+{
+  unsigned int count = GetDefaultPropertyCount();
+
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Default Properties: %d\n", count );
+
+  const TypeInfo* typeInfo( GetTypeInfo() );
+  if ( typeInfo )
+  {
+    unsigned int manual( typeInfo->GetPropertyCount() );
+    count += manual;
+
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Manual Properties:  %d\n", manual );
+  }
+
+  unsigned int custom( mCustomProperties.Count() );
+  count += custom;
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Custom Properties:  %d\n", custom );
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "Total Properties:   %d\n", count );
+
+  return count;
+}
+
+std::string Object::GetPropertyName( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index out of bounds" );
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    return GetDefaultPropertyName( index );
+  }
+
+  if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+    || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      return typeInfo->GetPropertyName( index );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Property index is invalid" );
+    }
+  }
+
+  CustomPropertyMetadata* custom = FindCustomProperty( index );
+  if( custom )
+  {
+    return custom->name;
+  }
+  return "";
+}
+
+Property::Index Object::GetPropertyIndex(const std::string& name) const
+{
+  Property::Index index = GetDefaultPropertyIndex( name );
+
+  if(index == Property::INVALID_INDEX)
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      index = typeInfo->GetPropertyIndex( name );
+      if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+      {
+        // check whether the animatable property is registered already, if not then register one.
+        if ( NULL == RegisterAnimatableProperty(index) )
+        {
+          index = Property::INVALID_INDEX;
+        }
+      }
+    }
+  }
+
+  if( (index == Property::INVALID_INDEX)&&( mCustomProperties.Count() > 0 ) )
+  {
+    Property::Index count = PROPERTY_CUSTOM_START_INDEX;
+    const PropertyMetadataLookup::ConstIterator end = mCustomProperties.End();
+    for( PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin(); iter != end; ++iter, ++count )
+    {
+      CustomPropertyMetadata* custom = static_cast<CustomPropertyMetadata*>(*iter);
+      if ( custom->name == name )
+      {
+        index = count;
+        break;
+      }
+    }
+  }
+
+  return index;
+}
+
+bool Object::IsPropertyWritable( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
+
+  bool writable = false;
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    writable = IsDefaultPropertyWritable( index );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      writable = typeInfo->IsPropertyWritable( index );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Invalid property index" );
+    }
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // Type Registry scene-graph properties are writable.
+    writable = true;
+  }
+  else
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom )
+    {
+      writable = custom->IsWritable();
+    }
+  }
+
+  return writable;
+}
+
+bool Object::IsPropertyAnimatable( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
+
+  bool animatable = false;
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    animatable = IsDefaultPropertyAnimatable( index );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // Type Registry event-thread only properties are not animatable.
+    animatable = false;
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // Type Registry scene-graph properties are animatable.
+    animatable = true;
+  }
+  else
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom )
+    {
+      animatable = custom->IsAnimatable();
+    }
+  }
+
+  return animatable;
+}
+
+bool Object::IsPropertyAConstraintInput( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds");
+
+  bool isConstraintInput = false;
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    isConstraintInput = IsDefaultPropertyAConstraintInput( index );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // Type Registry event-thread only properties cannot be used as an input to a constraint.
+    isConstraintInput = false;
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // scene graph properties can be used as input to a constraint.
+    isConstraintInput = true;
+  }
+  else
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom )
+    {
+      // ... custom properties can be used as input to a constraint.
+      isConstraintInput = true;
+    }
+  }
+
+  return isConstraintInput;
+}
+
+Property::Type Object::GetPropertyType( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    return GetDefaultPropertyType( index );
+  }
+
+  if ( ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+    || ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      return typeInfo->GetPropertyType( index );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Cannot find property index" );
+    }
+  }
+
+  CustomPropertyMetadata* custom = FindCustomProperty( index );
+  if( custom )
+  {
+    return custom->type;
+  }
+  return Property::NONE;
+}
+
+void Object::SetProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  DALI_ASSERT_ALWAYS(index > Property::INVALID_INDEX && "Property index is out of bounds" );
+
+  bool propertySet( true );
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    SetDefaultProperty( index, propertyValue );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      typeInfo->SetProperty( this, index, propertyValue );
+    }
+    else
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+      propertySet = false;
+    }
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // check whether the animatable property is registered already, if not then register one.
+    AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
+    if(!animatableProperty)
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+      propertySet = false;
+    }
+    else
+    {
+      // set the scene graph property value
+      SetSceneGraphProperty( index, *animatableProperty, propertyValue );
+    }
+  }
+  else
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if( custom )
+    {
+      if( custom->IsAnimatable() )
+      {
+        // set the scene graph property value
+        SetSceneGraphProperty( index, *custom, propertyValue );
+      }
+      else if( custom->IsWritable() )
+      {
+        custom->value = propertyValue;
+      }
+      else
+      {
+        // trying to set value on read only property is no-op
+        propertySet = false;
+      }
+    }
+    else
+    {
+      DALI_LOG_ERROR("Invalid property index\n");
+      propertySet = false;
+    }
+  }
+
+  // Let derived classes know that a property has been set
+  // TODO: We should not call this for read-only properties, SetDefaultProperty() && TypeInfo::SetProperty() should return a bool, which would be true if the property is set
+  if ( propertySet )
+  {
+    OnPropertySet(index, propertyValue);
+  }
+}
+
+Property::Value Object::GetProperty(Property::Index index) const
+{
+  DALI_ASSERT_ALWAYS( index > Property::INVALID_INDEX && "Property index is out of bounds" );
+
+  Property::Value value;
+
+  if ( index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    value = GetDefaultProperty( index );
+  }
+  else if ( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if ( typeInfo )
+    {
+      value = typeInfo->GetProperty( this, index );
+    }
+    else
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+    }
+  }
+  else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+  {
+    // check whether the animatable property is registered already, if not then register one.
+    AnimatablePropertyMetadata* animatableProperty = RegisterAnimatableProperty( index );
+    if(!animatableProperty)
+    {
+      DALI_LOG_ERROR("Cannot find property index\n");
+    }
+    else
+    {
+      // get the animatable property value
+      value = GetPropertyValue( animatableProperty );
+    }
+  }
+  else if(mCustomProperties.Count() > 0)
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    if(custom)
+    {
+      // get the custom property value
+      value = GetPropertyValue( custom );
+    }
+    else
+    {
+      DALI_LOG_ERROR("Invalid property index\n");
+    }
+  } // if custom
+
+  return value;
+}
+
+void Object::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Clear();
+
+  // Default Properties
+  GetDefaultPropertyIndices( indices );
+
+  // Manual Properties
+  const TypeInfo* typeInfo( GetTypeInfo() );
+  if ( typeInfo )
+  {
+    typeInfo->GetPropertyIndices( indices );
+  }
+
+  // Custom Properties
+  if ( mCustomProperties.Count() > 0 )
+  {
+    indices.Reserve( indices.Size() + mCustomProperties.Count() );
+
+    PropertyMetadataLookup::ConstIterator iter = mCustomProperties.Begin();
+    const PropertyMetadataLookup::ConstIterator endIter = mCustomProperties.End();
+    int i=0;
+    for ( ; iter != endIter; ++iter, ++i )
+    {
+      indices.PushBack( PROPERTY_CUSTOM_START_INDEX + i );
+    }
+  }
+}
+
+Property::Index Object::RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const
+{
+  // Create a new property
+  Dali::Internal::OwnerPointer<PropertyBase> newProperty;
+
+  switch ( propertyValue.GetType() )
+  {
+    case Property::BOOLEAN:
+    {
+      newProperty = new AnimatableProperty<bool>( propertyValue.Get<bool>() );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      newProperty = new AnimatableProperty<int>( propertyValue.Get<int>() );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      newProperty = new AnimatableProperty<float>( propertyValue.Get<float>() );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      newProperty = new AnimatableProperty<Vector2>( propertyValue.Get<Vector2>() );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      newProperty = new AnimatableProperty<Vector3>( propertyValue.Get<Vector3>() );
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      newProperty = new AnimatableProperty<Vector4>( propertyValue.Get<Vector4>() );
+      break;
+    }
+
+    case Property::MATRIX:
+    {
+      newProperty = new AnimatableProperty<Matrix>( propertyValue.Get<Matrix>() );
+      break;
+    }
+
+    case Property::MATRIX3:
+    {
+      newProperty = new AnimatableProperty<Matrix3>( propertyValue.Get<Matrix3>() );
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      newProperty = new AnimatableProperty<Quaternion>( propertyValue.Get<Quaternion>() );
+      break;
+    }
+
+    case Property::RECTANGLE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    case Property::NONE:
+    {
+      DALI_ASSERT_ALWAYS( !"PropertyType is not animatable" );
+      break;
+    }
+  }
+
+  // get the scene property owner from derived class
+  const SceneGraph::PropertyOwner* scenePropertyOwner = GetPropertyOwner();
+  // we can only pass properties to scene graph side if there is a scene object
+  if( scenePropertyOwner )
+  {
+    // keep a local pointer to the property as the OwnerPointer will pass its copy to the message
+    const PropertyBase* property = newProperty.Get();
+    if(index >= PROPERTY_CUSTOM_START_INDEX)
+    {
+      mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue.GetType(), property ) );
+    }
+    else
+    {
+      mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, Property::INVALID_COMPONENT_INDEX, propertyValue.GetType(), property ) ); // base property
+    }
+
+    // queue a message to add the property
+    InstallCustomPropertyMessage( const_cast<EventThreadServices&>(GetEventThreadServices()), *scenePropertyOwner, newProperty.Release() ); // Message takes ownership
+
+    // notify the derived class (optional) method in case it needs to do some more work on the new property
+    // note! have to use the local pointer as OwnerPointer now points to NULL as it handed over its ownership
+    NotifyScenePropertyInstalled( *property, name, index );
+
+    return index;
+  }
+  else
+  {
+    // property was orphaned and killed so return invalid index
+    return Property::INVALID_INDEX;
+  }
+}
+
+Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue)
+{
+  Property::Index index = RegisterSceneGraphProperty(name, PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count(), propertyValue);
+
+  /// @todo: don't keep a table of mappings per handle.
+  AddUniformMapping(index, name);
+
+  return index;
+}
+
+Property::Index Object::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode)
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  if(Property::ANIMATABLE == accessMode)
+  {
+    index = RegisterProperty(name, propertyValue);
+  }
+  else
+  {
+    // Add entry to the property lookup
+    index = PROPERTY_CUSTOM_START_INDEX + mCustomProperties.Count();
+    mCustomProperties.PushBack( new CustomPropertyMetadata( name, propertyValue, accessMode ) );
+  }
+
+  return index;
+}
+
+Dali::PropertyNotification Object::AddPropertyNotification(Property::Index index,
+                                                                int componentIndex,
+                                                                const Dali::PropertyCondition& condition)
+{
+  if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    if ( index <= PROPERTY_REGISTRATION_MAX_INDEX )
+    {
+      DALI_ASSERT_ALWAYS( false && "Property notification added to event side only property." );
+    }
+    else if ( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+    {
+      // check whether the animatable property is registered already, if not then register one.
+      AnimatablePropertyMetadata* animatable = RegisterAnimatableProperty( index );
+      DALI_ASSERT_ALWAYS( animatable && "Property index is invalid" );
+    }
+    else if ( mCustomProperties.Count() > 0 )
+    {
+      CustomPropertyMetadata* custom = FindCustomProperty( index );
+      DALI_ASSERT_ALWAYS( custom && "Invalid property index" );
+      DALI_ASSERT_ALWAYS( custom->IsAnimatable() && "Property notification added to event side only property." );
+    }
+  }
+
+  Dali::Handle self(this);
+  Property target( self, index );
+
+  PropertyNotificationPtr internal = PropertyNotification::New( target, componentIndex, condition );
+  Dali::PropertyNotification propertyNotification(internal.Get());
+
+  if( !mPropertyNotifications )
+  {
+    mPropertyNotifications = new PropertyNotificationContainer;
+  }
+  mPropertyNotifications->push_back(propertyNotification);
+
+  return propertyNotification;
+}
+
+void Object::RemovePropertyNotification(Dali::PropertyNotification propertyNotification)
+{
+  if( mPropertyNotifications )
+  {
+    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
+    while(iter != mPropertyNotifications->end() )
+    {
+      if(*iter == propertyNotification)
+      {
+        mPropertyNotifications->erase(iter);
+        // As we can't ensure all references are removed, we can just disable
+        // the notification.
+        GetImplementation(propertyNotification).Disable();
+        return;
+      }
+      ++iter;
+    }
+  }
+}
+
+void Object::RemovePropertyNotifications()
+{
+  if( mPropertyNotifications )
+  {
+    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
+    while(iter != mPropertyNotifications->end() )
+    {
+      // As we can't ensure all references are removed, we can just disable
+      // the notification.
+      GetImplementation(*iter).Disable();
+      ++iter;
+    }
+
+    mPropertyNotifications->clear();
+  }
+}
+
+void Object::EnablePropertyNotifications()
+{
+  if( mPropertyNotifications )
+  {
+    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
+    PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
+
+    for( ; iter != endIter; ++iter )
+    {
+      GetImplementation(*iter).Enable();
+    }
+  }
+}
+
+void Object::DisablePropertyNotifications()
+{
+  if( mPropertyNotifications )
+  {
+    PropertyNotificationContainerIter iter = mPropertyNotifications->begin();
+    PropertyNotificationContainerIter endIter = mPropertyNotifications->end();
+
+    for( ; iter != endIter; ++iter )
+    {
+      GetImplementation(*iter).Disable();
+    }
+  }
+}
+
+void Object::AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName )
+{
+  // Get the address of the property if it's a scene property
+  const PropertyInputImpl* propertyPtr = GetSceneObjectInputProperty( propertyIndex );
+
+  // Check instead for newly registered properties
+  if( propertyPtr == NULL )
+  {
+    PropertyMetadata* animatable = FindAnimatableProperty( propertyIndex );
+    if( animatable != NULL )
+    {
+      propertyPtr = animatable->GetSceneGraphProperty();
+    }
+  }
+
+  if( propertyPtr == NULL )
+  {
+    PropertyMetadata* custom = FindCustomProperty( propertyIndex );
+    if( custom != NULL )
+    {
+      propertyPtr = custom->GetSceneGraphProperty();
+    }
+  }
+
+  // @todo MESH_REWORK Store mappings for unstaged objects?
+
+  if( propertyPtr != NULL )
+  {
+    const SceneGraph::PropertyOwner* sceneObject = GetPropertyOwner();
+
+    if( sceneObject != NULL )
+    {
+      SceneGraph::UniformPropertyMapping* map = new SceneGraph::UniformPropertyMapping( uniformName, propertyPtr );
+      // Message takes ownership of Uniform map (and will delete it after copy)
+      AddUniformMapMessage( GetEventThreadServices(), *sceneObject, map);
+    }
+    else
+    {
+      // @todo MESH_REWORK FIXME Need to store something that can be sent to the scene
+      // object when staged.
+      DALI_ASSERT_ALWAYS(0 && "MESH_REWORK - Need to store property whilst off-stage" );
+    }
+  }
+}
+
+void Object::RemoveUniformMapping( const std::string& uniformName )
+{
+  const SceneGraph::PropertyOwner* sceneObject = GetSceneObject();
+  RemoveUniformMapMessage( GetEventThreadServices(), *sceneObject, uniformName);
+}
+
+Property::Value Object::GetPropertyValue( const PropertyMetadata* entry ) const
+{
+  Property::Value value;
+
+  DALI_ASSERT_ALWAYS( entry && "Invalid property metadata" );
+
+  if( !entry->IsAnimatable() )
+  {
+    value = entry->value;
+  }
+  else
+  {
+    BufferIndex bufferIndex( GetEventThreadServices().GetEventBufferIndex() );
+
+    switch ( entry->type )
+    {
+      case Property::BOOLEAN:
+      {
+        const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      case Property::INTEGER:
+      {
+        const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      case Property::FLOAT:
+      {
+        const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      case Property::VECTOR2:
+      {
+        const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        if(entry->componentIndex == 0)
+        {
+          value = (*property)[ bufferIndex ].x;
+        }
+        else if(entry->componentIndex == 1)
+        {
+          value = (*property)[ bufferIndex ].y;
+        }
+        else
+        {
+          value = (*property)[ bufferIndex ];
+        }
+        break;
+      }
+
+      case Property::VECTOR3:
+      {
+        const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        if(entry->componentIndex == 0)
+        {
+          value = (*property)[ bufferIndex ].x;
+        }
+        else if(entry->componentIndex == 1)
+        {
+          value = (*property)[ bufferIndex ].y;
+        }
+        else if(entry->componentIndex == 2)
+        {
+          value = (*property)[ bufferIndex ].z;
+        }
+        else
+        {
+          value = (*property)[ bufferIndex ];
+        }
+        break;
+      }
+
+      case Property::VECTOR4:
+      {
+        const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        if(entry->componentIndex == 0)
+        {
+          value = (*property)[ bufferIndex ].x;
+        }
+        else if(entry->componentIndex == 1)
+        {
+          value = (*property)[ bufferIndex ].y;
+        }
+        else if(entry->componentIndex == 2)
+        {
+          value = (*property)[ bufferIndex ].z;
+        }
+        else if(entry->componentIndex == 3)
+        {
+          value = (*property)[ bufferIndex ].w;
+        }
+        else
+        {
+          value = (*property)[ bufferIndex ];
+        }
+        break;
+      }
+
+      case Property::MATRIX:
+      {
+        const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      case Property::MATRIX3:
+      {
+        const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      case Property::ROTATION:
+      {
+        const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry->GetSceneGraphProperty() );
+        DALI_ASSERT_DEBUG( NULL != property );
+
+        value = (*property)[ bufferIndex ];
+        break;
+      }
+
+      default:
+      {
+        DALI_ASSERT_ALWAYS( false && "PropertyType enumeration is out of bounds" );
+        break;
+      }
+    } // switch(type)
+  } // if animatable
+
+  return value;
+}
+
+void Object::SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value )
+{
+  switch ( entry.type )
+  {
+    case Property::BOOLEAN:
+    {
+      const AnimatableProperty<bool>* property = dynamic_cast< const AnimatableProperty<bool>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<bool>( GetEventThreadServices(), *property, value.Get<bool>() );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      const AnimatableProperty<int>* property = dynamic_cast< const AnimatableProperty<int>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<int>( GetEventThreadServices(), *property, value.Get<int>() );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      const AnimatableProperty<float>* property = dynamic_cast< const AnimatableProperty<float>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<float>( GetEventThreadServices(), *property, value.Get<float>() );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      const AnimatableProperty<Vector2>* property = dynamic_cast< const AnimatableProperty<Vector2>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SetXComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SetYComponentMessage<Vector2>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else
+      {
+        BakeMessage<Vector2>( GetEventThreadServices(), *property, value.Get<Vector2>() );
+      }
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      const AnimatableProperty<Vector3>* property = dynamic_cast< const AnimatableProperty<Vector3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SetXComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SetYComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 2)
+      {
+        SetZComponentMessage<Vector3>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else
+      {
+        BakeMessage<Vector3>( GetEventThreadServices(), *property, value.Get<Vector3>() );
+      }
+
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      const AnimatableProperty<Vector4>* property = dynamic_cast< const AnimatableProperty<Vector4>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      if(entry.componentIndex == 0)
+      {
+        SetXComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 1)
+      {
+        SetYComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 2)
+      {
+        SetZComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else if(entry.componentIndex == 3)
+      {
+        SetWComponentMessage<Vector4>( GetEventThreadServices(), *property, value.Get<float>() );
+      }
+      else
+      {
+        BakeMessage<Vector4>( GetEventThreadServices(), *property, value.Get<Vector4>() );
+      }
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      const AnimatableProperty<Quaternion>* property = dynamic_cast< const AnimatableProperty<Quaternion>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Quaternion>( GetEventThreadServices(), *property, value.Get<Quaternion>() );
+      break;
+    }
+
+    case Property::MATRIX:
+    {
+      const AnimatableProperty<Matrix>* property = dynamic_cast< const AnimatableProperty<Matrix>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Matrix>( GetEventThreadServices(), *property, value.Get<Matrix>() );
+      break;
+    }
+
+    case Property::MATRIX3:
+    {
+      const AnimatableProperty<Matrix3>* property = dynamic_cast< const AnimatableProperty<Matrix3>* >( entry.GetSceneGraphProperty() );
+      DALI_ASSERT_DEBUG( NULL != property );
+
+      // property is being used in a separate thread; queue a message to set the property
+      BakeMessage<Matrix3>( GetEventThreadServices(), *property, value.Get<Matrix3>() );
+      break;
+    }
+
+    default:
+    {
+      // non-animatable scene graph property, do nothing
+    }
+  }
+}
+
+const TypeInfo* Object::GetTypeInfo() const
+{
+  if ( !mTypeInfo )
+  {
+    // This uses a dynamic_cast so can be quite expensive so we only really want to do it once
+    // especially as the type-info does not change during the life-time of an application
+
+    Dali::TypeInfo typeInfoHandle = TypeRegistry::Get()->GetTypeInfo( this );
+    if ( typeInfoHandle )
+    {
+      mTypeInfo = &GetImplementation( typeInfoHandle );
+    }
+  }
+
+  return mTypeInfo;
+}
+
+void Object::ApplyConstraint( ConstraintBase& constraint )
+{
+  if( !mConstraints )
+  {
+    mConstraints = new ConstraintContainer;
+  }
+  mConstraints->push_back( Dali::Constraint( &constraint ) );
+}
+
+void Object::RemoveConstraint( ConstraintBase& constraint )
+{
+  // NULL if the Constraint sources are destroyed before Constraint::Apply()
+  if( mConstraints )
+  {
+    ConstraintIter it( std::find( mConstraints->begin(), mConstraints->end(), Dali::Constraint( &constraint ) ) );
+    if( it != mConstraints->end() )
+    {
+      mConstraints->erase( it );
+    }
+  }
+}
+
+void Object::RemoveConstraints()
+{
+  // guard against constraint sending messages during core destruction
+  if( mConstraints && Stage::IsInstalled() )
+  {
+    // If we have nothing in the scene-graph, just clear constraint containers
+    const SceneGraph::PropertyOwner* propertyOwner = GetSceneObject();
+    if ( NULL != propertyOwner )
+    {
+      const ConstraintConstIter endIter = mConstraints->end();
+      for ( ConstraintIter iter = mConstraints->begin(); endIter != iter; ++iter )
+      {
+        GetImplementation( *iter ).RemoveInternal();
+      }
+    }
+
+    delete mConstraints;
+    mConstraints = NULL;
+  }
+}
+
+void Object::RemoveConstraints( unsigned int tag )
+{
+  // guard against constraint sending messages during core destruction
+  if( mConstraints && Stage::IsInstalled() )
+  {
+    ConstraintIter iter( mConstraints->begin() );
+    while(iter != mConstraints->end() )
+    {
+      ConstraintBase& constraint = GetImplementation( *iter );
+      if( constraint.GetTag() == tag )
+      {
+        GetImplementation( *iter ).RemoveInternal();
+        iter = mConstraints->erase( iter );
+      }
+      else
+      {
+        ++iter;
+      }
+    }
+
+    if ( mConstraints->empty() )
+    {
+      delete mConstraints;
+      mConstraints = NULL;
+    }
+  }
+}
+
+void Object::SetTypeInfo( const TypeInfo* typeInfo )
+{
+  mTypeInfo = typeInfo;
+}
+
+Object::~Object()
+{
+  // Notification for observers
+  for( ConstObserverIter iter = mObservers.Begin(), endIter =  mObservers.End(); iter != endIter; ++iter)
+  {
+    (*iter)->ObjectDestroyed(*this);
+  }
+
+  delete mConstraints;
+  delete mPropertyNotifications;
+}
+
+CustomPropertyMetadata* Object::FindCustomProperty( Property::Index index ) const
+{
+  CustomPropertyMetadata* property( NULL );
+  int arrayIndex = index - PROPERTY_CUSTOM_START_INDEX;
+  if( arrayIndex >= 0 )
+  {
+    if( arrayIndex < (int)mCustomProperties.Count() ) // we can only access the first 2 billion custom properties
+    {
+      property = static_cast<CustomPropertyMetadata*>(mCustomProperties[ arrayIndex ]);
+    }
+  }
+  return property;
+}
+
+AnimatablePropertyMetadata* Object::FindAnimatableProperty( Property::Index index ) const
+{
+  for ( int arrayIndex = 0; arrayIndex < (int)mAnimatableProperties.Count(); arrayIndex++ )
+  {
+    AnimatablePropertyMetadata* property = static_cast<AnimatablePropertyMetadata*>( mAnimatableProperties[ arrayIndex ] );
+    if( property->index == index )
+    {
+      return property;
+    }
+  }
+  return NULL;
+}
+
+AnimatablePropertyMetadata* Object::RegisterAnimatableProperty(Property::Index index) const
+{
+  DALI_ASSERT_ALWAYS( (( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ))
+                      && "Property index is out of bounds" );
+
+  // check whether the animatable property is registered already, if not then register one.
+  AnimatablePropertyMetadata* animatableProperty = FindAnimatableProperty( index );
+  if(!animatableProperty)
+  {
+    const TypeInfo* typeInfo( GetTypeInfo() );
+    if (typeInfo)
+    {
+      Property::Index basePropertyIndex = typeInfo->GetBasePropertyIndex(index);
+      if(basePropertyIndex == Property::INVALID_INDEX)
+      {
+        // If the property is not a component of a base property, register the whole property itself.
+        index = RegisterSceneGraphProperty(typeInfo->GetPropertyName(index), index, Property::Value(typeInfo->GetPropertyType(index)));
+      }
+      else
+      {
+        // Since the property is a component of a base property, check whether the base property is regsitered.
+        animatableProperty = FindAnimatableProperty( basePropertyIndex );
+        if(!animatableProperty)
+        {
+          // If the base property is not registered yet, register the base property first.
+          if(Property::INVALID_INDEX != RegisterSceneGraphProperty(typeInfo->GetPropertyName(basePropertyIndex), basePropertyIndex, Property::Value(typeInfo->GetPropertyType(basePropertyIndex))))
+          {
+            animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
+          }
+        }
+
+        if(animatableProperty)
+        {
+          // Create the metadata for the property component.
+          mAnimatableProperties.PushBack( new AnimatablePropertyMetadata( index, typeInfo->GetComponentIndex(index), animatableProperty->type, animatableProperty->GetSceneGraphProperty() ) );
+        }
+      }
+
+      // The metadata has just been added and therefore should be in the end of the vector.
+      animatableProperty = static_cast<AnimatablePropertyMetadata*>(mAnimatableProperties[mAnimatableProperties.Size()-1]);
+    }
+  }
+
+  return animatableProperty;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/object-impl.h b/dali/internal/event/common/object-impl.h
new file mode 100644 (file)
index 0000000..ddc5498
--- /dev/null
@@ -0,0 +1,556 @@
+#ifndef __DALI_INTERNAL_OBJECT_H__
+#define __DALI_INTERNAL_OBJECT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-notification.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/event/common/property-metadata.h>
+#include <dali/internal/update/common/property-base.h>
+
+namespace Dali
+{
+
+class PropertyNotification;
+
+namespace Internal
+{
+class ConstraintBase;
+class EventThreadServices;
+class Handle;
+class PropertyCondition;
+class PropertyInputImpl;
+class Stage;
+class TypeInfo;
+
+namespace SceneGraph
+{
+class PropertyBase;
+class PropertyOwner;
+}
+
+typedef std::vector< Dali::Constraint >     ConstraintContainer;
+typedef ConstraintContainer::iterator       ConstraintIter;
+typedef ConstraintContainer::const_iterator ConstraintConstIter;
+
+
+/**
+ * A base class for objects which optionally provide properties.
+ * The concrete derived class is responsible for implementing the property system methods.
+ * Classes may derive from Dali::BaseObject, until any properties are required.
+ *
+ * An object for a property-owning object in the scene-graph.
+ * This provides an interface for observing the addition/removal of scene-objects.
+ *
+ * The concrete derived class is responsible for:
+ *   1) Adding & removing an object from the scene-graph. The OnSceneObjectAdd() and OnSceneObjectRemove()
+ *      methods should be called by the derived class, to trigger observer callbacks.
+ *   3) Implementing the GetSceneObject() methods, used to access the scene-object.
+ *   4) Providing access to properties stored by the scene-graph object. These should match the properties
+ *      reported by the base Dali::Internal::Object methods.
+ *
+ */
+class Object : public Dali::BaseObject
+{
+public:
+
+  typedef Dali::Handle::Capability Capability;
+
+  class Observer
+  {
+  public:
+
+    /**
+     * Called immediately after the object has created & passed ownership of a scene-graph object.
+     * @param[in] object The object object.
+     */
+    virtual void SceneObjectAdded(Object& object) = 0;
+
+    /**
+     * Called shortly before the object sends a message to remove its scene object.
+     * @param[in] object The object object.
+     */
+    virtual void SceneObjectRemoved(Object& object) = 0;
+
+    /**
+     * Called shortly before the object itself is destroyed; no further callbacks will be received.
+     * @param[in] object The object object.
+     */
+    virtual void ObjectDestroyed(Object& object) = 0;
+
+  protected:
+
+    /**
+     * Virtual destructor
+     */
+    virtual ~Observer(){}
+  };
+
+  /**
+   * Constructor.
+   */
+  Object();
+
+  /**
+   * Add an observer to the object.
+   * @param[in] observer The observer to add.
+   */
+  virtual void AddObserver( Observer& observer );
+
+  /**
+   * Remove an observer from the object
+   * @pre The observer has already been added.
+   * @param[in] observer The observer to remove.
+   */
+  virtual void RemoveObserver( Observer& observer );
+
+  /**
+   * @copydoc Dali::Handle::Supports()
+   */
+  virtual bool Supports( Capability capability ) const;
+
+  /**
+   * @copydoc Dali::Handle::GetPropertyCount()
+   */
+  virtual unsigned int GetPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Handle::GetPropertyName()
+   */
+  virtual std::string GetPropertyName( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::GetPropertyIndex()
+   */
+  virtual Property::Index GetPropertyIndex( const std::string& name ) const;
+
+  /**
+   * @copydoc Dali::Handle::IsPropertyWritable()
+   */
+  virtual bool IsPropertyWritable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::IsPropertyAnimatable()
+   */
+  virtual bool IsPropertyAnimatable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::IsPropertyAConstraintInput()
+   */
+  virtual bool IsPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::GetPropertyType()
+   */
+  virtual Property::Type GetPropertyType( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::SetProperty()
+   */
+  virtual void SetProperty( Property::Index index, const Property::Value& propertyValue );
+
+  /**
+   * @copydoc Dali::Handle::GetProperty()
+   */
+  virtual Property::Value GetProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Handle::GetPropertyIndices()
+   */
+  virtual void GetPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Handle::RegisterProperty()
+   */
+  virtual Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue );
+
+  /**
+   * @copydoc Dali::Handle::RegisterProperty(std::string name, Property::Value propertyValue, Property::AccessMode accessMode)
+   */
+  virtual Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode );
+
+  /**
+   * @copydoc Dali::Handle::AddPropertyNotification()
+   */
+  virtual Dali::PropertyNotification AddPropertyNotification( Property::Index index,
+                                                              int componentIndex,
+                                                              const Dali::PropertyCondition& condition );
+
+  /**
+   * @copydoc Dali::Handle::RemovePropertyNotification()
+   */
+  virtual void RemovePropertyNotification( Dali::PropertyNotification propertyNotification );
+
+  /**
+   * @copydoc Dali::Handle::RemovePropertyNotifications()
+   */
+  virtual void RemovePropertyNotifications();
+
+  /******************************** Uniform Mappings ********************************/
+
+  /**
+   * @copydoc Dali::Handle::AddUniformMapping()
+   */
+  void AddUniformMapping( Property::Index propertyIndex, const std::string& uniformName );
+
+  /**
+   * @copydoc Dali::Handle::RemoveUniformMapping( )
+   */
+  void RemoveUniformMapping( const std::string& uniformName );
+
+  /******************************** Constraints ********************************/
+
+  /**
+   * Apply a constraint to an Object.
+   * @param[in] constraint The constraint to apply.
+   */
+  void ApplyConstraint( ConstraintBase& constraint );
+
+  /**
+   * Remove one constraint from an Object.
+   * @param[in] constraint The constraint to remove.
+   */
+  void RemoveConstraint( ConstraintBase& constraint );
+
+  /**
+   * Remove all constraints from a Object.
+   */
+  void RemoveConstraints();
+
+  /**
+   * Remove all constraints from a Object with a matching tag
+   */
+  void RemoveConstraints( unsigned int tag );
+
+  /**
+   * Called by TypeInfo to set the type-info that this object-impl is created by.
+   * @param[in] typeInfo The TypeInfo that creates this object-impl.
+   */
+  void SetTypeInfo( const TypeInfo* typeInfo );
+
+  /**
+   * @return the index from which custom properties start
+   */
+  unsigned int CustomPropertyStartIndex()
+  {
+    return PROPERTY_CUSTOM_START_INDEX;
+  }
+
+  /********************  To be overridden by deriving classes ********************/
+
+  /**
+   * Retrieve the scene-graph object added by this object.
+   * @return A pointer to the object, or NULL if no object has been added to the scene-graph.
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const = 0;
+
+  /**
+   * Retrieve an animatable property owned by the scene-graph object.
+   * @pre -1 < index < GetPropertyCount().
+   * @param[in] index The index of the property.
+   * @return A dereferenceable pointer to a property, or NULL if a scene-object does not exist with this property.
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const = 0;
+
+  /**
+   * Retrieve a constraint input-property owned by the scene-graph object.
+   * @pre -1 < index < GetPropertyCount().
+   * @param[in] index The index of the property.
+   * @return A dereferenceable pointer to an input property, or NULL if a scene-object does not exist with this property.
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const = 0;
+
+  /**
+   * Query whether the property is a component of a scene-graph property.
+   * @pre -1 < index < GetPropertyCount().
+   * @param[in] index The index of the property.
+   * @return The index or Property::INVALID_COMPONENT_INDEX.
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Object();
+
+  /**
+   * Called immediately by derived classes, after the scene-object has been created & passed to the scene-graph.
+   */
+  void OnSceneObjectAdd();
+
+  /**
+   * Called by derived classes, shortly before send a message to remove the scene-object.
+   */
+  void OnSceneObjectRemove();
+
+  /**
+   * For use in derived classes.
+   * This is called after a property is set.
+   * @param [in] index The index of the property.
+   * @param [in] propertyValue The value of the property.
+   */
+  virtual void OnPropertySet( Property::Index index, Property::Value propertyValue ) {}
+
+  /**
+   * Retrieves the TypeInfo for this object. Only retrieves it from the type-registry once and then stores a pointer
+   * to it locally there-after. The type info will not change during the life-time of the application.
+   * @return The type-info for this object (Can be NULL)
+   */
+  const TypeInfo* GetTypeInfo() const;
+
+  /**
+   * Helper to find custom property
+   * @param index
+   * @return pointer to the property
+   */
+  CustomPropertyMetadata* FindCustomProperty( Property::Index index ) const;
+
+  /**
+   * Helper to find animatable property
+   * @param index
+   * @return pointer to the property
+   */
+  AnimatablePropertyMetadata* FindAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * Helper to register a scene-graph property
+   * @param [in] name The name of the property.
+   * @param [in] index The index of the property
+   * @param [in] value The value of the property.
+   * @return The index of the registered property or Property::INVALID_INDEX if registration failed.
+   */
+  Property::Index RegisterSceneGraphProperty(const std::string& name, Property::Index index, const Property::Value& propertyValue) const;
+
+  /**
+   * Check whether the animatable property is registered already, if not then register one.
+   * @param [in] index The index of the property
+   * @return pointer to the property.
+   */
+  AnimatablePropertyMetadata* RegisterAnimatableProperty(Property::Index index) const;
+
+private: // Default property extensions for derived classes
+
+  /**
+   * Query how many default properties the derived class supports.
+   * @return The number of default properties.
+   */
+  virtual unsigned int GetDefaultPropertyCount() const = 0;
+
+  /**
+   * Retrieve all the indices that are associated with the default properties supported by the derived class.
+   * @return A container of default property indices.
+   * @note The deriving class must not modify the existing elements in the container.
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const = 0;
+
+  /**
+   * Query how many default properties the derived class supports.
+   * @return The number of default properties.
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const = 0;
+
+  /**
+   * Query the index of a default property.
+   * @param [in] name The name of the property.
+   * @return The index of the property, or Property::INVALID_INDEX if no default property exists with the given name.
+   */
+  virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const = 0;
+
+  /**
+   * Query whether a default property is writable.
+   * @param [in] index The index of the property.
+   * @return True if the property is animatable.
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const = 0;
+
+  /**
+   * Query whether a default property is animatable.
+   * This determines whether the property can be the target of an animation or constraint.
+   * @param [in] index The index of the property.
+   * @return True if the property is animatable.
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const = 0;
+
+  /**
+   * @brief Query whether a default property can be used as an input to a constraint.
+   *
+   * @param [in] index The index of the property.
+   * @return True if the property can be used as an input to a constraint.
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const = 0;
+
+  /**
+   * Query the type of a default property.
+   * @param [in] index The index of the property.
+   * @return The type of the property.
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const = 0;
+
+  /**
+   * Set the value of a default property.
+   * @pre The property types match i.e. propertyValue.GetType() is equal to GetPropertyType(index).
+   * @param [in] index The index of the property.
+   * @param [in] propertyValue The new value of the property.
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue ) = 0;
+
+  /**
+   * Retrieve a default property value.
+   * @param [in] index The index of the property.
+   * @return The property value.
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const = 0;
+
+  /**
+   * @todo this is virtual so that for now actor can override it,
+   * it needs to be removed and only have GetSceneObject but that requires changing actor and constraint logic
+   * Retrieve the scene-graph object added by this object.
+   * @return A pointer to the object, or NULL if no object has been added to the scene-graph.
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const
+  {
+    return GetSceneObject();
+  }
+
+  /**
+   * Notify derived class of installation of a new scene-object property.
+   * This method is called after the message is to sent to install the property
+   * @param [in] newProperty A newly allocated scene-object property. Ownership is obviously not passed.
+   * @param [in] name The name allocated to this custom property.
+   * @param [in] index The index allocated to this custom property.
+   */
+  virtual void NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index ) const
+  { }
+
+private:
+
+  // Not implemented
+  Object(const Object& rhs);
+
+  // Not implemented
+  Object& operator=(const Object& rhs);
+
+  /**
+   * Enable property notifications in scene graph
+   */
+  void EnablePropertyNotifications();
+
+  /**
+   * Enable property notifications in scene graph
+   */
+  void DisablePropertyNotifications();
+
+  /**
+   * Get the value of the property.
+   * @param [in] entry An entry from the property lookup container.
+   * @return The new value of the property.
+   */
+  Property::Value GetPropertyValue( const PropertyMetadata* entry ) const;
+
+  /**
+   * Set the value of scene graph property.
+   * @param [in] index The index of the property.
+   * @param [in] entry An entry from the property lookup container.
+   * @param [in] value The new value of the property.
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+protected:
+  /**
+   * Get the event thread services object - used for sending messages to the scene graph
+   * Assert if called from the wrong thread.
+   * This is intentionally inline for performance reasons.
+   *
+   * @return The event thread services object
+   */
+  inline EventThreadServices& GetEventThreadServices()
+  {
+    DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() );
+    return mEventThreadServices;
+  }
+
+  /**
+   * Get the event thread services object - used for sending messages to the scene graph
+   * Assert if called from the wrong thread
+   * This is intentionally inline for performance reasons.
+   *
+   * @return The event thread services object
+   */
+  inline const EventThreadServices& GetEventThreadServices() const
+  {
+    DALI_ASSERT_DEBUG( EventThreadServices::IsCoreRunning() );
+    return mEventThreadServices;
+  }
+
+private:
+  EventThreadServices& mEventThreadServices;
+
+private:
+
+  typedef OwnerContainer<PropertyMetadata*> PropertyMetadataLookup;
+  mutable PropertyMetadataLookup mCustomProperties; ///< Used for accessing custom Node properties
+  mutable PropertyMetadataLookup mAnimatableProperties; ///< Used for accessing animatable Node properties
+  mutable TypeInfo const *  mTypeInfo; ///< The type-info for this object, mutable so it can be lazy initialized from const method if it is required
+
+  Dali::Vector<Observer*> mObservers;
+
+  ConstraintContainer* mConstraints;               ///< Container of owned -constraints.
+
+  typedef std::vector< Dali::PropertyNotification >     PropertyNotificationContainer;
+  typedef PropertyNotificationContainer::iterator       PropertyNotificationContainerIter;
+  typedef PropertyNotificationContainer::const_iterator PropertyNotificationContainerConstIter;
+  PropertyNotificationContainer* mPropertyNotifications; ///< Container of owned property notifications.
+};
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Object& GetImplementation(Dali::Handle& object)
+{
+  DALI_ASSERT_ALWAYS( object && "Object handle is empty" );
+
+  BaseObject& handle = object.GetBaseObject();
+
+  return static_cast<Internal::Object&>(handle);
+}
+
+inline const Internal::Object& GetImplementation(const Dali::Handle& object)
+{
+  DALI_ASSERT_ALWAYS( object && "Object handle is empty" );
+
+  const BaseObject& handle = object.GetBaseObject();
+
+  return static_cast<const Internal::Object&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_OBJECT_H__
diff --git a/dali/internal/event/common/object-registry-impl.cpp b/dali/internal/event/common/object-registry-impl.cpp
new file mode 100644 (file)
index 0000000..c97c94a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/object-registry-impl.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/public-api/object/object-registry.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_OBJECT_CREATED =   "object-created";
+const char* const SIGNAL_OBJECT_DESTROYED = "object-destroyed";
+
+TypeRegistration mType( typeid( Dali::ObjectRegistry ), typeid( Dali::BaseHandle ), NULL );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_OBJECT_CREATED,   &ObjectRegistry::DoConnectSignal );
+SignalConnectorType signalConnector2( mType, SIGNAL_OBJECT_DESTROYED, &ObjectRegistry::DoConnectSignal );
+
+}
+
+ObjectRegistryPtr ObjectRegistry::New()
+{
+  return ObjectRegistryPtr( new ObjectRegistry() );
+}
+
+ObjectRegistry::ObjectRegistry()
+{
+}
+
+ObjectRegistry::~ObjectRegistry()
+{
+}
+
+void ObjectRegistry::RegisterObject( Dali::BaseObject* object )
+{
+  if ( !mObjectCreatedSignal.Empty() )
+  {
+    Dali::BaseHandle handle( object );
+    mObjectCreatedSignal.Emit( handle );
+  }
+}
+
+void ObjectRegistry::UnregisterObject( Dali::BaseObject* object )
+{
+  mObjectDestroyedSignal.Emit( object );
+}
+
+bool ObjectRegistry::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  ObjectRegistry* objectRegistry = dynamic_cast<ObjectRegistry*>( object );
+
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_OBJECT_CREATED ) )
+  {
+    objectRegistry->ObjectCreatedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_OBJECT_DESTROYED ) )
+  {
+    objectRegistry->ObjectDestroyedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/object-registry-impl.h b/dali/internal/event/common/object-registry-impl.h
new file mode 100644 (file)
index 0000000..13f225f
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef __DALI_INTERNAL_OBJECT_REGISTRY_H__
+#define __DALI_INTERNAL_OBJECT_REGISTRY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/object/object-registry.h>
+#include <dali/public-api/object/base-object.h>
+
+namespace Dali
+{
+
+struct Vector2;
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+class ObjectRegistry;
+
+typedef IntrusivePtr<ObjectRegistry> ObjectRegistryPtr;
+
+/**
+ * The ObjectRegistry notifies it's observers when an object is created.
+ * There is a single instance of Object registry for each Dali-core instance.
+ * All Dali Objects need to register with ObjectRegistry to be observed by
+ * feedback plugin's and other observers.
+ */
+class ObjectRegistry : public BaseObject
+{
+public:
+
+  /**
+   * Create the objectRegistry
+   */
+  static ObjectRegistryPtr New();
+
+  /**
+   * Registers the Object into the Object Registry, which notifies
+   * about this object creation to its observers using signals. As
+   * the signals use a BaseHandle, the object must already have a
+   * ref-count > 0, otherwise it will get deleted on signal completion.
+   * @pre The object is not already registered.
+   * @pre the object is ref counted (held in an intrusive pointer)
+   * @param[in] object Pointer to the object.
+   */
+  void RegisterObject( Dali::BaseObject* object );
+
+  /**
+   * Unregisters the Object from the Object Registry, Which notifies
+   * about this object destruction to its observers.
+   * @pre The object is already registered.
+   * @param[in] object Pointer to the object.
+   */
+  void UnregisterObject( Dali::BaseObject* object );
+
+  /**
+   * @copydoc Dali::ObjectRegistry::ObjectCreatedSignal()
+   */
+  Dali::ObjectRegistry::ObjectCreatedSignalType& ObjectCreatedSignal()
+  {
+    return mObjectCreatedSignal;
+  }
+
+  /**
+   * @copydoc Dali::ObjectRegistry::ObjectDestroyedSignal()
+   */
+  Dali::ObjectRegistry::ObjectDestroyedSignalType& ObjectDestroyedSignal()
+  {
+    return mObjectDestroyedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object registry signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+private:
+
+  /**
+   * Protected constructor; see also ObjectRegistry::New()
+   */
+  ObjectRegistry();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  ~ObjectRegistry();
+
+private:
+
+  Dali::ObjectRegistry::ObjectCreatedSignalType mObjectCreatedSignal;
+  Dali::ObjectRegistry::ObjectDestroyedSignalType mObjectDestroyedSignal;
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ObjectRegistry& GetImplementation(Dali::ObjectRegistry& objectRegistry)
+{
+  DALI_ASSERT_ALWAYS( objectRegistry && "ObjectRegistry handle is empty" );
+
+  BaseObject& handle = objectRegistry.GetBaseObject();
+
+  return static_cast<Internal::ObjectRegistry&>(handle);
+}
+
+inline const Internal::ObjectRegistry& GetImplementation(const Dali::ObjectRegistry& objectRegistry)
+{
+  DALI_ASSERT_ALWAYS( objectRegistry && "ObjectRegistry handle is empty" );
+
+  const BaseObject& handle = objectRegistry.GetBaseObject();
+
+  return static_cast<const Internal::ObjectRegistry&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_OBJECT_REGISTRY_H__
diff --git a/dali/internal/event/common/projection.cpp b/dali/internal/event/common/projection.cpp
new file mode 100644 (file)
index 0000000..2783195
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/projection.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+bool Unproject( const Vector4& windowPos,
+                const Matrix& inverseMvp,
+                float viewportWidth,
+                float viewportHeight,
+                Vector4& objectPos )
+{
+  objectPos.x = windowPos.x;
+  objectPos.y = windowPos.y;
+  objectPos.z = windowPos.z;
+  objectPos.w = 1.0f;
+
+  objectPos.x = objectPos.x / viewportWidth;
+  objectPos.y = objectPos.y / viewportHeight;
+
+  objectPos.x = objectPos.x * 2.0f - 1.0f;
+  objectPos.y = objectPos.y * 2.0f - 1.0f;
+  objectPos.z = objectPos.z * 2.0f - 1.0f;
+
+  objectPos = inverseMvp * objectPos;
+
+  // In the case where objectPos.w is exactly zero, the unproject fails
+  if ( EqualsZero( objectPos.w ) )
+  {
+    return false;
+  }
+
+  objectPos.x /= objectPos.w;
+  objectPos.y /= objectPos.w;
+  objectPos.z /= objectPos.w;
+
+  return true;
+}
+
+bool UnprojectFull( const Vector4& windowPos,
+                    const Matrix& modelView,
+                    const Matrix& projection,
+                    float viewportWidth,
+                    float viewportHeight,
+                    Vector4& objectPos )
+{
+  Matrix invertedMvp( false ); // Don't initialize.
+  Matrix::Multiply( invertedMvp, modelView, projection );
+
+  if (invertedMvp.Invert())
+  {
+    return Unproject( windowPos, invertedMvp, viewportWidth, viewportHeight, objectPos );
+  }
+
+  return false;
+}
+
+bool XyPlaneIntersect( const Vector4& pointA, const Vector4& pointB, Vector4& intersect )
+{
+  const Vector4* near = NULL;
+  const Vector4* far = NULL;
+
+  if ( pointA.z > 0.0f && pointB.z < 0.0f )
+  {
+    near = &pointA;
+    far  = &pointB;
+  }
+  else if ( pointB.z > 0.0f && pointA.z < 0.0f )
+  {
+    near = &pointB;
+    far  = &pointA;
+  }
+  else
+  {
+    return false; // ray does not cross xy plane
+  }
+
+  float dist = near->z / (near->z - far->z);
+
+  intersect.x = near->x + (far->x - near->x) * dist;
+  intersect.y = near->y + (far->y - near->y) * dist;
+  intersect.z = 0.0f;
+
+  return true;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/projection.h b/dali/internal/event/common/projection.h
new file mode 100644 (file)
index 0000000..3719129
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __DALI_INTERNAL_PROJECTION_H__
+#define __DALI_INTERNAL_PROJECTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+struct Vector4;
+class Matrix;
+
+namespace Internal
+{
+
+bool XyPlaneIntersect(const Dali::Vector4& pointA,
+                      const Dali::Vector4& pointB,
+                      Dali::Vector4& intersect);
+
+bool UnprojectFull(const Dali::Vector4& windowPos,
+                   const Matrix& modelView,
+                   const Matrix& projection,
+                   float viewportWidth,
+                   float viewportHeight,
+                   Dali::Vector4& objectPos);
+
+bool Unproject(const Dali::Vector4& windowPos,
+               const Matrix& inverseMvp,
+               float viewportWidth,
+               float viewportHeight,
+               Dali::Vector4& objectPos);
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROJECTION_H__
+
diff --git a/dali/internal/event/common/property-buffer-impl.cpp b/dali/internal/event/common/property-buffer-impl.cpp
new file mode 100644 (file)
index 0000000..384e136
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
+
+// EXTERNAL INCLUDE
+#include <algorithm> // std::sort
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/object/property-buffer.h> // Dali::Internal::PropertyBuffer
+
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+using SceneGraph::PropertyBufferMetadata::Format;
+using SceneGraph::PropertyBufferMetadata::Component;
+
+namespace
+{
+
+/**
+ *            |name    |type             |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "size",          INTEGER, true,  false, true,   Dali::PropertyBuffer::Property::SIZE )
+DALI_PROPERTY( "buffer-format", MAP,     false, false, false,  Dali::PropertyBuffer::Property::BUFFER_FORMAT )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> PROPERTY_BUFFER_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::PropertyBuffer ), typeid( Dali::Handle ), Create );
+
+/**
+ * Calculate the alignment requirements of a type
+ *
+ * This is used to calculate the memory alignment requirements of a type
+ * It creates a structure with a dummy char and a member of the type we want to check
+ * this will cause the second member to be aligned by it's alignment requirement.
+ */
+template<Property::Type type>
+struct PropertyImplementationTypeAlignment
+{
+  // Create a structure that forces alignment of the data type
+  struct TestStructure
+  {
+    char oneChar;  ///< Member with sizeof() == 1
+    typename PropertyImplementationType<type>::Type data;
+  };
+  enum { VALUE = offsetof( TestStructure, data ) };
+};
+
+unsigned int GetPropertyImplementationAlignment( Property::Type& propertyType )
+{
+  unsigned int alignment = 0u;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    {
+      DALI_ASSERT_ALWAYS( false && "No size for properties with no type, or dynamic sizes" );
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::BOOLEAN >::VALUE;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::INTEGER >::VALUE;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::FLOAT >::VALUE;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR2 >::VALUE;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR3 >::VALUE;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::VECTOR4 >::VALUE;
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::MATRIX3 >::VALUE;
+      break;
+    }
+    case Property::MATRIX:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::MATRIX >::VALUE;
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::RECTANGLE >::VALUE;
+      break;
+    }
+    case Property::ROTATION:
+    {
+      alignment = PropertyImplementationTypeAlignment< Property::ROTATION >::VALUE;
+      break;
+    }
+  }
+
+  return alignment;
+}
+
+} // unnamed namespace
+
+PropertyBufferPtr PropertyBuffer::New()
+{
+  PropertyBufferPtr propertyBuffer( new PropertyBuffer() );
+  propertyBuffer->Initialize();
+
+  return propertyBuffer;
+}
+
+void PropertyBuffer::SetSize( std::size_t size )
+{
+  mSize = size;
+
+  SizeChanged();
+
+  SceneGraph::SetSizeMessage( GetEventThreadServices(),
+                              *mSceneObject,
+                              mSize );
+}
+
+std::size_t PropertyBuffer::GetSize() const
+{
+  return mSize;
+}
+
+void PropertyBuffer::SetData( const void* data )
+{
+  DALI_ASSERT_DEBUG( mFormat.Count() && "Format must be set before setting the data." );
+
+  DALI_ASSERT_ALWAYS( mSize && "Size of the buffer must be set before setting the data." );
+
+  const char* source = static_cast<const char*>( data );
+  std::copy( source, source + mBuffer.Size(), &mBuffer[0] );
+
+  SceneGraph::SetDataMessage( GetEventThreadServices(),
+                              *mSceneObject,
+                              new SceneGraph::PropertyBuffer::BufferType( mBuffer ) );
+}
+
+const SceneGraph::PropertyBuffer* PropertyBuffer::GetPropertyBufferSceneObject() const
+{
+  return mSceneObject;
+}
+
+void PropertyBuffer::SetFormat( Dali::Property::Map& format )
+{
+  DALI_ASSERT_ALWAYS( format.Count() && "Format cannot be empty." );
+
+  DALI_ASSERT_DEBUG( 0 == mFormat.Count() && "Format of property buffer can only be set once." );
+
+  mFormat = format;
+
+  FormatChanged();
+}
+
+unsigned int PropertyBuffer::GetDefaultPropertyCount() const
+{
+  return PROPERTY_BUFFER_IMPL.GetDefaultPropertyCount();
+}
+
+void PropertyBuffer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* PropertyBuffer::GetDefaultPropertyName(Property::Index index) const
+{
+  return PROPERTY_BUFFER_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index PropertyBuffer::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return PROPERTY_BUFFER_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool PropertyBuffer::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return PROPERTY_BUFFER_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool PropertyBuffer::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool PropertyBuffer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return PROPERTY_BUFFER_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type PropertyBuffer::GetDefaultPropertyType( Property::Index index ) const
+{
+  return PROPERTY_BUFFER_IMPL.GetDefaultPropertyType( index );
+}
+
+void PropertyBuffer::SetDefaultProperty( Property::Index index,
+                                         const Property::Value& propertyValue )
+{
+  switch( index )
+  {
+    case Dali::PropertyBuffer::Property::SIZE:
+    {
+      SetSize( propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+  }
+}
+
+void PropertyBuffer::SetSceneGraphProperty( Property::Index index,
+                                            const PropertyMetadata& entry,
+                                            const Property::Value& value )
+{
+  PROPERTY_BUFFER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+}
+
+Property::Value PropertyBuffer::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+
+  switch( index )
+  {
+    case Dali::PropertyBuffer::Property::SIZE:
+    {
+      value = static_cast<int>( GetSize() );
+      break;
+    }
+    case Dali::PropertyBuffer::Property::BUFFER_FORMAT:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+  }
+  return value;
+}
+
+const SceneGraph::PropertyOwner* PropertyBuffer::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* PropertyBuffer::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* PropertyBuffer::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
+  const SceneGraph::PropertyBase* property = NULL;
+
+  if( OnStage() )
+  {
+    property = PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty(
+      this,
+      &PropertyBuffer::FindAnimatableProperty,
+      &PropertyBuffer::FindCustomProperty,
+      index );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
+    }
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* PropertyBuffer::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  if( OnStage() )
+  {
+    const SceneGraph::PropertyBase* baseProperty =
+      PROPERTY_BUFFER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                            &PropertyBuffer::FindAnimatableProperty,
+                                                            &PropertyBuffer::FindCustomProperty,
+                                                            index );
+    property = static_cast<const PropertyInputImpl*>( baseProperty );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      if( index == Dali::PropertyBuffer::Property::SIZE )
+      {
+        // @todo MESH_REWORK
+        DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      }
+    }
+  }
+
+  return property;
+}
+
+int PropertyBuffer::GetPropertyComponentIndex( Property::Index index ) const
+{
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+bool PropertyBuffer::OnStage() const
+{
+  return mOnStage;
+}
+
+void PropertyBuffer::Connect()
+{
+  mOnStage = true;
+}
+
+void PropertyBuffer::Disconnect()
+{
+  mOnStage = false;
+}
+
+PropertyBuffer::~PropertyBuffer()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
+
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+PropertyBuffer::PropertyBuffer()
+: mSceneObject( NULL ),
+  mBufferFormat( NULL ),
+  mSize( 0 ),
+  mOnStage( false )
+{
+}
+
+void PropertyBuffer::Initialize()
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  mSceneObject = new SceneGraph::PropertyBuffer();
+  AddMessage( updateManager, updateManager.GetPropertyBufferOwner(), *mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
+}
+
+void PropertyBuffer::FormatChanged()
+{
+  size_t numComponents = mFormat.Count();
+
+  // Create the format
+  DALI_ASSERT_DEBUG( mBufferFormat == NULL && "PropertyFormat should not be set yet" );
+  Format* bufferFormat = new Format();
+  bufferFormat->components.resize( numComponents );
+
+  unsigned int currentAlignment = 0u;
+  unsigned int maxAlignmentRequired = 0u;
+
+  for( size_t i = 0u; i < numComponents; ++i )
+  {
+    StringValuePair component = mFormat.GetPair( i );
+
+    // Get the name
+    bufferFormat->components[i].name = component.first;
+
+    // enums are stored in the map as int
+    Property::Type type = Property::Type( component.second.Get<int>() );
+
+    // Get the size and alignment
+    unsigned int elementSize = GetPropertyImplementationSize( type );
+    unsigned int elementAlignment = GetPropertyImplementationAlignment( type );
+
+    // check if current alignment is compatible with new member
+    if( unsigned int offset = currentAlignment % elementAlignment )
+    {
+      // Not compatible, realign
+      currentAlignment = currentAlignment + elementSize - offset;
+    }
+
+    // write to the format
+    bufferFormat->components[i].size = elementSize;
+    bufferFormat->components[i].offset = currentAlignment;
+    bufferFormat->components[i].type = type;
+
+    // update offset
+    currentAlignment += elementSize;
+
+    // update max alignment requirement
+    if( elementAlignment > maxAlignmentRequired )
+    {
+      maxAlignmentRequired = elementAlignment;
+    }
+
+  }
+
+  // Check the alignment for the maxAlignment required to calculate the size of the format
+  if( maxAlignmentRequired != 0 )
+  {
+    if( unsigned int offset = currentAlignment % maxAlignmentRequired )
+    {
+      // Not compatible, realign
+      currentAlignment = currentAlignment + maxAlignmentRequired - offset;
+    }
+  }
+
+  // Set the format size
+  bufferFormat->size = currentAlignment;
+
+  mBufferFormat = bufferFormat;
+
+  SceneGraph::SetFormatMessage( GetEventThreadServices(),
+                                *mSceneObject,
+                                bufferFormat );
+
+  if( mSize )
+  {
+    SizeChanged();
+  }
+}
+
+void PropertyBuffer::SizeChanged()
+{
+  // Check if format and size have been set yet
+  if( mBufferFormat != NULL )
+  {
+    unsigned int bufferSize = mBufferFormat->size * mSize;
+    mBuffer.Resize( bufferSize );
+  }
+}
+
+unsigned int GetPropertyImplementationSize( Property::Type& propertyType )
+{
+  unsigned int size = 0u;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    {
+      DALI_ASSERT_ALWAYS( "No size for properties with no type, or dynamic sizes" );
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      size = sizeof( PropertyImplementationType< Property::BOOLEAN >::Type );
+      break;
+    }
+    case Property::INTEGER:
+    {
+      size = sizeof( PropertyImplementationType< Property::INTEGER >::Type );
+      break;
+    }
+    case Property::FLOAT:
+    {
+      size = sizeof( PropertyImplementationType< Property::FLOAT >::Type );
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR2 >::Type );
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR3 >::Type );
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      size = sizeof( PropertyImplementationType< Property::VECTOR4 >::Type );
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      size = sizeof( PropertyImplementationType< Property::MATRIX3 >::Type );
+      break;
+    }
+    case Property::MATRIX:
+    {
+      size = sizeof( PropertyImplementationType< Property::MATRIX >::Type );
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      size = sizeof( PropertyImplementationType< Property::RECTANGLE >::Type );
+      break;
+    }
+    case Property::ROTATION:
+    {
+      size = sizeof( PropertyImplementationType< Property::ROTATION >::Type );
+      break;
+    }
+  }
+
+  return size;
+}
+
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/common/property-buffer-impl.h b/dali/internal/event/common/property-buffer-impl.h
new file mode 100644 (file)
index 0000000..3c08271
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef DALI_INTERNAL_PROPERTY_BUFFER_H
+#define DALI_INTERNAL_PROPERTY_BUFFER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <utility> // std::pair
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/public-api/object/property-map.h> // Dali::Property::Map
+#include <dali/devel-api/object/property-buffer.h> // Dali::PropertyBuffer
+#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class PropertyBuffer;
+
+namespace PropertyBufferMetadata
+{
+struct Format;
+} // namespace PropertyBufferMetadata
+
+} // namespace SceneGraph
+
+class PropertyBuffer;
+typedef IntrusivePtr<PropertyBuffer> PropertyBufferPtr;
+
+/**
+ * PropertyBuffer is an object that contains an array of structures of values that
+ * can be accessed as properties.
+ */
+class PropertyBuffer : public Object, public Connectable
+{
+public:
+
+  /**
+   * @copydoc PropertBuffer::New()
+   */
+  static PropertyBufferPtr New();
+
+  /**
+   * @copydoc PropertBuffer::SetSize()
+   */
+  void SetSize( std::size_t size );
+
+  /**
+   * @copydoc PropertBuffer::GetSize()
+   */
+  std::size_t GetSize() const;
+
+  /**
+   * @copydoc PropertBuffer::SetData()
+   */
+  void SetData( const void* data );
+
+  /**
+   * @copydoc PropertBuffer::GetPropertyIndex()
+   */
+  Dali::Property::Index GetPropertyIndex( const std::string name, std::size_t index );
+
+  /**
+   * @brief Get the propertyBuffer scene object
+   *
+   * @return the propertyBuffer scene object
+   */
+  const SceneGraph::PropertyBuffer* GetPropertyBufferSceneObject() const;
+
+  /**
+   * @brief Set the format of the PropertyBuffer
+   *
+   * @pre Has not been set yet
+   *
+   * @param[in] format of the PropertyBuffer
+   */
+  void SetFormat( Dali::Property::Map& format );
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+public: // Functions from Connectable
+  /**
+   * @copydoc Dali::Internal::Connectable::OnStage()
+   */
+  virtual bool OnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Contnect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Disconnect()
+   */
+  virtual void Disconnect();
+
+protected:
+  /**
+   * @brief Destructor
+   */
+  ~PropertyBuffer();
+
+private: // implementation
+  /**
+   * @brief Default constructor
+   */
+  PropertyBuffer();
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize();
+
+  /**
+   * Update the buffer when the format changes
+   */
+  void FormatChanged();
+
+  /**
+   * Update the buffer when the size changes
+   */
+  void SizeChanged();
+
+private: // unimplemented methods
+  PropertyBuffer( const PropertyBuffer& );
+  PropertyBuffer& operator=( const PropertyBuffer& );
+
+private: // data
+  SceneGraph::PropertyBuffer* mSceneObject; ///< Update side object
+
+  Property::Map mFormat;  ///< Format of the property buffer
+  const SceneGraph::PropertyBufferMetadata::Format* mBufferFormat;  ///< Metadata for the format of the property buffer
+  unsigned int mSize; ///< Number of elements in the buffer
+  Dali::Vector< char > mBuffer; // Data of the property-buffer
+
+  bool mOnStage;  ///< Flag to know if the object is on stage
+};
+
+/**
+ * Get the implementation type from a Property::Type
+ */
+template<Property::Type type> struct PropertyImplementationType
+{
+  // typedef ... Type; not defined, only support types declared bellow
+};
+template<> struct PropertyImplementationType< Property::BOOLEAN > { typedef bool Type; };
+template<> struct PropertyImplementationType< Property::FLOAT > { typedef float Type; };
+template<> struct PropertyImplementationType< Property::INTEGER > { typedef int Type; };
+template<> struct PropertyImplementationType< Property::VECTOR2 > { typedef Vector2 Type; };
+template<> struct PropertyImplementationType< Property::VECTOR3 > { typedef Vector3 Type; };
+template<> struct PropertyImplementationType< Property::VECTOR4 > { typedef Vector4 Type; };
+template<> struct PropertyImplementationType< Property::MATRIX3 > { typedef Matrix3 Type; };
+template<> struct PropertyImplementationType< Property::MATRIX > { typedef Matrix Type; };
+template<> struct PropertyImplementationType< Property::RECTANGLE > { typedef Rect<int> Type; };
+template<> struct PropertyImplementationType< Property::ROTATION > { typedef Quaternion Type; };
+
+unsigned int GetPropertyImplementationSize( Property::Type& propertyType );
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::PropertyBuffer& GetImplementation(Dali::PropertyBuffer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "PropertyBuffer handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::PropertyBuffer&>(object);
+}
+
+inline const Internal::PropertyBuffer& GetImplementation(const Dali::PropertyBuffer& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "PropertyBuffer handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::PropertyBuffer&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_PROPERTY_BUFFER_H
diff --git a/dali/internal/event/common/property-conditions-impl.cpp b/dali/internal/event/common/property-conditions-impl.cpp
new file mode 100644 (file)
index 0000000..06557ae
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-conditions-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+PropertyCondition::PropertyCondition()
+: type(False)
+{
+
+}
+
+PropertyCondition::~PropertyCondition()
+{
+
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/property-conditions-impl.h b/dali/internal/event/common/property-conditions-impl.h
new file mode 100644 (file)
index 0000000..2a40d61
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_INTERNAL_PROPERTY_CONDITIONS_H__
+#define __DALI_INTERNAL_PROPERTY_CONDITIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/property-conditions.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property-value.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Structure to contain PropertyCondition internal data
+ */
+
+class PropertyCondition : public Dali::BaseObject
+{
+
+public:
+
+  /**
+   * Condition types.
+   */
+  enum Type
+  {
+    False,                ///< Result Always False
+    LessThan,             ///< Magnitude of type is less than float value (arg0).
+    GreaterThan,          ///< Magnitude of type is greater than float value (arg0).
+    Inside,               ///< Magnitude of type is within float values (arg0 & arg1).
+    Outside,              ///< Magnitude of type is outside float values (arg0 & arg1).
+    Step,                 ///< Value of type has crossed a step amount
+    VariableStep          ///< Similar to step, except user can define a list of steps from reference value
+  };
+
+  /**
+   * Constructor
+   */
+  PropertyCondition();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PropertyCondition();
+
+private:
+
+  // Not implemented
+  PropertyCondition(const PropertyCondition& rhs);
+
+  // Not implemented
+  PropertyCondition& operator=(const PropertyCondition& rhs);
+
+public:
+
+  Type type;                     ///< The condition Type.
+  Dali::Vector<float> arguments; ///< The condition Arguments.
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::PropertyCondition& GetImplementation(Dali::PropertyCondition& pub)
+{
+  DALI_ASSERT_ALWAYS( pub && "PropertyCondition handle is empty" );
+
+  BaseObject& handle = pub.GetBaseObject();
+
+  return static_cast<Internal::PropertyCondition&>(handle);
+}
+
+inline const Internal::PropertyCondition& GetImplementation(const Dali::PropertyCondition& pub)
+{
+  DALI_ASSERT_ALWAYS( pub && "PropertyCondition handle is empty" );
+
+  const BaseObject& handle = pub.GetBaseObject();
+
+  return static_cast<const Internal::PropertyCondition&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_CONDITIONS_H__
diff --git a/dali/internal/event/common/property-helper.h b/dali/internal/event/common/property-helper.h
new file mode 100644 (file)
index 0000000..65de3c8
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef __DALI_PROPERTY_HELPER_H__
+#define __DALI_PROPERTY_HELPER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+#include <dali/devel-api/scripting/scripting.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Structure for setting up default properties and their details.
+ */
+struct PropertyDetails
+{
+  const char* name;             ///< The name of the property.
+  Property::Type type;          ///< The property type.
+  bool writable:1;              ///< Whether the property is writable
+  bool animatable:1;            ///< Whether the property is animatable.
+  bool constraintInput:1;       ///< Whether the property can be used as an input to a constraint.
+#ifdef DEBUG_ENABLED
+  Property::Index enumIndex;    ///< Used to check the index is correct within a debug build.
+#endif
+};
+
+/**
+ * These macros are used to define a table of property details per Actor object.
+ * The index property is only compiled in for DEBUG_ENABLED builds and allows checking the table index VS the property enum index.
+ * DALI_PROPERTY_TABLE_END Forces a run-time check that will happen once.
+ */
+#define DALI_PROPERTY_TABLE_BEGIN const Internal::PropertyDetails DEFAULT_PROPERTY_DETAILS[] = {
+#ifdef DEBUG_ENABLED
+#define DALI_PROPERTY_TABLE_END( startIndex )   }; const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails ); \
+  struct PROPERTY_CHECK \
+  { \
+    PROPERTY_CHECK() \
+    { \
+      for( int i = 0; i < DEFAULT_PROPERTY_COUNT; i++ ) \
+      { \
+        if ( DEFAULT_PROPERTY_DETAILS[i].enumIndex != ( startIndex + i ) ) \
+        { \
+          DALI_LOG_ERROR( "Checking property failed: index:%d, enumIndex:%d == index+start:%d, (name:%s)\n", i, \
+                          DEFAULT_PROPERTY_DETAILS[i].enumIndex, (startIndex + i), DEFAULT_PROPERTY_DETAILS[i].name ); \
+          DALI_ASSERT_DEBUG( false && "Property enumeration mismatch" ); \
+        } \
+      } \
+    } \
+  }; \
+  static PROPERTY_CHECK PROPERTY_CHECK_INSTANCE;
+#else
+#define DALI_PROPERTY_TABLE_END( startIndex )   }; const int DEFAULT_PROPERTY_COUNT = sizeof( DEFAULT_PROPERTY_DETAILS ) / sizeof( Internal::PropertyDetails );
+#endif
+#ifdef DEBUG_ENABLED
+#define DALI_PROPERTY( text, type, writable, animatable, constraint, index ) { text, Dali::Property::type, writable, animatable, constraint, index },
+#else
+#define DALI_PROPERTY( text, type, writable, animatable, constraint, index ) { text, Dali::Property::type, writable, animatable, constraint },
+#endif
+
+/**
+ * Macros for creating enumeration to string tables.
+ * Example:
+ *
+ * DALI_ENUM_TO_STRING_TABLE_BEGIN( SizeMode )
+ * DALI_ENUM_TO_STRING( USE_OWN_SIZE )
+ * DALI_ENUM_TO_STRING( SIZE_EQUAL_TO_PARENT )
+ * DALI_ENUM_TO_STRING_TABLE_END( SizeMode )
+ *
+ * Creates:
+ * const Scripting::StringEnum< SizeMode > SizeModeTable[] = {
+ * { "USE_OWN_SIZE", USE_OWN_SIZE },
+ * { "SIZE_EQUAL_TO_PARENT", SIZE_EQUAL_TO_PARENT },
+ * }; const unsigned int SizeModeTableCount = sizeof( SizeModeTable ) / sizeof( SizeModeTable[0] );
+ */
+#define DALI_ENUM_TO_STRING_TABLE_BEGIN( t ) const Dali::Scripting::StringEnum t##Table[] = {
+#define DALI_ENUM_TO_STRING_TABLE_END( t )   }; const unsigned int t##TableCount = sizeof( t##Table ) / sizeof( t##Table[0] );
+#define DALI_ENUM_TO_STRING( s ) { #s, s },
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_HELPER_H__
diff --git a/dali/internal/event/common/property-input-impl.h b/dali/internal/event/common/property-input-impl.h
new file mode 100644 (file)
index 0000000..1778b54
--- /dev/null
@@ -0,0 +1,387 @@
+#ifndef __DALI_INTERNAL_PROPERTY_INPUT_IMPL_H__
+#define __DALI_INTERNAL_PROPERTY_INPUT_IMPL_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * These dummy values are used to handle PropertyInputImpl errors
+ */
+static const bool DUMMY_BOOLEAN_VALUE( false );
+static const float DUMMY_FLOAT_VALUE( 0.0f );
+static const int DUMMY_INTEGER_VALUE( 0 );
+static const Vector2 DUMMY_VECTOR2_VALUE( 0.0f, 0.0f );
+static const Vector3 DUMMY_VECTOR3_VALUE( 0.0f, 0.0f, 0.0f );
+static const Vector4 DUMMY_VECTOR4_VALUE( 0.0f, 0.0f, 0.0f, 0.0f );
+static const Matrix3 DUMMY_MATRIX3_VALUE;
+static const Matrix DUMMY_MATRIX_VALUE;
+static const Quaternion DUMMY_QUATERNION_VALUE( 1.0f, 0.0f, 0.0f, 0.0f );
+
+/**
+ * An abstract interface for receiving property values, and for querying whether
+ * a property value has changed i.e. whether a constraint needs to be reapplied.
+ */
+class PropertyInputImpl
+{
+public:
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyInputImpl()
+  {
+  }
+
+  /**
+   * Query the type of property input.
+   * @return The property type.
+   */
+  virtual Property::Type GetType() const = 0;
+
+  /**
+   * Query the input value (for a constraint) has been initialized.
+   * @return True if initialized, otherwise the constraint should be skipped.
+   */
+  virtual bool InputInitialized() const = 0;
+
+  /**
+   * Query the input value (for a constraint) has changed.
+   * @return True if the input value has changed.
+   */
+  virtual bool InputChanged() const = 0;
+
+  /**
+   * Retrieve a boolean value.
+   * @pre GetType() returns Property::BOOLEAN.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The boolean value.
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_BOOLEAN_VALUE;
+  }
+
+  /**
+   * Retrieve an integer value.
+   * @pre GetType() returns Property::INTEGER.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The integer value.
+   */
+  virtual const int& GetInteger( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_INTEGER_VALUE;
+  }
+
+  /**
+   * Retrieve a float value.
+   * @pre GetType() returns Property::FLOAT.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The float value.
+   */
+  virtual const float& GetFloat( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_FLOAT_VALUE;
+  }
+
+  /**
+   * Retrieve a Vector2 value.
+   * @pre GetType() returns Property::VECTOR2.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Vector2 value.
+   */
+  virtual const Vector2& GetVector2( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_VECTOR2_VALUE;
+  }
+
+  /**
+   * Retrieve a Vector3 value.
+   * @pre GetType() returns Property::VECTOR3.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Vector3 value.
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_VECTOR3_VALUE;
+  }
+
+  /**
+   * Retrieve a Vector4 value.
+   * @pre GetType() returns Property::VECTOR4.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Vector4 value.
+   */
+  virtual const Vector4& GetVector4( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_VECTOR4_VALUE;
+  }
+
+  /**
+   * Retrieve a Quaternion value.
+   * @pre GetType() returns Property::Quaternion.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Quaternion value.
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_QUATERNION_VALUE;
+  }
+
+  /**
+   * Retrieve a Matrix value.
+   * @pre GetType() returns Property::Matrix.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Matrix value.
+   */
+  virtual const Matrix3& GetMatrix3( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_MATRIX3_VALUE;
+  }
+
+  /**
+   * Retrieve a Matrix value.
+   * @pre GetType() returns Property::Matrix.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The Matrix value.
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_MATRIX_VALUE;
+  }
+
+  // Accessors for Constraint functions
+
+  /**
+   * Retrieve a boolean input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::BOOLEAN.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return The boolean value.
+   */
+  virtual const bool& GetConstraintInputBoolean( BufferIndex updateBufferIndex ) const
+  {
+    return GetBoolean( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve an integer input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::INTEGER.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return The integer value.
+   */
+  virtual const int& GetConstraintInputInteger( BufferIndex updateBufferIndex ) const
+  {
+    return GetInteger( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a float input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::FLOAT.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return The float value.
+   */
+  virtual const float& GetConstraintInputFloat( BufferIndex updateBufferIndex ) const
+  {
+    return GetFloat( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Vector2 input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::VECTOR2.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Vector2 value.
+   */
+  virtual const Vector2& GetConstraintInputVector2( BufferIndex updateBufferIndex ) const
+  {
+    return GetVector2( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Vector3 input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::VECTOR3.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Vector3 value.
+   */
+  virtual const Vector3& GetConstraintInputVector3( BufferIndex updateBufferIndex ) const
+  {
+    return GetVector3( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Vector4 input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::VECTOR4.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Vector4 value.
+   */
+  virtual const Vector4& GetConstraintInputVector4( BufferIndex updateBufferIndex ) const
+  {
+    return GetVector4( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Quaternion input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::Quaternion.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Quaternion value.
+   */
+  virtual const Quaternion& GetConstraintInputQuaternion( BufferIndex updateBufferIndex ) const
+  {
+    return GetQuaternion( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Matrix3 input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::Matrix.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Matrix value.
+   */
+  virtual const Matrix3& GetConstraintInputMatrix3( BufferIndex updateBufferIndex ) const
+  {
+    return GetMatrix3( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve a Matrix input for a constraint function.
+   * @note For inherited properties, this method should be overriden to return the value
+   * from the previous frame i.e. not from the current update buffer.
+   * @pre GetType() returns Property::Matrix.
+   * @param[in] updateBufferIndex The buffer to read from.
+   * @return The Matrix value.
+   */
+  virtual const Matrix& GetConstraintInputMatrix( BufferIndex updateBufferIndex ) const
+  {
+    return GetMatrix( updateBufferIndex );
+  }
+
+  /**
+   * Print the property value using a stream.
+   * @param[in] debugStream The output stream.
+   * @param[in] bufferIndex The buffer to read from.
+   * @todo Place this far-too-large-to-be-inlined function in a cpp and remove <iostream> header dependency from this file.
+   */
+  void DebugPrint( std::ostream& debugStream, BufferIndex bufferIndex ) const
+  {
+    switch ( GetType() )
+    {
+      case Property::BOOLEAN:
+      {
+        debugStream << GetBoolean( bufferIndex );
+        break;
+      }
+
+      case Property::INTEGER:
+      {
+        debugStream << GetInteger( bufferIndex );
+        break;
+      }
+
+      case Property::FLOAT:
+      {
+        debugStream << GetFloat( bufferIndex );
+        break;
+      }
+
+      case Property::VECTOR2:
+      {
+        debugStream << GetVector2( bufferIndex );
+        break;
+      }
+
+      case Property::VECTOR3:
+      {
+        debugStream << GetVector3( bufferIndex );
+        break;
+      }
+
+      case Property::VECTOR4:
+      {
+        debugStream << GetVector4( bufferIndex );
+        break;
+      }
+
+      case Property::ROTATION:
+      {
+        debugStream << GetQuaternion( bufferIndex );
+        break;
+      }
+
+      case Property::MATRIX:
+      {
+        debugStream << GetMatrix( bufferIndex );
+        break;
+      }
+
+      case Property::MATRIX3:
+      {
+        debugStream << GetMatrix3( bufferIndex );
+        break;
+      }
+
+      default:
+        break; // print nothing
+    }
+  }
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_INPUT_IMPL_H__
diff --git a/dali/internal/event/common/property-metadata.h b/dali/internal/event/common/property-metadata.h
new file mode 100644 (file)
index 0000000..61b3c82
--- /dev/null
@@ -0,0 +1,260 @@
+#ifndef __DALI_INTERNAL_PROPERTY_METADATA_H__
+#define __DALI_INTERNAL_PROPERTY_METADATA_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+#include <utility>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class PropertyBase;
+}
+
+/**
+ * An entry in a property metadata lookup.
+ * The type field should be queried, before accessing the scene-graph property:
+ *
+ * @code
+ * void Example(PropertyEntry entry)
+ * {
+ *   if (entry.type == Property::VECTOR3)
+ *   {
+ *     SceneGraph::AnimatableProperty<Vector3>* property = dynamic_cast< SceneGraph::AnimatableProperty<Vector3>* >( entry.property );
+ *     ...
+ *   }
+ * @endcode
+ *
+ */
+class PropertyMetadata
+{
+public:
+
+  /**
+   * Constructor for an uninitalized property metadata
+   */
+  PropertyMetadata()
+  : type(Property::NONE),
+    value(),
+    componentIndex(Property::INVALID_COMPONENT_INDEX),
+    mProperty(NULL)
+  {
+  }
+
+  /**
+   * Constructor for property metadata
+   * @param [in] newProperty A pointer to the property metadata.
+   */
+  PropertyMetadata(const SceneGraph::PropertyBase* newProperty)
+  : type(Property::NONE),
+    value(), // value is held by newProperty
+    componentIndex(Property::INVALID_COMPONENT_INDEX),
+    mProperty(newProperty)
+  {
+    DALI_ASSERT_DEBUG(mProperty && "Uninitialized scenegraph property") ;
+  }
+
+  /**
+   * Constructor for property metadata
+   * @param [in] newValue The value of the scene-graph owned property.
+   */
+  PropertyMetadata(Property::Value newValue)
+  : type(newValue.GetType()),
+    value(newValue),
+    componentIndex(Property::INVALID_COMPONENT_INDEX),
+    mProperty(NULL)
+  {
+  }
+
+  /**
+   * Destructor for property metadata
+   */
+  virtual ~PropertyMetadata()
+  {
+  }
+
+  /**
+   * @return true if the property is animatable (i.e. if its a scene graph property)
+   */
+  bool IsAnimatable(void) const
+  {
+    return NULL != mProperty;
+  }
+
+  /**
+   * @return true if the property can be written to
+   */
+  virtual bool IsWritable(void) const = 0;
+
+  /**
+   * @return the scene graph property
+   */
+  const SceneGraph::PropertyBase* GetSceneGraphProperty() const
+  {
+    DALI_ASSERT_DEBUG(mProperty && "Accessing uninitialized SceneGraph property") ;
+    return mProperty;
+  }
+
+  Property::Type type;    ///< The type of the property
+  Property::Value value;  ///< The property value for a non animatable and custom property
+  int componentIndex;     ///< The index of the property component
+
+protected:
+
+  // Not implemented
+  PropertyMetadata( const PropertyMetadata& );
+  PropertyMetadata& operator=( const PropertyMetadata& );
+
+  const SceneGraph::PropertyBase* mProperty; ///< A pointer to a scene-graph property; should not be modified from actor-thread.
+};
+
+
+/**
+ * An entry in an animatable property metadata lookup.
+ * The type field should be queried, before accessing the animatable property:
+ */
+class AnimatablePropertyMetadata : public PropertyMetadata
+{
+public:
+
+  /**
+   * Constructor for metadata of animatable property
+   * @param [in] newIndex The index of the animatable property.
+   * @param [in] newType The type ID of the animatable property.
+   * @param [in] newProperty A pointer to the scene-graph owned property.
+   */
+  AnimatablePropertyMetadata( Property::Index newIndex,
+                        int newComponentIndex,
+                        Property::Type newType,
+                        const SceneGraph::PropertyBase* newProperty )
+  : index(newIndex)
+  {
+    componentIndex = newComponentIndex;
+    type = newType;
+    mProperty = newProperty;
+    DALI_ASSERT_DEBUG(mProperty && "Uninitialized scenegraph property") ;
+  }
+
+  /**
+   * Constructor for metadata of animatable property
+   * @param [in] newIndex The index of the animatable property.
+   * @param [in] newValue The value of the scene-graph owned property.
+   */
+  AnimatablePropertyMetadata( Property::Index newIndex,
+                        int newComponentIndex,
+                        Property::Value newValue )
+  : index(newIndex)
+  {
+    componentIndex = newComponentIndex;
+    type = newValue.GetType();
+    value = newValue;
+  }
+
+  /**
+   * @return true if the property can be written to
+   */
+  virtual bool IsWritable(void) const
+  {
+    return true ;
+  }
+
+  Property::Index index;       ///< The index of the property
+
+private:
+
+  // Not implemented
+  AnimatablePropertyMetadata();
+  AnimatablePropertyMetadata( const AnimatablePropertyMetadata& );
+  AnimatablePropertyMetadata& operator=( const AnimatablePropertyMetadata& );
+};
+
+class CustomPropertyMetadata : public PropertyMetadata
+{
+public:
+
+  /**
+   * Constructor for metadata of scene graph based properties
+   * @param [in] newName The name of the custom property.
+   * @param [in] newType The type ID of the custom property.
+   * @param [in] newProperty A pointer to the scene-graph owned property.
+   */
+  CustomPropertyMetadata( const std::string& newName,
+                          Property::Type newType,
+                          const SceneGraph::PropertyBase* newProperty)
+  : name(newName),
+    mAccessMode(Property::ANIMATABLE)
+  {
+    type = newType;
+    mProperty = newProperty;
+    DALI_ASSERT_DEBUG(mProperty && "Uninitialized scenegraph property") ;
+  }
+
+  /**
+   * Constructor for metadata of event side only properties
+   * @param [in] newName The name of the custom property.
+   * @param [in] newValue The value of the custom property.
+   * @param [in] accessMode The access mode of the custom property (writable, animatable etc).
+   */
+  CustomPropertyMetadata( const std::string& newName,
+                          Property::Value newValue,
+                          Property::AccessMode accessMode )
+  : name(newName),
+    mAccessMode(accessMode)
+  {
+    type = newValue.GetType();
+    value = newValue;
+    DALI_ASSERT_DEBUG(accessMode != Property::ANIMATABLE && "Animatable must have scenegraph property") ;
+  }
+
+  /**
+   * @return true if the property can be written to
+   */
+  virtual bool IsWritable(void) const
+  {
+    return (mAccessMode == Property::ANIMATABLE) || (mAccessMode == Property::READ_WRITE) ;
+  }
+
+  std::string name;       ///< The name of the property
+
+private:
+
+  // Not implemented
+  CustomPropertyMetadata();
+  CustomPropertyMetadata( const CustomPropertyMetadata& );
+  CustomPropertyMetadata& operator=( const CustomPropertyMetadata& );
+
+private:
+  Property::AccessMode mAccessMode; ///< The mode of the property
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_METADATA_H__
diff --git a/dali/internal/event/common/property-notification-impl.cpp b/dali/internal/event/common/property-notification-impl.cpp
new file mode 100644 (file)
index 0000000..14536a1
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/property-notification-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/property-notification-manager.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+
+using Dali::Internal::SceneGraph::UpdateManager;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+PropertyNotificationPtr PropertyNotification::New(Property& target,
+                                                  int componentIndex,
+                                                  const Dali::PropertyCondition& condition)
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+
+  UpdateManager& updateManager = tls.GetUpdateManager();
+
+  StagePtr stage = Stage::GetCurrent();
+  if( stage )
+  {
+    PropertyNotificationManager& propertyNotificationManager = stage->GetPropertyNotificationManager();
+    PropertyNotificationPtr propertyNotification = new PropertyNotification(updateManager,
+                                                                            propertyNotificationManager,
+                                                                            target,
+                                                                            componentIndex,
+                                                                            condition);
+    return propertyNotification;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+PropertyNotification::PropertyNotification( UpdateManager& updateManager,
+                                            PropertyNotificationManager& propertyNotificationManager,
+                                            Property& target,
+                                            int componentIndex,
+                                            const Dali::PropertyCondition& condition )
+: mUpdateManager( updateManager ),
+  mPropertyNotification( NULL ),
+  mPropertyNotificationManager( propertyNotificationManager ),
+  mObjectPropertyIndex( target.propertyIndex ),
+  mPropertyType( Property::NONE ),
+  mComponentIndex( componentIndex ),
+  mCondition( condition ),
+  mNotifyMode( Dali::PropertyNotification::NotifyOnTrue ),
+  mNotifyResult( false )
+{
+  const Internal::PropertyCondition& conditionImpl = GetImplementation( condition );
+
+  Dali::Vector<float>::SizeType count = conditionImpl.arguments.Count();
+  for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
+  {
+    mRawConditionArgs.PushBack( conditionImpl.arguments[ index ] );
+  }
+
+  // Observe target object and create/destroy notification scene object accordingly.
+  mObject = dynamic_cast<Object*>( &GetImplementation(target.object) );
+  if ( mObject )
+  {
+    mPropertyType = mObject->GetPropertyType(mObjectPropertyIndex);
+
+    int internalComponentIndex = mObject->GetPropertyComponentIndex(mObjectPropertyIndex);
+    if( internalComponentIndex != Property::INVALID_COMPONENT_INDEX )
+    {
+      // override the one passed in
+      mComponentIndex = internalComponentIndex;
+    }
+    if(mComponentIndex != Property::INVALID_COMPONENT_INDEX)
+    {
+      Property::Type type = mObject->GetPropertyType(mObjectPropertyIndex);
+      if( type == Property::VECTOR2
+          || type == Property::VECTOR3
+          || type == Property::VECTOR4 )
+      {
+        mPropertyType = Property::FLOAT;
+      }
+    }
+
+    // Check if target scene-object already present, and if so create our notification
+    // scene-object
+    const SceneGraph::PropertyOwner* object = mObject->GetSceneObject();
+    if (object)
+    {
+      CreateSceneObject();
+    }
+  }
+
+  // Connect to the property notification manager
+  mPropertyNotificationManager.PropertyNotificationCreated( *this );
+}
+
+PropertyNotification::~PropertyNotification()
+{
+  Disable();
+
+  // Guard to disallow use of PropertyNotificationManager after Core has been destroyed
+  if ( Stage::IsInstalled() )
+  {
+    // Disconnect from the property notification manager
+    mPropertyNotificationManager.PropertyNotificationDestroyed( *this );
+  }
+}
+
+Dali::PropertyNotifySignalType& PropertyNotification::NotifySignal()
+{
+  return mNotifySignal;
+}
+
+void PropertyNotification::EmitSignalNotify()
+{
+  Dali::PropertyNotification source(this);
+
+  mNotifySignal.Emit( source );
+}
+
+void PropertyNotification::Enable()
+{
+  CreateSceneObject();
+}
+
+void PropertyNotification::Disable()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if ( Stage::IsInstalled() )
+  {
+    // Stop scene-graph from monitoring the target's properties.
+    DestroySceneObject();
+  }
+}
+
+void PropertyNotification::SetNotifyResult( bool result )
+{
+  mNotifyResult = result;
+}
+
+const Dali::PropertyCondition& PropertyNotification::GetCondition() const
+{
+  return mCondition;
+}
+
+Dali::Handle PropertyNotification::GetTarget() const
+{
+  Dali::Handle handle(mObject);
+
+  return handle;
+}
+
+Property::Index PropertyNotification::GetTargetProperty() const
+{
+  return mObjectPropertyIndex;
+}
+
+void PropertyNotification::SetNotifyMode( NotifyMode mode )
+{
+  mNotifyMode = mode;
+  if( mPropertyNotification )
+  {
+    PropertyNotificationSetNotifyModeMessage( mUpdateManager, mPropertyNotification, mode );
+  }
+}
+
+PropertyNotification::NotifyMode PropertyNotification::GetNotifyMode()
+{
+  return mNotifyMode;
+}
+
+bool PropertyNotification::GetNotifyResult() const
+{
+  return mNotifyResult;
+}
+
+bool PropertyNotification::CompareSceneObject( const SceneGraph::PropertyNotification* sceneObject )
+{
+  return sceneObject && sceneObject == mPropertyNotification;
+}
+
+void PropertyNotification::CreateSceneObject()
+{
+  // this method can be called from constructor and on stage connection
+  if( !mPropertyNotification )
+  {
+    // Create a new PropertyNotification, temporarily owned
+    SceneGraph::PropertyNotification* propertyNotification = SceneGraph::PropertyNotification::New( *mObject,
+                                                                                                    mObjectPropertyIndex,
+                                                                                                    mPropertyType,
+                                                                                                    mComponentIndex,
+                                                                                                    GetImplementation(mCondition).type,
+                                                                                                    mRawConditionArgs,
+                                                                                                    mNotifyMode );
+    // Keep a const pointer to the PropertyNotification.
+    mPropertyNotification = propertyNotification;
+
+    // Transfer scene object ownership to the update manager through a message
+    AddPropertyNotificationMessage( mUpdateManager, propertyNotification );
+  }
+}
+
+void PropertyNotification::DestroySceneObject()
+{
+  if ( mPropertyNotification != NULL )
+  {
+    // Remove PropertyNotification using a message to the update manager
+    RemovePropertyNotificationMessage( mUpdateManager, *mPropertyNotification );
+    mPropertyNotification = NULL;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/property-notification-impl.h b/dali/internal/event/common/property-notification-impl.h
new file mode 100644 (file)
index 0000000..03e2d58
--- /dev/null
@@ -0,0 +1,225 @@
+#ifndef __DALI_INTERNAL_PROPERTY_NOTIFICATION_H__
+#define __DALI_INTERNAL_PROPERTY_NOTIFICATION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/object/property-notification.h>
+#include <dali/internal/event/common/property-conditions-impl.h>
+
+namespace Dali
+{
+
+class PropertyCondition;
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class PropertyNotification;
+class UpdateManager;
+}
+
+class Actor;
+class PropertyNotification;
+class Object;
+class PropertyNotificationManager;
+
+typedef IntrusivePtr<PropertyNotification> PropertyNotificationPtr;
+
+/**
+ * PropertyNotification is a proxy for a SceneGraph::PropertyNotification object.
+ * The UpdateManager owns the PropertyNotification object, but the lifetime of the PropertyNotification is
+ * indirectly controlled by the PropertyNotification.
+ */
+class PropertyNotification : public BaseObject
+{
+public:
+
+  typedef Dali::PropertyNotification::NotifyMode NotifyMode;
+  typedef PropertyCondition::Type ConditionType;
+
+  /**
+   * RawArgumentContainer provides fast direct access to arguments for condition evaluation.
+   */
+  typedef Dali::Vector<float> RawArgumentContainer;
+
+  /**
+   * Create a new PropertyNotification object.
+   * @param[in] target The target object to inspect
+   * @param[in] componentIndex Index to the component of a complex property such as a Vector
+   * @param[in] condition The condition for this notification.
+   * @return A smart-pointer to the newly allocated PropertyNotification.
+   */
+  static PropertyNotificationPtr New(Property& target,
+                                     int componentIndex,
+                                     const Dali::PropertyCondition& condition);
+
+public:
+
+  /**
+   * @copydoc Dali::PropertyNotification::NotifySignal()
+   */
+  Dali::PropertyNotifySignalType& NotifySignal();
+
+  /**
+   * Emit the Notify signal
+   */
+  void EmitSignalNotify();
+
+  /**
+   * Enables PropertyNotification
+   */
+  void Enable();
+
+  /**
+   * Disables PropertyNotification
+   */
+  void Disable();
+
+  /**
+   * Sets the result from the property condition test for use by applications that connect to the notification signal
+   *
+   * @param[in] result The result of the property condition test
+   */
+  void SetNotifyResult(bool result);
+
+  /**
+   * @copydoc Dali::PropertyNotification::GetCondition
+   */
+  const Dali::PropertyCondition& GetCondition() const;
+
+  /**
+   * @copydoc Dali::PropertyNotification::GetTarget
+   */
+  Dali::Handle GetTarget() const;
+
+  /**
+   * @copydoc Dali::PropertyNotification::GetTargetProperty
+   */
+  Property::Index GetTargetProperty() const;
+
+  /**
+   * @copydoc Dali::PropertyNotification::SetNotifyMode
+   */
+  void SetNotifyMode( NotifyMode mode );
+
+  /**
+   * @copydoc Dali::PropertyNotification::GetNotifyMode
+   */
+  NotifyMode GetNotifyMode();
+
+  /**
+   * @copydoc Dali::PropertyNotification::GetNotifyResult
+   */
+  bool GetNotifyResult() const;
+
+  /**
+   * Compare the passed sceneObject to the one created by this instance
+   * @param[in] sceneObject The SceneGraph::PropertyNotification pointer to compare
+   * @return true if sceneObject is the same as the one created by this instance
+   */
+   bool CompareSceneObject( const SceneGraph::PropertyNotification* sceneObject );
+
+protected:
+
+  /**
+   * Construct a new PropertyNotification.
+   * @param[in] updateManager The UpdateManager associated with this PropertyNotification.
+   * @param[in] propertyNotificationManager The property notification manager object.
+   * @param[in] target The target property.
+   * @param[in] componentIndex Index to the component of a complex property such as a Vector
+   * @param[in] condition The condition for this notification.
+   */
+  PropertyNotification(SceneGraph::UpdateManager& updateManager,
+                       PropertyNotificationManager& propertyNotificationManager,
+                       Property& target,
+                       int componentIndex,
+                       const Dali::PropertyCondition& condition);
+
+  /**
+   * Helper to create a scene-graph PropertyNotification
+   */
+  void CreateSceneObject();
+
+  /**
+   * Helper to destroy a scene-graph PropertyNotification
+   */
+  void DestroySceneObject();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~PropertyNotification();
+
+private:
+
+  // Undefined
+  PropertyNotification(const PropertyNotification&);
+
+  // Undefined
+  PropertyNotification& operator=(const PropertyNotification& rhs);
+
+protected:
+
+  SceneGraph::UpdateManager& mUpdateManager;
+  const SceneGraph::PropertyNotification* mPropertyNotification;
+
+  Dali::PropertyNotifySignalType mNotifySignal;
+
+private:
+
+  PropertyNotificationManager& mPropertyNotificationManager;  ///< Reference to the property notification manager
+  Object*                      mObject;                       ///< Target object, not owned by PropertyNotification.
+  Property::Index              mObjectPropertyIndex;          ///< Target object's property index of interest.
+  Property::Type               mPropertyType;                 ///< The type of property to evaluate
+  int                          mComponentIndex;               ///< Index to a specific component of a complex property such as a Vector
+  Dali::PropertyCondition      mCondition;                    ///< The PropertyCondition handle.
+  RawArgumentContainer         mRawConditionArgs;             ///< The Raw Condition args. (float type)
+  NotifyMode                   mNotifyMode;                   ///< The current notification mode.
+  bool                         mNotifyResult;                 ///< The result of the last condition check that caused a signal emit
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::PropertyNotification& GetImplementation(Dali::PropertyNotification& pub)
+{
+  DALI_ASSERT_ALWAYS( pub && "PropertyNotification handle is empty" );
+
+  BaseObject& handle = pub.GetBaseObject();
+
+  return static_cast<Internal::PropertyNotification&>(handle);
+}
+
+inline const Internal::PropertyNotification& GetImplementation(const Dali::PropertyNotification& pub)
+{
+  DALI_ASSERT_ALWAYS( pub && "PropertyNotification handle is empty" );
+
+  const BaseObject& handle = pub.GetBaseObject();
+
+  return static_cast<const Internal::PropertyNotification&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_NOTIFICATION_H__
diff --git a/dali/internal/event/common/property-notification-manager.cpp b/dali/internal/event/common/property-notification-manager.cpp
new file mode 100644 (file)
index 0000000..54980c8
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/property-notification-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+PropertyNotificationManager* PropertyNotificationManager::New()
+{
+  return new PropertyNotificationManager;
+}
+
+PropertyNotificationManager::~PropertyNotificationManager()
+{
+}
+
+void PropertyNotificationManager::PropertyNotificationCreated( PropertyNotification& propertyNotification )
+{
+  mPropertyNotifications.PushBack( &propertyNotification );
+}
+
+void PropertyNotificationManager::PropertyNotificationDestroyed( PropertyNotification& propertyNotification )
+{
+  Dali::Vector< PropertyNotification* >::Iterator iter = std::find( mPropertyNotifications.Begin(), mPropertyNotifications.End(), &propertyNotification );
+  DALI_ASSERT_ALWAYS( iter != mPropertyNotifications.End() && "PropertyNotification not found" );
+
+  mPropertyNotifications.Remove( iter );
+}
+
+void PropertyNotificationManager::NotifyProperty( SceneGraph::PropertyNotification* propertyNotification, bool validity )
+{
+  Dali::Vector< PropertyNotification* >::Iterator iter = mPropertyNotifications.Begin();
+  const Dali::Vector< PropertyNotification* >::Iterator endIter = mPropertyNotifications.End();
+
+  // walk the collection of PropertyNotifications
+  for( ; iter != endIter; ++iter )
+  {
+    // found one with the matching SceneGraph::PropertyNotification?
+    if( (*iter)->CompareSceneObject( propertyNotification ) )
+    {
+      // allow application to access the value that triggered this emit incase of NotifyOnChanged mode
+      (*iter)->SetNotifyResult(validity);
+      // yes..emit signal
+      (*iter)->EmitSignalNotify();
+      break;
+    }
+  }
+}
+
+PropertyNotificationManager::PropertyNotificationManager()
+{
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/common/property-notification-manager.h b/dali/internal/event/common/property-notification-manager.h
new file mode 100644 (file)
index 0000000..a5eef94
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef __DALI_INTERNAL_PROPERTY_NOTIFICATION_MANAGER_H__
+#define __DALI_INTERNAL_PROPERTY_NOTIFICATION_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/event/common/property-notifier.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class PropertyNotification;
+
+/**
+ * PropertyNotificationManager issues notifications to applications
+ * a condition of a property being met.
+ * It also monitors the lifetime of PropertyNotification objects and will
+ * only emit signals for PropertyNotification objects which are still valid.
+ */
+class PropertyNotificationManager : public PropertyNotifier
+{
+public:
+
+  /**
+   * Create an PropertyNotificationManager.
+   * @return A newly allocated object.
+   */
+  static PropertyNotificationManager* New();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyNotificationManager();
+
+  /**
+   * Called when a PropertyNotification is constructed.
+   */
+  void PropertyNotificationCreated( PropertyNotification& propertyNotification );
+
+  /**
+   * Called when a PropertyNotification is destroyed.
+   */
+  void PropertyNotificationDestroyed( PropertyNotification& propertyNotification );
+
+private: // private virtual overrides
+
+  /**
+   * @copydoc PropertyNotifier::NotifyProperty
+   */
+  virtual void NotifyProperty( SceneGraph::PropertyNotification* propertyNotification, bool validity );
+
+private:
+
+  /**
+   * Default constructor.
+   */
+  PropertyNotificationManager();
+
+  // Undefined
+  PropertyNotificationManager(const PropertyNotificationManager&);
+
+  // Undefined
+  PropertyNotificationManager& operator=(const PropertyNotificationManager& rhs);
+
+private:
+
+  Dali::Vector< PropertyNotification* > mPropertyNotifications; ///< All existing PropertyNotifications (not owned)
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_NOTIFICATION_MANAGER_H__
+
diff --git a/dali/internal/event/common/property-notifier.h b/dali/internal/event/common/property-notifier.h
new file mode 100644 (file)
index 0000000..76859d9
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef __DALI_INTERNAL_PROPERTY_NOTIFIER_H__
+#define __DALI_INTERNAL_PROPERTY_NOTIFIER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class PropertyNotification;
+
+} //namespace SceneGraph
+
+/**
+ * Interface used by the update-thread to trigger property changed notification signals.
+ */
+class PropertyNotifier
+{
+public:
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyNotifier()
+  {
+  }
+
+  /**
+   * Provide notification signals for a changed property.
+   * This method should be called in the event-thread; the update-thread must use PropertyChangedMessage.
+   * @param[in] propertyNotification A pointer to the SceneGraph::PropertyNotification that has been mnodified.
+   * @param[in] validity Passes in whether the notification was triggered by a true or false condition result
+   */
+  virtual void NotifyProperty( SceneGraph::PropertyNotification* propertyNotification, bool validity ) = 0;
+};
+
+/**
+ * Notification message for when a property has been modified
+ * @param[in] notifier This will provide the notification signal.
+ */
+inline MessageBase* PropertyChangedMessage( PropertyNotifier& notifier, SceneGraph::PropertyNotification* propertyNotification, bool validity )
+{
+  return new MessageValue2< PropertyNotifier, SceneGraph::PropertyNotification*, bool >( &notifier,
+                                                                                   &PropertyNotifier::NotifyProperty,
+                                                                                   propertyNotification, validity);
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROPERTY_NOTIFIER_H__
diff --git a/dali/internal/event/common/stage-def.h b/dali/internal/event/common/stage-def.h
new file mode 100644 (file)
index 0000000..7df5cc1
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef __DALI_INTERNAL_STAGE_DEF_H__
+#define __DALI_INTERNAL_STAGE_DEF H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/intrusive-ptr.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Stage;
+
+typedef Stage* StagePtr;
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_STAGE_DEF H__
diff --git a/dali/internal/event/common/stage-impl.cpp b/dali/internal/event/common/stage-impl.cpp
new file mode 100644 (file)
index 0000000..5678841
--- /dev/null
@@ -0,0 +1,635 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/stage-impl.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+#include <cmath>
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/system-overlay.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/actors/layer-list.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
+#include <dali/internal/event/common/system-overlay-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/property-notification-manager.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/event/common/object-registry-impl.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+
+using Dali::Internal::SceneGraph::Node;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+const float DEFAULT_STEREO_BASE( 65.0f );
+
+// Signals
+
+const char* const SIGNAL_KEY_EVENT =                 "key-event";
+const char* const SIGNAL_EVENT_PROCESSING_FINISHED = "event-processing-finished";
+const char* const SIGNAL_TOUCHED =                   "touched";
+const char* const SIGNAL_WHEEL_EVENT =               "wheel-event";
+const char* const SIGNAL_CONTEXT_LOST =              "context-lost";
+const char* const SIGNAL_CONTEXT_REGAINED =          "context-regained";
+const char* const SIGNAL_SCENE_CREATED =             "scene-created";
+
+TypeRegistration mType( typeid(Dali::Stage), typeid(Dali::BaseHandle), NULL );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_KEY_EVENT,                 &Stage::DoConnectSignal );
+SignalConnectorType signalConnector2( mType, SIGNAL_EVENT_PROCESSING_FINISHED, &Stage::DoConnectSignal );
+SignalConnectorType signalConnector3( mType, SIGNAL_TOUCHED,                   &Stage::DoConnectSignal );
+SignalConnectorType signalConnector4( mType, SIGNAL_WHEEL_EVENT,               &Stage::DoConnectSignal );
+SignalConnectorType signalConnector5( mType, SIGNAL_CONTEXT_LOST,              &Stage::DoConnectSignal );
+SignalConnectorType signalConnector6( mType, SIGNAL_CONTEXT_REGAINED,          &Stage::DoConnectSignal );
+SignalConnectorType signalConnector7( mType, SIGNAL_SCENE_CREATED,             &Stage::DoConnectSignal );
+
+} // unnamed namespace
+
+StagePtr Stage::New( AnimationPlaylist& playlist,
+                     PropertyNotificationManager& propertyNotificationManager,
+                     SceneGraph::UpdateManager& updateManager,
+                     NotificationManager& notificationManager )
+{
+  return StagePtr( new Stage( playlist, propertyNotificationManager, updateManager, notificationManager ) );
+}
+
+void Stage::Initialize()
+{
+  mObjectRegistry = ObjectRegistry::New();
+
+  // Create the ordered list of layers
+  mLayerList = LayerList::New( mUpdateManager, false/*not system-level*/ );
+
+  // The stage owns the default layer
+  mRootLayer = Layer::NewRoot( *mLayerList, mUpdateManager, false/*not system-level*/ );
+  mRootLayer->SetName("RootLayer");
+  // The root layer needs to have a fixed resize policy (as opposed to the default USE_NATURAL_SIZE).
+  // This stops actors parented to the stage having their relayout requests propagating
+  // up to the root layer, and down through other children unnecessarily.
+  mRootLayer->SetResizePolicy( ResizePolicy::FIXED, Dimension::ALL_DIMENSIONS );
+
+  // Create the default camera actor first; this is needed by the RenderTaskList
+  CreateDefaultCameraActor();
+
+  // Create the list of render-tasks
+  mRenderTaskList = RenderTaskList::New( *this, *this, false/*not system-level*/ );
+
+  // Create the default render-task
+  Dali::RenderTask defaultRenderTask = mRenderTaskList->CreateTask();
+}
+
+void Stage::Uninitialize()
+{
+  // Remove actors added to SystemOverlay
+  delete mSystemOverlay;
+  mSystemOverlay = NULL;
+
+  if( mDefaultCamera )
+  {
+    // its enough to release the handle so the object is released
+    // don't need to remove it from root actor as root actor will delete the object
+    mDefaultCamera.Reset();
+  }
+
+  if( mRootLayer )
+  {
+    // we are closing down so just delete the root, no point emit disconnect
+    // signals or send messages to update
+    mRootLayer.Reset();
+  }
+}
+
+StagePtr Stage::GetCurrent()
+{
+  StagePtr stage( NULL );
+  // no checking in this version
+  ThreadLocalStorage* tls = ThreadLocalStorage::GetInternal();
+  if( tls )
+  {
+    stage = tls->GetCurrentStage();
+  }
+  return stage;
+}
+
+bool Stage::IsInstalled()
+{
+  return ThreadLocalStorage::Created();
+}
+
+ObjectRegistry& Stage::GetObjectRegistry()
+{
+  return *mObjectRegistry;
+}
+
+void Stage::RegisterObject( Dali::BaseObject* object )
+{
+  mObjectRegistry->RegisterObject( object );
+}
+
+void Stage::UnregisterObject( Dali::BaseObject* object )
+{
+  mObjectRegistry->UnregisterObject( object );
+}
+
+Layer& Stage::GetRootActor()
+{
+  return *mRootLayer;
+}
+
+AnimationPlaylist& Stage::GetAnimationPlaylist()
+{
+  return mAnimationPlaylist;
+}
+
+PropertyNotificationManager& Stage::GetPropertyNotificationManager()
+{
+  return mPropertyNotificationManager;
+}
+
+void Stage::Add( Actor& actor )
+{
+  mRootLayer->Add( actor );
+}
+
+void Stage::Remove( Actor& actor )
+{
+  mRootLayer->Remove( actor );
+}
+
+void Stage::SetSize(float width, float height)
+{
+  // Internally we want to report the actual size of the stage.
+  mSize.width  = width;
+  mSize.height = height;
+
+  // Calculates the aspect ratio, near and far clipping planes, field of view and camera Z position.
+  mDefaultCamera->SetPerspectiveProjection( mSize );
+
+  // The depth of the stage gets set to the maximun of these values
+  mRootLayer->SetSize( mSize );
+
+  // Repeat for SystemOverlay actors
+  if( mSystemOverlay )
+  {
+    mSystemOverlay->GetImpl()->SetSize( mSize.width, mSize.height );
+  }
+
+  SetDefaultSurfaceRectMessage( mUpdateManager, Rect<int>( 0, 0, width, height ) );
+}
+
+Vector2 Stage::GetSize() const
+{
+  return mSize;
+}
+
+RenderTaskList& Stage::GetRenderTaskList() const
+{
+  return *mRenderTaskList;
+}
+
+void Stage::CreateDefaultCameraActor()
+{
+  // The default camera attributes and position is such that
+  // children of the default layer, can be positioned at (0,0) and
+  // be at the top-left of the viewport.
+  mDefaultCamera = CameraActor::New( Size::ZERO );
+  mDefaultCamera->SetParentOrigin(ParentOrigin::CENTER);
+  Add(*(mDefaultCamera.Get()));
+}
+
+Actor& Stage::GetDefaultRootActor()
+{
+  return *mRootLayer;
+}
+
+CameraActor& Stage::GetDefaultCameraActor()
+{
+  return *mDefaultCamera;
+}
+
+unsigned int Stage::GetLayerCount() const
+{
+  return mLayerList->GetLayerCount();
+}
+
+Dali::Layer Stage::GetLayer( unsigned int depth ) const
+{
+  return Dali::Layer(mLayerList->GetLayer( depth ));
+}
+
+Dali::Layer Stage::GetRootLayer() const
+{
+  return Dali::Layer( mRootLayer.Get() );
+}
+
+LayerList& Stage::GetLayerList()
+{
+  return *mLayerList;
+}
+
+Integration::SystemOverlay& Stage::GetSystemOverlay()
+{
+  // Lazily create system-level if requested
+  if( !mSystemOverlay )
+  {
+    mSystemOverlay = new Integration::SystemOverlay( SystemOverlay::New( *this ) );
+    DALI_ASSERT_ALWAYS( NULL != mSystemOverlay && "Failed to create system overlay" );
+
+    mSystemOverlay->GetImpl()->SetSize( mSize.width, mSize.height );
+  }
+
+  return *mSystemOverlay;
+}
+
+SystemOverlay* Stage::GetSystemOverlayInternal()
+{
+  SystemOverlay* overlay( NULL );
+
+  if( mSystemOverlay )
+  {
+    overlay = mSystemOverlay->GetImpl();
+  }
+
+  return overlay;
+}
+
+void Stage::SetViewMode( ViewMode viewMode )
+{
+  if( mViewMode != viewMode )
+  {
+    DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "View mode changed from %d to %d\n", mViewMode, viewMode);
+
+    if( mViewMode == MONO )
+    {
+      mDefaultCamera->SetOrientation( Dali::ANGLE_180, Vector3::YAXIS );
+      mRenderTaskList->GetTask(0).SetSourceActor( Dali::Actor() );
+
+      //Create camera and RenderTask for left eye
+      mLeftCamera = CameraActor::New( Size::ZERO );
+      mLeftCamera->SetParentOrigin( ParentOrigin::CENTER );
+      mDefaultCamera->Add( *mLeftCamera.Get() );
+      mLeftRenderTask = mRenderTaskList->CreateTask();
+      mLeftRenderTask.SetCameraActor( Dali::CameraActor( mLeftCamera.Get() ) );
+      mLeftCamera->SetType( Dali::Camera::FREE_LOOK );
+
+      //Create camera and RenderTask for right eye
+      mRightCamera = CameraActor::New( Size::ZERO );
+      mRightCamera->SetParentOrigin( ParentOrigin::CENTER );
+      mDefaultCamera->Add( *mRightCamera.Get() );
+      mRightRenderTask = mRenderTaskList->CreateTask();
+      mRightRenderTask.SetClearColor( Vector4( 1.0f,0.0f,0.0f,1.0f));
+
+      mRightRenderTask.SetCameraActor( Dali::CameraActor( mRightCamera.Get() ) );
+      mRightCamera->SetType( Dali::Camera::FREE_LOOK );
+    }
+
+    // save new mode
+    mViewMode = viewMode;
+
+    switch( viewMode )
+    {
+      case MONO:
+      {
+        // delete extra stereoscopic render tasks and cameras
+        mRenderTaskList->RemoveTask( mLeftRenderTask );
+        mDefaultCamera->Remove( *mLeftCamera.Get() );
+        mLeftRenderTask.Reset();
+        mLeftCamera.Reset();
+        mRenderTaskList->RemoveTask( mRightRenderTask );
+        mDefaultCamera->Remove( *mRightCamera.Get() );
+        mRightRenderTask.Reset();
+        mRightCamera.Reset();
+        mDefaultCamera->SetOrientation( Dali::ANGLE_0, Vector3::YAXIS );
+        mDefaultCamera->SetType( Dali::Camera::LOOK_AT_TARGET );
+        mRenderTaskList->GetTask(0).SetSourceActor( Dali::Layer(mRootLayer.Get()) );
+
+        break;
+      }
+      case STEREO_HORIZONTAL:
+      {
+        //Stereo mode with horizontal split is for landscape mode. That's the reason for the cameras being rotated
+        //Top camera renders the scene as seen from the right eye and bottom camera as seen from left.
+
+        //Calculate separation in pixels along vertical axis ( mStereoBase is defined in millimetres )
+        const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().y ) * 0.5f );
+
+        //Calculate aspect ratio
+        float aspect = mSize.width / (mSize.height * 0.5f);
+
+        mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0f,stereoBase) );
+        mLeftCamera->SetAspectRatio( aspect );
+
+        mLeftCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
+        mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+        mLeftRenderTask.SetViewport( Viewport(0, mSize.height * 0.5f, mSize.width, mSize.height * 0.5f) );
+
+        mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0,  -stereoBase) );
+        mRightCamera->SetAspectRatio( aspect );
+        mRightCamera->SetOrientation( -Dali::ANGLE_90, Vector3::ZAXIS );
+        mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+        mRightRenderTask.SetViewport( Viewport(0, 0, mSize.width, mSize.height * 0.5f ) );
+
+        break;
+      }
+      case STEREO_VERTICAL:
+      {
+        //Calculate separation in pixels along horizontal axis
+        const float stereoBase( ( (mStereoBase / 25.4f) * GetDpi().x ) * 0.5f );
+
+        //Recalculate fov based on viewport size
+        const float fov = 2.0f * std::atan(  mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
+
+        mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
+        mLeftCamera->SetFieldOfView( fov );
+        mLeftCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
+        mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+        mLeftRenderTask.SetViewport( Viewport(0, 0, mSize.width * 0.5f, mSize.height ) );
+
+        mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
+        mRightCamera->SetFieldOfView( fov );
+        mRightCamera->SetOrientation( Dali::ANGLE_0, Vector3::ZAXIS );
+        mRightCamera->SetPosition( Vector3( -stereoBase, 0.0f, 0.0f ) );
+        mRightRenderTask.SetViewport( Viewport(mSize.width * 0.5f, 0, mSize.width * 0.5f, mSize.height ) );
+
+        break;
+      }
+      case STEREO_INTERLACED:
+      {
+        break;
+      }
+    }
+  }
+}
+
+ViewMode Stage::GetViewMode() const
+{
+  return mViewMode;
+}
+
+void Stage::SetStereoBase( float stereoBase )
+{
+  if( ! Equals( mStereoBase, stereoBase ) )
+  {
+    DALI_LOG_INFO( Debug::Filter::gActor, Debug::Concise, "old( %.2f) new(%.2f)", mStereoBase, stereoBase );
+    mStereoBase = stereoBase;
+
+    switch( mViewMode  )
+    {
+      case STEREO_HORIZONTAL:
+      {
+        stereoBase = mStereoBase / 25.4f * GetDpi().y * 0.5f;
+        float aspect = mSize.width / (mSize.height * 0.5f);
+
+        mLeftCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, stereoBase) );
+        mLeftCamera->SetAspectRatio( aspect );
+        mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+
+        mRightCamera->SetPerspectiveProjection( mSize, Vector2( 0.0, -stereoBase) );
+        mRightCamera->SetAspectRatio( aspect );
+        mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+
+        break;
+      }
+      case STEREO_VERTICAL:
+      {
+        stereoBase = mStereoBase / 25.4f * GetDpi().x * 0.5f;
+        const float fov = 2.0f * std::atan(  mSize.y / (2.0f * std::max( mSize.x*0.5f, mSize.y )) );
+
+        mLeftCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(stereoBase,0.0f) );
+        mLeftCamera->SetFieldOfView( fov );
+        mLeftCamera->SetPosition( Vector3( stereoBase, 0.0f, 0.0f ) );
+
+        mRightCamera->SetPerspectiveProjection( Size( mSize.x * 0.5f, mSize.y ), Vector2(-stereoBase,0.0f) );
+        mRightCamera->SetFieldOfView( fov );
+        mRightCamera->SetPosition( Vector3(-stereoBase, 0.0f, 0.0f ) );
+
+        break;
+      }
+      default:
+        break;
+    }
+  }
+}
+
+float Stage::GetStereoBase() const
+{
+  return mStereoBase;
+}
+
+void Stage::SetBackgroundColor(Vector4 color)
+{
+  // Cache for public GetBackgroundColor()
+  mBackgroundColor = color;
+
+  // Send message to change color in next frame
+  SetBackgroundColorMessage( mUpdateManager, color );
+}
+
+Vector4 Stage::GetBackgroundColor() const
+{
+  return mBackgroundColor;
+}
+
+Vector2 Stage::GetDpi() const
+{
+  return mDpi;
+}
+
+void Stage::SetDpi(Vector2 dpi)
+{
+  mDpi = dpi;
+}
+
+void Stage::KeepRendering( float durationSeconds )
+{
+  // Send message to keep rendering
+  KeepRenderingMessage( mUpdateManager, durationSeconds );
+}
+
+bool Stage::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  Stage* stage = dynamic_cast<Stage*>(object);
+
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_KEY_EVENT ) )
+  {
+    stage->KeyEventSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_EVENT_PROCESSING_FINISHED ) )
+  {
+    stage->EventProcessingFinishedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_TOUCHED ) )
+  {
+    stage->TouchedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_WHEEL_EVENT ) )
+  {
+    stage->WheelEventSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_CONTEXT_LOST ) )
+  {
+    stage->ContextLostSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_CONTEXT_REGAINED ) )
+  {
+    stage->ContextRegainedSignal().Connect( tracker, functor );
+  }
+  else if( 0 == strcmp( signalName.c_str(), SIGNAL_SCENE_CREATED ) )
+  {
+    stage->SceneCreatedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void Stage::EmitKeyEventSignal(const KeyEvent& event)
+{
+  // Emit the key event signal when no actor in the stage has gained the key input focus
+
+  mKeyEventSignal.Emit( event );
+}
+
+void Stage::EmitEventProcessingFinishedSignal()
+{
+   mEventProcessingFinishedSignal.Emit();
+}
+
+void Stage::EmitTouchedSignal( const TouchEvent& touch )
+{
+  mTouchedSignal.Emit( touch );
+}
+
+void Stage::EmitWheelEventSignal(const WheelEvent& event)
+{
+  // Emit the wheel event signal when no actor in the stage has gained the wheel input focus
+
+  mWheelEventSignal.Emit( event );
+}
+
+void Stage::EmitSceneCreatedSignal()
+{
+  mSceneCreatedSignal.Emit();
+}
+
+Dali::Stage::KeyEventSignalType& Stage::KeyEventSignal()
+{
+  return mKeyEventSignal;
+}
+
+Dali::Stage::EventProcessingFinishedSignalType& Stage::EventProcessingFinishedSignal()
+{
+  return mEventProcessingFinishedSignal;
+}
+
+Dali::Stage::TouchedSignalType& Stage::TouchedSignal()
+{
+  return mTouchedSignal;
+}
+
+Dali::Stage::WheelEventSignalType& Stage::WheelEventSignal()
+{
+  return mWheelEventSignal;
+}
+
+Dali::Stage::ContextStatusSignal& Stage::ContextLostSignal()
+{
+  return mContextLostSignal;
+}
+
+Dali::Stage::ContextStatusSignal& Stage::ContextRegainedSignal()
+{
+  return mContextRegainedSignal;
+}
+
+Dali::Stage::SceneCreatedSignalType& Stage::SceneCreatedSignal()
+{
+  return mSceneCreatedSignal;
+}
+
+void Stage::NotifyContextLost()
+{
+  mContextLostSignal.Emit();
+}
+
+void Stage::NotifyContextRegained()
+{
+  mContextRegainedSignal.Emit();
+}
+
+Stage::Stage( AnimationPlaylist& playlist,
+              PropertyNotificationManager& propertyNotificationManager,
+              SceneGraph::UpdateManager& updateManager,
+              NotificationManager& notificationManager )
+: mAnimationPlaylist( playlist ),
+  mPropertyNotificationManager(propertyNotificationManager),
+  mUpdateManager(updateManager),
+  mNotificationManager(notificationManager),
+  mSize(Vector2::ZERO),
+  mBackgroundColor(Dali::Stage::DEFAULT_BACKGROUND_COLOR),
+  mViewMode( MONO ),
+  mStereoBase( DEFAULT_STEREO_BASE ),
+  mSystemOverlay(NULL)
+{
+}
+
+SceneGraph::UpdateManager& Stage::GetUpdateManager()
+{
+  return mUpdateManager;
+}
+
+unsigned int* Stage::ReserveMessageSlot( std::size_t size, bool updateScene )
+{
+  return mUpdateManager.ReserveMessageSlot( size, updateScene );
+}
+
+BufferIndex Stage::GetEventBufferIndex() const
+{
+  return mUpdateManager.GetEventBufferIndex();
+}
+
+Stage::~Stage()
+{
+  delete mSystemOverlay;
+
+  mObjectRegistry.Reset();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/stage-impl.h b/dali/internal/event/common/stage-impl.h
new file mode 100644 (file)
index 0000000..33c7cc9
--- /dev/null
@@ -0,0 +1,503 @@
+#ifndef __DALI_INTERNAL_STAGE_H__
+#define __DALI_INTERNAL_STAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/integration-api/context-notifier.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/object-registry-impl.h>
+#include <dali/internal/event/common/stage-def.h>
+#include <dali/internal/event/render-tasks/render-task-defaults.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/public-api/common/view-mode.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/render-tasks/render-task.h>
+
+namespace Dali
+{
+
+struct Vector2;
+
+namespace Integration
+{
+class SystemOverlay;
+}
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+class AnimationPlaylist;
+class PropertyNotificationManager;
+class Layer;
+class LayerList;
+class SystemOverlay;
+class CameraActor;
+class RenderTaskList;
+
+/**
+ * Implementation of Stage
+ */
+class Stage : public BaseObject, public RenderTaskDefaults, public Integration::ContextNotifierInterface, public EventThreadServices
+{
+public:
+
+  /**
+   * Create the stage
+   * @param[in] playlist for animations
+   * @param[in] propertyNotificationManager
+   * @param[in] updateManager
+   * @param[in] notificationManager
+   */
+  static StagePtr New( AnimationPlaylist& playlist,
+                       PropertyNotificationManager& propertyNotificationManager,
+                       SceneGraph::UpdateManager& updateManager,
+                       NotificationManager& notificationManager );
+
+  /**
+   * Initialize the stage.
+   */
+  void Initialize();
+
+  /**
+   * Uninitialize the stage.
+   */
+  void Uninitialize();
+
+  /**
+   * @copydoc Dali::Stage::GetCurrent()
+   * @note this version is for internal usage so it does not assert
+   */
+  static StagePtr GetCurrent();
+
+  /**
+   * @copydoc Dali::Stage::IsInstalled().
+   */
+  static bool IsInstalled();
+
+  /**
+   * @copydoc Dali::Stage::GetObjectRegistry()
+   */
+  ObjectRegistry& GetObjectRegistry();
+
+  /**
+   * Retrieve the root actor (not publically accessible).
+   * @return The root actor.
+   */
+  Layer& GetRootActor();
+
+  /**
+   * Returns the animation playlist.
+   * @return reference to the animation playlist.
+   */
+  AnimationPlaylist& GetAnimationPlaylist();
+
+  /**
+   * Returns the property notification manager.
+   * @return reference to the property notification manager.
+   */
+  PropertyNotificationManager& GetPropertyNotificationManager();
+
+  // Root actor accessors
+
+  /**
+   * @copydoc Dali::Stage::Add()
+   */
+  void Add( Actor& actor );
+
+  /**
+   * @copydoc Dali::Stage::Remove()
+   */
+  void Remove( Actor& actor );
+
+  /**
+   * Sets the size of the stage and indirectly, the root actor.
+   * @param [in] width  The new width.
+   * @param [in] height The new height.
+   */
+  void SetSize( float width, float height );
+
+  /**
+   * Returns the size of the Stage in pixels as a Vector.
+   * The x component will be the width of the Stage in pixels
+   * The y component will be the height of the Stage in pixels
+   * @return The size of the Stage as a Vector.
+   */
+  Vector2 GetSize() const;
+
+  /**
+   * @copydoc Dali::Stage::GetRenderTaskList()
+   */
+  RenderTaskList& GetRenderTaskList() const;
+
+  /**
+   * Create a default camera actor
+   */
+  void CreateDefaultCameraActor();
+
+  /**
+   * From RenderTaskDefaults; retrieve the default root actor.
+   * @return The default root actor.
+   */
+  virtual Actor& GetDefaultRootActor();
+
+  /**
+   * From RenderTaskDefaults; retrieve the default camera actor.
+   * @return The default camera actor.
+   */
+  virtual CameraActor& GetDefaultCameraActor();
+
+  // Layers
+
+  /**
+   * @copydoc Dali::Stage::GetLayerCount()
+   */
+  unsigned int GetLayerCount() const;
+
+  /**
+   * @copydoc Dali::Stage::GetLayer()
+   */
+  Dali::Layer GetLayer( unsigned int depth ) const;
+
+  /**
+   * @copydoc Dali::Stage::GetRootLayer()
+   */
+  Dali::Layer GetRootLayer() const;
+
+  /**
+   * Retrieve the ordered list of on-stage layers.
+   * @return The layer-list.
+   */
+  LayerList& GetLayerList();
+
+  // System-level overlay actors
+
+  /**
+   * @copydoc Dali::Integration::Core::GetSystemOverlay()
+   */
+  Integration::SystemOverlay& GetSystemOverlay();
+
+  /**
+   * Retrieve the internal implementation of the SystemOverlay.
+   * @return The implementation, or NULL if this has never been requested from Integration API.
+   */
+  SystemOverlay* GetSystemOverlayInternal();
+
+  // Stereoscopy
+
+  /**
+   * @copydoc Dali::Integration::Core::SetViewMode()
+   */
+  void SetViewMode( ViewMode viewMode );
+
+  /**
+   * @copydoc Dali::Integration::Core::GetViewMode()
+   */
+  ViewMode GetViewMode() const;
+
+  /**
+   * @copydoc Dali::Integration::Core::SetStereoBase()
+   */
+  void SetStereoBase( float stereoBase );
+
+  /**
+   * @copydoc Dali::Integration::Core::GetStereoBase()
+   */
+  float GetStereoBase() const;
+
+  // Keyboard stuff
+
+  /**
+   * As one virtual keyboard per stage, the stage will hold a pointer to the Actor currently
+   * set to receive keyboard input.
+   * @param[in] actor to receive keyboard input
+   */
+  void SetKeyboardFocusActor( Actor* actor );
+
+  /**
+   * Get the actor that is currently set to receive keyboard inputs
+   * @return Pointer to the actor set to receive keyboard inputs.
+   */
+  Actor* GetKeyboardFocusActor() const;
+
+  /**
+   * Removes the given actor from keyboard focus so it will no longer receive key events from keyboard.
+   * @param [in] actor which should be removed from focus.
+   */
+  void RemoveActorFromKeyFocus( Actor* actor );
+
+  // Misc
+
+  /**
+   * @copydoc Dali::Stage::SetBackgroundColor
+   */
+  void SetBackgroundColor(Vector4 color);
+
+  /**
+   * @copydoc Dali::Stage::GetBackgroundColor
+   */
+  Vector4 GetBackgroundColor() const;
+
+  /**
+   * @copydoc Dali::Stage::GetDpi
+   */
+  Vector2 GetDpi() const;
+
+  /**
+   * Sets horizontal and vertical pixels per inch value that is used by the display
+   * @param[in] dpi Horizontal and vertical dpi value
+   */
+  void SetDpi( Vector2 dpi );
+
+  NotificationManager& GetNotificationManager()
+  {
+    return mNotificationManager;
+  }
+
+  /**
+   * @copydoc Dali::Stage::KeepRendering()
+   */
+  void KeepRendering( float durationSeconds );
+
+  /**
+   * Used by the EventProcessor to emit key event signals.
+   * @param[in] event The key event.
+   */
+  void EmitKeyEventSignal(const KeyEvent& event);
+
+  /**
+   * Emits the event processing finished signal.
+   *
+   * @see Dali::Stage::SignalEventProcessingFinished()
+   */
+  void EmitEventProcessingFinishedSignal();
+
+  /**
+   * Emits the touched signal.
+   * @param[in] touch The touch event details.
+   */
+  void EmitTouchedSignal( const TouchEvent& touch );
+
+  /**
+   * Used by the EventProcessor to emit wheel event signals.
+   * @param[in] event The wheel event.
+   */
+  void EmitWheelEventSignal( const WheelEvent& event );
+
+  /**
+   * Emits the scene created.
+   */
+  void EmitSceneCreatedSignal();
+
+  /**
+   * @copydoc Dali::Stage::KeyEventSignal()
+   */
+  Dali::Stage::KeyEventSignalType& KeyEventSignal();
+
+  /**
+   * @copydoc Dali::Stage::SignalEventProcessingFinished()
+   */
+  Dali::Stage::EventProcessingFinishedSignalType& EventProcessingFinishedSignal();
+
+  /**
+    * @copydoc Dali::Stage::TouchedSignal()
+    */
+  Dali::Stage::TouchedSignalType& TouchedSignal();
+
+  /**
+   * @copydoc Dali::Stage::WheelEventSignal()
+   */
+  Dali::Stage::WheelEventSignalType& WheelEventSignal();
+
+  /**
+   * @copydoc Dali::Stage::ContextLostSignal()
+   */
+  Dali::Stage::ContextStatusSignal& ContextLostSignal();
+
+  /**
+   * @copydoc Dali::Stage::ContextRegainedSignal()
+   */
+  Dali::Stage::ContextStatusSignal& ContextRegainedSignal();
+
+  /**
+   * @copydoc Dali::Stage::SceneCreatedSignal()
+   */
+  Dali::Stage::SceneCreatedSignalType& SceneCreatedSignal();
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+private: // Implementation of ContextNotificationInterface:
+
+  /**
+   * @copydoc Dali::Integration::NotifyContextLost();
+   */
+  virtual void NotifyContextLost();
+
+  /**
+   * @copydoc Dali::Integration::NotifyContextRegained();
+   */
+  virtual void NotifyContextRegained();
+
+public: // Implementation of EventThreadServices
+
+  /**
+   * @copydoc EventThreadServices::RegisterObject
+   */
+  virtual void RegisterObject( BaseObject* object);
+
+  /**
+   * @copydoc EventThreadServices::UnregisterObject
+   */
+  virtual void UnregisterObject( BaseObject* object);
+
+  /**
+   * @copydoc EventThreadServices::GetUpdateManager
+   */
+  virtual SceneGraph::UpdateManager& GetUpdateManager();
+
+  /**
+   * @copydoc EventThreadServices::ReserveMessageSlot
+   */
+  virtual unsigned int* ReserveMessageSlot( std::size_t size, bool updateScene );
+
+  /**
+   * @copydoc EventThreadServices::GetEventBufferIndex
+   */
+  virtual BufferIndex GetEventBufferIndex() const;
+
+private:
+
+  /**
+   * Protected constructor; see also Stage::New()
+   */
+  Stage( AnimationPlaylist& playlist,
+         PropertyNotificationManager& propertyNotificationManager,
+         SceneGraph::UpdateManager& updateManager,
+         NotificationManager& notificationManager );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Stage();
+
+private:
+
+  // For 'Fire and forget' animation support
+  AnimationPlaylist& mAnimationPlaylist;
+
+  PropertyNotificationManager& mPropertyNotificationManager;
+
+  SceneGraph::UpdateManager& mUpdateManager;
+
+  NotificationManager& mNotificationManager;
+
+  // The Actual size of the stage.
+  Vector2 mSize;
+
+  // Cached for public GetBackgroundColor()
+  Vector4 mBackgroundColor;
+
+  LayerPtr mRootLayer;
+
+  // Ordered list of currently on-stage layers
+  OwnerPointer<LayerList> mLayerList;
+
+  IntrusivePtr<CameraActor> mDefaultCamera;
+
+  ViewMode mViewMode;
+  float mStereoBase;
+
+  Vector2 mDpi;
+
+  // The object registry
+  ObjectRegistryPtr mObjectRegistry;
+
+  // The list of render-tasks
+  IntrusivePtr<RenderTaskList> mRenderTaskList;
+
+  Dali::RenderTask mRightRenderTask;
+  IntrusivePtr<CameraActor> mRightCamera;
+  Dali::RenderTask mLeftRenderTask;
+  IntrusivePtr<CameraActor> mLeftCamera;
+
+  Integration::SystemOverlay* mSystemOverlay; ///< SystemOverlay stage access
+
+  // The key event signal
+  Dali::Stage::KeyEventSignalType                 mKeyEventSignal;
+
+  // The event processing finished signal
+  Dali::Stage::EventProcessingFinishedSignalType  mEventProcessingFinishedSignal;
+
+  // The touched signal
+  Dali::Stage::TouchedSignalType                  mTouchedSignal;
+
+  // The wheel event signal
+  Dali::Stage::WheelEventSignalType               mWheelEventSignal;
+
+  Dali::Stage::ContextStatusSignal mContextLostSignal;
+  Dali::Stage::ContextStatusSignal mContextRegainedSignal;
+
+  Dali::Stage::SceneCreatedSignalType mSceneCreatedSignal;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::Stage& GetImplementation(Dali::Stage& stage)
+{
+  DALI_ASSERT_ALWAYS( stage && "Stage handle is empty" );
+
+  BaseObject& handle = stage.GetBaseObject();
+
+  return static_cast<Internal::Stage&>(handle);
+}
+
+inline const Internal::Stage& GetImplementation(const Dali::Stage& stage)
+{
+  DALI_ASSERT_ALWAYS( stage && "Stage handle is empty" );
+
+  const BaseObject& handle = stage.GetBaseObject();
+
+  return static_cast<const Internal::Stage&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_STAGE_H__
diff --git a/dali/internal/event/common/system-overlay-impl.cpp b/dali/internal/event/common/system-overlay-impl.cpp
new file mode 100644 (file)
index 0000000..2733568
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/system-overlay-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/actors/layer-list.h>
+#include <dali/internal/event/actor-attachments/camera-attachment-impl.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+SystemOverlay* SystemOverlay::New( EventThreadServices& eventThreadServices )
+{
+  SystemOverlay* overlay = new SystemOverlay( eventThreadServices );
+
+  overlay->Initialize();
+
+  return overlay;
+}
+
+SystemOverlay::~SystemOverlay()
+{
+  if ( mRootLayer )
+  {
+    // we are closing down so just delete the root, no point emit disconnect
+    // signals or send messages to update
+    mRootLayer.Reset();
+  }
+}
+
+void SystemOverlay::Add( Actor& actor )
+{
+  CreateRootLayer();
+
+  mRootLayer->Add( actor );
+}
+
+void SystemOverlay::Remove( Actor& actor )
+{
+  if ( mRootLayer )
+  {
+    mRootLayer->Remove( actor );
+  }
+}
+
+RenderTaskList& SystemOverlay::GetOverlayRenderTasks()
+{
+  if ( !mOverlayRenderTaskList )
+  {
+    mOverlayRenderTaskList = RenderTaskList::New( mEventThreadServices, *this, true/*system-overlay*/ );
+  }
+
+  return *mOverlayRenderTaskList;
+}
+
+void SystemOverlay::SetSize( float width, float height )
+{
+  mSize = Vector2( width, height );
+
+  if ( mRootLayer )
+  {
+    mRootLayer->SetSize( mSize.width, mSize.height );
+  }
+
+  if ( mDefaultCameraActor )
+  {
+    // Sets the default perspective projection for the given size.
+    mDefaultCameraActor->SetPerspectiveProjection( mSize );
+  }
+}
+
+LayerList& SystemOverlay::GetLayerList()
+{
+  return *mLayerList;
+}
+
+Actor& SystemOverlay::GetDefaultRootActor()
+{
+  CreateRootLayer();
+
+  return *mRootLayer;
+}
+
+CameraActor& SystemOverlay::GetDefaultCameraActor()
+{
+  CreateDefaultCameraActor();
+
+  return *mDefaultCameraActor;
+}
+
+SystemOverlay::SystemOverlay( EventThreadServices& eventThreadServices )
+: mEventThreadServices( eventThreadServices )
+{
+}
+
+void SystemOverlay::Initialize()
+{
+  // Create the ordered list of layers
+  mLayerList = LayerList::New( mEventThreadServices.GetUpdateManager(), true/*system layers*/ );
+}
+
+void SystemOverlay::CreateRootLayer()
+{
+  // Lazy initialization; SystemOverlay may never be used
+  if ( !mRootLayer )
+  {
+    mRootLayer = Layer::NewRoot( *mLayerList, mEventThreadServices.GetUpdateManager(), true/*system layer*/ );
+    mRootLayer->SetName("SystemOverlayRoot");
+    mRootLayer->SetSize( mSize.width, mSize.height );
+  }
+}
+
+void SystemOverlay::CreateDefaultCameraActor()
+{
+  // Lazy initialization; SystemOverlay may never be used
+  if ( !mDefaultCameraActor )
+  {
+    // Creates a default camera with a default perspective projection.
+    mDefaultCameraActor = CameraActor::New( mSize );
+    mDefaultCameraActor->SetParentOrigin( ParentOrigin::CENTER );
+
+    Add( *mDefaultCameraActor );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/system-overlay-impl.h b/dali/internal/event/common/system-overlay-impl.h
new file mode 100644 (file)
index 0000000..eeb9a54
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __DALI_INTERNAL_SYSTEM_OVERLAY_H__
+#define __DALI_INTERNAL_SYSTEM_OVERLAY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/system-overlay.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/event/actors/actor-declarations.h>
+#include <dali/internal/event/render-tasks/render-task-defaults.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class LayerList;
+class RenderTaskList;
+class EventThreadServices;
+
+/**
+ * Implementation of Dali::Integration::SystemOverlay
+ */
+class SystemOverlay : public RenderTaskDefaults
+{
+public:
+
+  /**
+   * Create the SystemOverlay; This should only be done once for each Dali core.
+   * @param[in] eventThreadServices to send messaged to scene graph.
+   * @return The newly allocated SystemOverlay.
+   */
+  static SystemOverlay* New( EventThreadServices& eventThreadServices );
+
+  /**
+   * Non-virtual destructor; not intended as a base class.
+   */
+  ~SystemOverlay();
+
+  /**
+   * @copydoc Dali::Integration::SystemOverlay::Add()
+   */
+  void Add( Actor& actor );
+
+  /**
+   * @copydoc Dali::Integration::SystemOverlay::Remove()
+   */
+  void Remove( Actor& actor );
+
+  /**
+   * @copydoc Dali::Integration::SystemOverlay::GetOverlayRenderTasks()
+   */
+  RenderTaskList& GetOverlayRenderTasks();
+
+  /**
+   * Forwarded from Stage::SetSize().
+   * @param[in] width  The new width.
+   * @param[in] height The new height.
+   */
+  void SetSize( float width, float height );
+
+  /**
+   * Retrieve the ordered list of system layers.
+   * @return The layer-list.
+   */
+  LayerList& GetLayerList();
+
+  /**
+   * From RenderTaskDefaults.
+   * Retrieve the default SystemOverlay root actor.
+   * @note This is different to the root actor provided by Dali::Stage.
+   */
+  virtual Actor& GetDefaultRootActor();
+
+  /**
+   * From RenderTaskDefaults.
+   * Retrieve the default SystemOverlay camera actor.
+   * @note This is different to the default camera actor provided by Dali::Stage.
+   */
+  virtual CameraActor& GetDefaultCameraActor();
+
+private:
+
+  /**
+   * Protected constructor; see also SystemOverlay::New().
+   * @param[in] eventThreadServices to send messaged to the scene graph.
+   */
+  SystemOverlay( EventThreadServices& eventThreadServices );
+
+  /**
+   * Second-phase construction.
+   */
+  void Initialize();
+
+  /**
+   * Lazy initialization of the SystemOverlay root actor.
+   */
+  void CreateRootLayer();
+
+  /**
+   * Lazy initialization of the default camera actor.
+   */
+  void CreateDefaultCameraActor();
+
+private:
+
+  EventThreadServices& mEventThreadServices;
+
+  Vector2 mSize;
+
+  IntrusivePtr<RenderTaskList> mOverlayRenderTaskList;
+
+  LayerPtr mRootLayer;
+
+  CameraActorPtr mDefaultCameraActor;
+
+  // Ordered list of currently on-stage layers
+  OwnerPointer<LayerList> mLayerList;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SYSTEM_OVERLAY_H__
diff --git a/dali/internal/event/common/thread-local-storage.cpp b/dali/internal/event/common/thread-local-storage.cpp
new file mode 100644 (file)
index 0000000..ee99ba8
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/thread-local-storage.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/core-impl.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+__thread ThreadLocalStorage* threadLocal = NULL;
+}
+
+ThreadLocalStorage::ThreadLocalStorage(Core* core)
+: mCore( core )
+{
+  DALI_ASSERT_ALWAYS( threadLocal == NULL && "Cannot create more than one ThreadLocalStorage object" );
+
+  threadLocal = this;
+}
+
+ThreadLocalStorage::~ThreadLocalStorage()
+{
+}
+
+void ThreadLocalStorage::Remove()
+{
+  threadLocal = NULL;
+}
+
+ThreadLocalStorage& ThreadLocalStorage::Get()
+{
+  DALI_ASSERT_ALWAYS(threadLocal);
+
+  return *threadLocal;
+}
+
+bool ThreadLocalStorage::Created()
+{
+  // see if the TLS has been set yet
+  return (threadLocal != NULL);
+}
+
+ThreadLocalStorage* ThreadLocalStorage::GetInternal()
+{
+  return threadLocal;
+}
+
+Dali::Integration::PlatformAbstraction& ThreadLocalStorage::GetPlatformAbstraction()
+{
+  return mCore->GetPlatform();
+}
+
+SceneGraph::UpdateManager& ThreadLocalStorage::GetUpdateManager()
+{
+  return mCore->GetUpdateManager();
+}
+
+NotificationManager& ThreadLocalStorage::GetNotificationManager()
+{
+  return mCore->GetNotificationManager();
+}
+
+ResourceManager& ThreadLocalStorage::GetResourceManager()
+{
+  return mCore->GetResourceManager();
+}
+
+ResourceClient& ThreadLocalStorage::GetResourceClient()
+{
+  return mCore->GetResourceClient();
+}
+
+ImageFactory& ThreadLocalStorage::GetImageFactory()
+{
+  return mCore->GetImageFactory();
+}
+
+ShaderFactory& ThreadLocalStorage::GetShaderFactory()
+{
+  return mCore->GetShaderFactory();
+}
+
+StagePtr ThreadLocalStorage::GetCurrentStage()
+{
+  return mCore->GetCurrentStage();
+}
+
+GestureEventProcessor& ThreadLocalStorage::GetGestureEventProcessor()
+{
+  return mCore->GetGestureEventProcessor();
+}
+
+RelayoutController& ThreadLocalStorage::GetRelayoutController()
+{
+  return mCore->GetRelayoutController();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/thread-local-storage.h b/dali/internal/event/common/thread-local-storage.h
new file mode 100644 (file)
index 0000000..73a4021
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef __DALI_INTERNAL_THREAD_LOCAL_STORAGE_H__
+#define __DALI_INTERNAL_THREAD_LOCAL_STORAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/stage-def.h>
+
+namespace Dali
+{
+
+struct Vector2;
+
+namespace Integration
+{
+class PlatformAbstraction;
+}
+
+namespace Internal
+{
+
+class Core;
+class NotificationManager;
+class ResourceClient;
+class ResourceManager;
+class ImageFactory;
+class ShaderFactory;
+class GestureEventProcessor;
+class RelayoutController;
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+/**
+ * Class to store a pointer to core in thread local storage.
+ *
+ */
+class ThreadLocalStorage
+{
+public:
+
+  /**
+   * Constructor
+   * Creates the TLS and adds a pointer to core
+   * @param [in] core reference to core
+   */
+  ThreadLocalStorage(Core* core);
+
+  /**
+   * Destructor.
+   */
+  ~ThreadLocalStorage();
+
+  /**
+   * Remove core pointer.
+   * Prevents the core pointer being automatically deleted when the thread exits.
+   */
+  void Remove();
+
+  /**
+   * Get the TLS
+   * @return reference to the TLS
+   */
+  static ThreadLocalStorage& Get();
+
+  /**
+   * Checks if the TLS has been created
+   * @return if the TLS has been created
+   */
+  static bool Created();
+
+  /**
+   * Get a pointer to the TLS or NULL if not initialized
+   * @return pointer to the TLS
+   */
+  static ThreadLocalStorage* GetInternal();
+
+  /**
+   * get platform abstraction
+   * @return reference to core
+   */
+  Dali::Integration::PlatformAbstraction& GetPlatformAbstraction();
+
+  /**
+   * Retrieve the update manager
+   * @return reference to update manager
+   */
+  SceneGraph::UpdateManager& GetUpdateManager();
+
+  /**
+   * Returns the Notification Manager
+   * @return reference to the Notification Manager
+   */
+  NotificationManager& GetNotificationManager();
+
+  /**
+   * Returns the Resource Manager
+   * @return reference to the Resource Manager
+   */
+  ResourceManager& GetResourceManager();
+
+  /**
+   * Returns the Resource Client
+   * @return reference to the Resource Client
+   */
+  ResourceClient& GetResourceClient();
+
+  /**
+   * Returns the Image Factory
+   * @return reference to the Image Factory
+   */
+  ImageFactory& GetImageFactory();
+
+  /**
+   * Returns the Shader Factory
+   * @return reference to the Shader Factory
+   */
+  ShaderFactory& GetShaderFactory();
+
+  /**
+   * Returns the current stage.
+   * @return A pointer to the current stage.
+   */
+  StagePtr GetCurrentStage();
+
+  /**
+   * Returns the gesture event processor.
+   * @return A reference to the gesture event processor.
+   */
+  GestureEventProcessor& GetGestureEventProcessor();
+
+  /**
+   * Return the relayout controller
+   * @Return Return a reference to the relayout controller
+   */
+  RelayoutController& GetRelayoutController();
+
+private:
+
+  Core* mCore;                                              ///< reference to core
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_THREAD_LOCAL_STORAGE_H__
diff --git a/dali/internal/event/common/type-info-impl.cpp b/dali/internal/event/common/type-info-impl.cpp
new file mode 100644 (file)
index 0000000..b73d925
--- /dev/null
@@ -0,0 +1,677 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/type-info-impl.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm> // std::find_if
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/common/type-registry-impl.h>
+#include <dali/internal/event/common/object-impl.h>
+
+using std::find_if;
+
+namespace
+{
+
+/*
+ * Functor to find by given type for vector of pairs
+ */
+template <typename S, typename T>
+struct PairFinder
+{
+  PairFinder(const S& find)
+  : mFind(find)
+  {
+  }
+
+  bool operator()(const T& p) const
+  {
+    return p.first == mFind;
+  }
+
+private:
+
+  const S& mFind;
+};
+
+/**
+ * Functor to find a matching property name
+ */
+template <typename T>
+struct PropertyNameFinder
+{
+  PropertyNameFinder( const std::string& find )
+  : mFind( find )
+  {
+  }
+
+  bool operator()(const T &p) const
+  {
+    return p.second.name == mFind;
+  }
+
+private:
+
+  const std::string& mFind;
+};
+
+/**
+ * Functor to find a matching property component index
+ */
+template <typename T>
+struct PropertyComponentFinder
+{
+  PropertyComponentFinder( Dali::Property::Index basePropertyIndex, const int find )
+  : mBasePropertyIndex( basePropertyIndex ),
+    mFind( find )
+  {
+  }
+
+  bool operator()(const T &p) const
+  {
+    return ( p.second.basePropertyIndex == mBasePropertyIndex && p.second.componentIndex == mFind );
+  }
+
+private:
+
+  Dali::Property::Index mBasePropertyIndex;
+  const int mFind;
+};
+
+} // namespace anon
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+TypeInfo::TypeInfo(const std::string &name, const std::string &baseTypeName, Dali::TypeInfo::CreateFunction creator)
+  : mTypeName(name), mBaseTypeName(baseTypeName), mCreate(creator)
+{
+  DALI_ASSERT_ALWAYS(!name.empty() && "Type info construction must have a name");
+  DALI_ASSERT_ALWAYS(!baseTypeName.empty() && "Type info construction must have a base type name");
+}
+
+TypeInfo::~TypeInfo()
+{
+}
+
+BaseHandle TypeInfo::CreateInstance() const
+{
+  BaseHandle ret;
+
+  if(mCreate)
+  {
+    ret = mCreate();
+
+    if ( ret )
+    {
+      BaseObject& handle = ret.GetBaseObject();
+      Object *object = dynamic_cast<Internal::Object*>(&handle);
+
+      if ( object )
+      {
+        object->SetTypeInfo( this );
+      }
+    }
+  }
+  return ret;
+}
+
+  bool TypeInfo::DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties)
+{
+  bool done = false;
+
+  ActionContainer::iterator iter = find_if(mActions.begin(), mActions.end(), PairFinder<std::string, ActionPair>(actionName));
+
+  if( iter != mActions.end() )
+  {
+    done = (iter->second)(object, actionName, properties);
+  }
+  else
+  {
+    DALI_LOG_WARNING("Type '%s' cannot do action '%s'\n", mTypeName.c_str(), actionName.c_str());
+  }
+
+  if(!done)
+  {
+    Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
+    while( base )
+    {
+      done = GetImplementation(base).DoActionTo(object, actionName, properties);
+      if( done )
+      {
+        break;
+      }
+      base =  Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+    }
+  }
+
+  return done;
+}
+
+bool TypeInfo::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( false );
+
+  ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
+                                                 PairFinder<std::string, ConnectionPair>(signalName) );
+
+  if( iter != mSignalConnectors.end() )
+  {
+    connected = (iter->second)( object, connectionTracker, signalName, functor );
+  }
+
+  return connected;
+}
+
+const std::string& TypeInfo::GetName() const
+{
+  return mTypeName;
+}
+
+const std::string& TypeInfo::GetBaseName() const
+{
+  return mBaseTypeName;
+}
+
+Dali::TypeInfo::CreateFunction TypeInfo::GetCreator() const
+{
+  return mCreate;
+}
+
+size_t TypeInfo::GetActionCount() const
+{
+  size_t count = mActions.size();
+
+  Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
+  while( base )
+  {
+    count += GetImplementation(base).mActions.size();
+    base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+  }
+
+  return count;
+}
+
+std::string TypeInfo::GetActionName(size_t index) const
+{
+  std::string name;
+
+  if( index < mActions.size() )
+  {
+    name = mActions[index].first;
+  }
+  else
+  {
+    size_t count = mActions.size();
+
+    Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
+    while( base )
+    {
+      size_t baseCount = GetImplementation(base).mActions.size();
+
+      if( index < count + baseCount )
+      {
+        name = GetImplementation(base).mActions[ index - count ].first;
+        break;
+      }
+
+      count += baseCount;
+
+      base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+    }
+  }
+
+  return name;
+}
+
+size_t TypeInfo::GetSignalCount() const
+{
+  size_t count = mSignalConnectors.size();
+
+  Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
+  while( base )
+  {
+    count += GetImplementation(base).mSignalConnectors.size();
+    base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+  }
+
+  return count;
+}
+
+std::string TypeInfo::GetSignalName(size_t index) const
+{
+  std::string name;
+
+  if( index < mSignalConnectors.size() )
+  {
+    name = mSignalConnectors[index].first;
+  }
+  else
+  {
+    size_t count = mSignalConnectors.size();
+
+    Dali::TypeInfo base = Dali::TypeRegistry::Get().GetTypeInfo( mBaseTypeName );
+    while( base )
+    {
+      size_t baseCount = GetImplementation(base).mSignalConnectors.size();
+
+      if( index < count + baseCount )
+      {
+        name = GetImplementation(base).mSignalConnectors[ index - count ].first;
+        break;
+      }
+
+      count += baseCount;
+
+      base = Dali::TypeRegistry::Get().GetTypeInfo( base.GetBaseName() );
+    }
+  }
+
+  return name;
+}
+
+void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+  Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+  if ( base )
+  {
+    const TypeInfo& baseImpl( GetImplementation( base ) );
+    baseImpl.GetPropertyIndices( indices );
+  }
+
+  if ( ! mRegisteredProperties.empty() )
+  {
+    indices.Reserve( indices.Size() + mRegisteredProperties.size() );
+
+    const RegisteredPropertyContainer::const_iterator endIter = mRegisteredProperties.end();
+    for ( RegisteredPropertyContainer::const_iterator iter = mRegisteredProperties.begin(); iter != endIter; ++iter )
+    {
+      indices.PushBack( iter->first );
+    }
+  }
+}
+
+const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
+{
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    return iter->second.name;
+  }
+
+  Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+  if ( base )
+  {
+    return GetImplementation(base).GetPropertyName( index );
+  }
+
+  DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+}
+
+void TypeInfo::AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function )
+{
+  if( NULL == function)
+  {
+    DALI_LOG_WARNING("Action function is empty\n");
+  }
+  else
+  {
+    ActionContainer::iterator iter = std::find_if(mActions.begin(), mActions.end(),
+                                                  PairFinder<std::string, ActionPair>(actionName));
+
+    if( iter == mActions.end() )
+    {
+      mActions.push_back( ActionPair( actionName, function ) );
+    }
+    else
+    {
+      DALI_LOG_WARNING("Action already exists in TypeRegistry Type", actionName.c_str());
+    }
+  }
+}
+
+void TypeInfo::AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function )
+{
+  if( NULL == function)
+  {
+    DALI_LOG_WARNING("Connector function is empty\n");
+  }
+  else
+  {
+    ConnectorContainer::iterator iter = find_if( mSignalConnectors.begin(), mSignalConnectors.end(),
+                                                   PairFinder<std::string, ConnectionPair>(signalName) );
+
+    if( iter == mSignalConnectors.end() )
+    {
+      mSignalConnectors.push_back( ConnectionPair( signalName, function ) );
+    }
+    else
+    {
+      DALI_LOG_WARNING("Signal name already exists in TypeRegistry Type for signal connector function", signalName.c_str());
+    }
+  }
+}
+
+void TypeInfo::AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
+{
+  // The setter can be empty as a property can be read-only.
+
+  if ( NULL == getFunc )
+  {
+    DALI_ASSERT_ALWAYS( ! "GetProperty Function is empty" );
+  }
+  else
+  {
+    RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+    if ( iter == mRegisteredProperties.end() )
+    {
+      mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, setFunc, getFunc, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+    }
+  }
+}
+
+void TypeInfo::AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type )
+{
+  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                        PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+  if ( iter == mRegisteredProperties.end() )
+  {
+    mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, Property::INVALID_INDEX, Property::INVALID_COMPONENT_INDEX ) ) );
+  }
+  else
+  {
+    DALI_ASSERT_ALWAYS( ! "Property index already added to Type" );
+  }
+}
+
+void TypeInfo::AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
+{
+  Property::Type type = GetPropertyType( baseIndex );
+  DALI_ASSERT_ALWAYS( ( type == Property::VECTOR2 || type == Property::VECTOR3 || type == Property::VECTOR4 ) && "Base property does not support component" );
+
+  bool success = false;
+
+  RegisteredPropertyContainer::iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                        PairFinder< Property::Index, RegisteredPropertyPair>(index) );
+
+  if ( iter == mRegisteredProperties.end() )
+  {
+    iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                    PropertyComponentFinder< RegisteredPropertyPair >( baseIndex, componentIndex ) );
+
+    if ( iter == mRegisteredProperties.end() )
+    {
+      mRegisteredProperties.push_back( RegisteredPropertyPair( index, RegisteredProperty( type, NULL, NULL, name, baseIndex, componentIndex ) ) );
+      success = true;
+    }
+  }
+
+  DALI_ASSERT_ALWAYS( success && "Property component already registered" );
+}
+
+size_t TypeInfo::GetPropertyCount() const
+{
+  size_t count( mRegisteredProperties.size() );
+
+  Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+  while ( base )
+  {
+    const TypeInfo& baseImpl( GetImplementation(base) );
+    count += baseImpl.mRegisteredProperties.size();
+    base = TypeRegistry::Get()->GetTypeInfo( baseImpl.mBaseTypeName );
+  }
+
+  return count;
+}
+
+Property::Index TypeInfo::GetPropertyIndex( const std::string& name ) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Slow but should not be done that often
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PropertyNameFinder< RegisteredPropertyPair >( name ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    index = iter->first;
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      index = GetImplementation(base).GetPropertyIndex( name );
+    }
+  }
+
+  return index;
+}
+
+Property::Index TypeInfo::GetBasePropertyIndex( Property::Index index ) const
+{
+  Property::Index basePropertyIndex = Property::INVALID_INDEX;
+
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    basePropertyIndex = iter->second.basePropertyIndex;
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      basePropertyIndex = GetImplementation(base).GetBasePropertyIndex( index );
+    }
+  }
+
+  return basePropertyIndex;
+}
+
+int TypeInfo::GetComponentIndex( Property::Index index ) const
+{
+  int componentIndex = Property::INVALID_COMPONENT_INDEX;
+
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    componentIndex = iter->second.componentIndex;
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      componentIndex = GetImplementation(base).GetComponentIndex( index );
+    }
+  }
+
+  return componentIndex;
+}
+
+bool TypeInfo::IsPropertyWritable( Property::Index index ) const
+{
+  bool writable( false );
+
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    if( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) )
+    {
+      writable = true; // animatable property is writable
+    }
+    else
+    {
+      writable = iter->second.setFunc ? true : false;
+    }
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      writable = GetImplementation(base).IsPropertyWritable( index );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+    }
+  }
+
+  return writable;
+}
+
+Property::Type TypeInfo::GetPropertyType( Property::Index index ) const
+{
+  Property::Type type( Property::NONE );
+
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+
+  if ( iter != mRegisteredProperties.end() )
+  {
+    type = iter->second.type;
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      type = GetImplementation(base).GetPropertyType( index );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+    }
+  }
+
+  return type;
+}
+
+void TypeInfo::SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const
+{
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                              PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+  if ( iter != mRegisteredProperties.end() )
+  {
+    if( iter->second.setFunc )
+    {
+      iter->second.setFunc( object, index, value );
+    }
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      GetImplementation(base).SetProperty( object, index, value );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+    }
+  }
+}
+
+void TypeInfo::SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const
+{
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                              PropertyNameFinder< RegisteredPropertyPair >( name ) );
+  if ( iter != mRegisteredProperties.end() )
+  {
+    DALI_ASSERT_ALWAYS( iter->second.setFunc && "Trying to write to a read-only property" );
+    iter->second.setFunc( object, iter->first, value );
+  }
+  else
+  {
+    Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+    if ( base )
+    {
+      GetImplementation(base).SetProperty( object, name, value );
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
+    }
+  }
+}
+
+Property::Value TypeInfo::GetProperty( const BaseObject *object, Property::Index index ) const
+{
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PairFinder< Property::Index, RegisteredPropertyPair >( index ) );
+  if( iter != mRegisteredProperties.end() )
+  {
+    // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
+    return iter->second.getFunc( const_cast< BaseObject* >( object ), index );
+  }
+
+  Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+  if ( base )
+  {
+    return GetImplementation( base ).GetProperty( object, index );
+  }
+
+  DALI_ASSERT_ALWAYS( ! "Cannot find property index" ); // use the same assert as Object
+}
+
+Property::Value TypeInfo::GetProperty( const BaseObject *object, const std::string& name ) const
+{
+  RegisteredPropertyContainer::const_iterator iter = find_if( mRegisteredProperties.begin(), mRegisteredProperties.end(),
+                                                          PropertyNameFinder< RegisteredPropertyPair >( name ) );
+  if( iter != mRegisteredProperties.end() )
+  {
+    // Need to remove the constness here as CustomActor will not be able to call Downcast with a const pointer to the object
+    return iter->second.getFunc( const_cast< BaseObject* >( object ), iter->first );
+  }
+
+  Dali::TypeInfo base = TypeRegistry::Get()->GetTypeInfo( mBaseTypeName );
+  if ( base )
+  {
+    return GetImplementation( base ).GetProperty( object, name );
+  }
+
+  DALI_ASSERT_ALWAYS( ! "Cannot find property name" );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/type-info-impl.h b/dali/internal/event/common/type-info-impl.h
new file mode 100644 (file)
index 0000000..9055e35
--- /dev/null
@@ -0,0 +1,318 @@
+#ifndef __DALI_INTERNAL_TYPE_INFO_H__
+#define __DALI_INTERNAL_TYPE_INFO_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/type-info.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A TypeInfo class to support registered type creation, and introspection of available
+ * actions and signal connection.
+ * It also supports doing actions and connecting signal handlers. Note this is properly
+ * conducted through the BaseHandle interface which uses the TypeRegistry to walk
+ * all base classes.
+ */
+class TypeInfo : public BaseObject
+{
+public:
+  /**
+   * Create TypeInfo
+   * @param [name] the registered name
+   * @param [baseName] the base type registered name
+   * @param [creator] the creator function for this type
+   */
+  TypeInfo(const std::string &name, const std::string &baseName, Dali::TypeInfo::CreateFunction creator);
+
+  /**
+   *
+   */
+  ~TypeInfo();
+
+  /**
+   * @copydoc Dali::TypeInfo::GetName
+   */
+  const std::string& GetName() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetBaseName
+   */
+  const std::string& GetBaseName() const;
+
+  /**
+   * @copydoc TypeInfo::CreateFunction
+   */
+  BaseHandle CreateInstance() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetCreator
+   */
+  Dali::TypeInfo::CreateFunction GetCreator() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetActionCount
+   */
+  size_t GetActionCount() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetActionName
+   */
+  std::string GetActionName(size_t index) const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetSignalCount
+   */
+  size_t GetSignalCount() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetSignalName
+   */
+  std::string GetSignalName(size_t index) const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetPropertyCount
+   */
+  size_t GetPropertyCount() const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetPropertyName
+   */
+  std::string GetPropertyName(size_t index) const;
+
+  /**
+   * Adds the property indices to the container specified.
+   * @param[in/out] indices The container where the property indices are added.
+   */
+  void GetPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::TypeInfo::GetPropertyName() const
+   */
+  const std::string& GetPropertyName( Property::Index index ) const;
+
+  /*
+   * Add an action function
+   */
+  void AddActionFunction( const std::string &actionName, Dali::TypeInfo::ActionFunction function );
+
+  /*
+   * Add a function for connecting a signal.
+   * @param[in] signalName The name of the signal.
+   * @param[in] function The function used for connecting to the signal.
+   */
+  void AddConnectorFunction( const std::string& signalName, Dali::TypeInfo::SignalConnectorFunction function );
+
+  /**
+   * Adds an event-thread only property to the type.
+   * @param[in] name The name of the property.
+   * @param[in] index The index of the property.
+   * @param[in] type The Property::Type.
+   * @param[in] setFunc The function to call to set the property (Can be NULL).
+   * @param[in] getFunc The function to call to retrieve the value of the property.
+   */
+  void AddProperty( const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc );
+
+  /**
+   * Adds an animatable property to the type.
+   * @param[in] name The name of the property.
+   * @param[in] index The index of the property
+   * @param[in] type The Property::Type.
+   */
+  void AddAnimatableProperty( const std::string& name, Property::Index index, Property::Type type );
+
+  /**
+   * Adds a component of an animatable property to the type.
+   * The animatable property must have been type-registered and must be a Vector2, Vector3 or Vector4 type.
+   * @param[in] name The name of the component.
+   * @param[in] index The index of the property
+   * @param[in] baseIndex The index of the base animatable property
+   * @param[in] component The index The index of the component.
+   */
+  void AddAnimatablePropertyComponent( const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex );
+
+  /**
+   * Do an action on base object
+   * @param [in] object The base object to act upon
+   * @param [in] actionName The name of the desired action
+   * @param [in] properties The arguments of the action
+   * @return bool If the action could be executed
+   */
+  bool DoActionTo(BaseObject *object, const std::string &actionName, const Property::Map &properties);
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  bool ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor );
+
+  /**
+   * Given a property name, retrieve the index.
+   * @param[in] name The name of the property.
+   * @return The index associated with that name.
+   */
+  Property::Index GetPropertyIndex( const std::string& name ) const;
+
+  /**
+   * Given a property index, retrieve the index of its base property.
+   * @param[in] index The index of the property.
+   * @return The index of the base property associated with the given property index.
+   */
+  Property::Index GetBasePropertyIndex( Property::Index index ) const;
+
+  /**
+   * Given a property index, retrieve its component index.
+   * @param[in] index The index of the property.
+   * @return The component index associated with that property index.
+   */
+  int GetComponentIndex( Property::Index index ) const;
+
+  /**
+   * Checks if there is a setter for the property. If there is then it is writable.
+   * @param[in] index The property index.
+   * @return True, if writable, false otherwise.
+   */
+  bool IsPropertyWritable( Property::Index index ) const;
+
+  /**
+   * Retrieve the Property::Type of the property at the given index.
+   * @param[in] index The property index.
+   * @return The Property::Type at that index.
+   */
+  Property::Type GetPropertyType( Property::Index index ) const;
+
+  /**
+   * Sets the value of a property at the index specified for the given object.
+   * @param[in] object The object whose property is to be set.
+   * @param[in] index The property index.
+   * @param[in] value The value to set.
+   */
+  void SetProperty( BaseObject *object, Property::Index index, const Property::Value& value ) const;
+
+  /**
+   * Sets the value of a property with the name specified for the given object.
+   * @param[in] object The object whose property is to be set.
+   * @param[in] name The property name.
+   * @param[in] value The value to set.
+   */
+  void SetProperty( BaseObject *object, const std::string& name, const Property::Value& value ) const;
+
+  /**
+   * Retrieves the value of a property at the index specified for the given object.
+   * @param[in] object The object whose property is to be queried.
+   * @param[in] index The property index.
+   * @return The current value of the property.
+   */
+  Property::Value GetProperty( const BaseObject *object, Property::Index index ) const;
+
+  /**
+   * Retrieves the value of a property with the name specified for the given object.
+   * @param[in] object The object whose property is to be queried.
+   * @param[in] name The property name.
+   * @return The current value of the property.
+   */
+  Property::Value GetProperty( const BaseObject *object, const std::string& name ) const;
+
+private:
+
+  struct RegisteredProperty
+  {
+    RegisteredProperty()
+    : type( Property::NONE ),
+      setFunc( NULL ),
+      getFunc( NULL ),
+      name(),
+      basePropertyIndex(Property::INVALID_INDEX),
+      componentIndex(Property::INVALID_COMPONENT_INDEX)
+    {
+    }
+
+    RegisteredProperty( Property::Type propType, Dali::TypeInfo::SetPropertyFunction set, Dali::TypeInfo::GetPropertyFunction get, const std::string& propName, Property::Index basePropertyIndex, int componentIndex )
+    : type( propType ),
+      setFunc( set ),
+      getFunc( get ),
+      name( propName ),
+      basePropertyIndex(basePropertyIndex),
+      componentIndex(componentIndex)
+    {
+    }
+
+    Property::Type type;
+    Dali::TypeInfo::SetPropertyFunction setFunc;
+    Dali::TypeInfo::GetPropertyFunction getFunc;
+    std::string name;
+    Property::Index basePropertyIndex;
+    int componentIndex;
+  };
+
+  typedef std::pair<std::string, Dali::TypeInfo::SignalConnectorFunction > ConnectionPair;
+  typedef std::pair<std::string, Dali::TypeInfo::ActionFunction > ActionPair;
+  typedef std::pair<Property::Index, RegisteredProperty> RegisteredPropertyPair;
+
+  typedef std::vector< ActionPair > ActionContainer;
+  typedef std::vector< ConnectionPair > ConnectorContainer;
+  typedef std::vector< RegisteredPropertyPair > RegisteredPropertyContainer;
+
+  std::string mTypeName;
+  std::string mBaseTypeName;
+  Dali::TypeInfo::CreateFunction mCreate;
+  ActionContainer mActions;
+  ConnectorContainer mSignalConnectors;
+  RegisteredPropertyContainer mRegisteredProperties;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::TypeInfo& GetImplementation(Dali::TypeInfo& typeInfo)
+{
+  DALI_ASSERT_ALWAYS(typeInfo);
+
+  BaseObject& handle = typeInfo.GetBaseObject();
+
+  return static_cast<Internal::TypeInfo&>(handle);
+}
+
+inline const Internal::TypeInfo& GetImplementation(const Dali::TypeInfo& typeInfo)
+{
+  DALI_ASSERT_ALWAYS(typeInfo);
+
+  const BaseObject& handle = typeInfo.GetBaseObject();
+
+  return static_cast<const Internal::TypeInfo&>(handle);
+}
+
+} // namespace Dali
+
+#endif // header
diff --git a/dali/internal/event/common/type-registry-impl.cpp b/dali/internal/event/common/type-registry-impl.cpp
new file mode 100644 (file)
index 0000000..d875fc5
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/common/type-registry-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/internal/event/actors/custom-actor-internal.h>
+#include <dali/internal/event/common/demangler.h>
+
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TYPE_REGISTRY");
+#endif
+
+} // namespace anon
+
+namespace Dali
+{
+
+extern std::string Demangle(const char* symbol);
+
+namespace Internal
+{
+
+TypeRegistry *TypeRegistry::Get()
+{
+  static TypeRegistry *_reg(new TypeRegistry());
+  DALI_ASSERT_DEBUG(_reg);
+  return _reg;
+}
+
+TypeRegistry::TypeRegistry()
+{
+
+}
+
+TypeRegistry::~TypeRegistry()
+{
+  mRegistryLut.clear();
+}
+
+Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::string &uniqueTypeName )
+{
+  Dali::TypeInfo ret;
+
+  RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
+
+  if( iter != mRegistryLut.end() )
+  {
+    ret = iter->second;
+  }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", uniqueTypeName.c_str());
+  }
+
+  return ret;
+}
+
+Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::type_info& registerType )
+{
+  Dali::TypeInfo ret;
+
+  std::string typeName = DemangleClassName(registerType.name());
+
+  RegistryMap::iterator iter = mRegistryLut.find(typeName);
+
+  if( iter != mRegistryLut.end() )
+  {
+    ret = iter->second;
+  }
+  else
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Cannot find requested type '%s'\n", registerType.name());
+  }
+
+  return ret;
+}
+
+size_t TypeRegistry::GetTypeNameCount() const
+{
+  return mRegistryLut.size();
+}
+
+
+std::string TypeRegistry::GetTypeName(size_t index) const
+{
+  std::string name;
+
+  if( index < mRegistryLut.size() )
+  {
+    RegistryMap::const_iterator iter = mRegistryLut.begin();
+    std::advance(iter, index);
+    name = iter->first;
+  }
+
+  return name;
+}
+
+
+bool TypeRegistry::Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
+                             Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
+{
+  std::string uniqueTypeName  = DemangleClassName(theTypeInfo.name());
+
+  return Register( uniqueTypeName, baseTypeInfo, createInstance, callCreateOnInit );
+}
+
+bool TypeRegistry::Register( const std::string& uniqueTypeName, const std::type_info& baseTypeInfo,
+                             Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit )
+{
+  bool ret = false;
+
+  std::string baseTypeName    = DemangleClassName(baseTypeInfo.name());
+
+  RegistryMap::iterator iter = mRegistryLut.find(uniqueTypeName);
+
+  if( iter == mRegistryLut.end() )
+  {
+    mRegistryLut[uniqueTypeName] = Dali::TypeInfo(new Internal::TypeInfo(uniqueTypeName, baseTypeName, createInstance));
+    ret = true;
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "Type Registration %s(%s)\n", uniqueTypeName.c_str(), baseTypeName.c_str());
+  }
+  else
+  {
+    DALI_LOG_WARNING("Duplicate name for TypeRegistry for '%s'\n", + uniqueTypeName.c_str());
+    DALI_ASSERT_ALWAYS(!"Duplicate type name for Type Registation");
+  }
+
+  if( callCreateOnInit )
+  {
+    mInitFunctions.push_back(createInstance);
+  }
+
+  return ret;
+}
+
+void TypeRegistry::CallInitFunctions(void) const
+{
+  for( InitFunctions::const_iterator iter = mInitFunctions.begin(); iter != mInitFunctions.end(); ++iter)
+  {
+    (*iter)();
+  }
+}
+
+std::string TypeRegistry::RegistrationName( const std::type_info& registerType )
+{
+  return DemangleClassName( registerType.name() );
+}
+
+void TypeRegistry::RegisterSignal( TypeRegistration& typeRegistration, const std::string& name, Dali::TypeInfo::SignalConnectorFunction func )
+{
+  RegistryMap::iterator iter = mRegistryLut.find( typeRegistration.RegisteredName() );
+
+  if( iter != mRegistryLut.end() )
+  {
+    DALI_ASSERT_DEBUG(iter->second);
+
+    GetImplementation(iter->second).AddConnectorFunction( name, func );
+  }
+}
+
+bool TypeRegistry::RegisterAction( TypeRegistration &registered, const std::string &name, Dali::TypeInfo::ActionFunction f)
+{
+  RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
+
+  if( iter != mRegistryLut.end() )
+  {
+    DALI_ASSERT_DEBUG(iter->second);
+
+    GetImplementation(iter->second).AddActionFunction( name, f );
+
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool TypeRegistry::RegisterProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc )
+{
+  RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
+
+  if( iter != mRegistryLut.end() )
+  {
+    DALI_ASSERT_DEBUG(iter->second);
+
+    GetImplementation(iter->second).AddProperty( name, index, type, setFunc, getFunc );
+
+    return true;
+  }
+
+  return false;
+}
+
+bool TypeRegistry::RegisterAnimatableProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type )
+{
+  RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
+
+  if( iter != mRegistryLut.end() )
+  {
+    DALI_ASSERT_DEBUG(iter->second);
+
+    GetImplementation(iter->second).AddAnimatableProperty( name, index, type );
+
+    return true;
+  }
+
+  return false;
+}
+
+bool TypeRegistry::RegisterAnimatablePropertyComponent( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex )
+{
+  RegistryMap::iterator iter = mRegistryLut.find( registered.RegisteredName() );
+
+  if( iter != mRegistryLut.end() )
+  {
+    DALI_ASSERT_DEBUG(iter->second);
+
+    GetImplementation(iter->second).AddAnimatablePropertyComponent( name, index, baseIndex, componentIndex );
+
+    return true;
+  }
+
+  return false;
+}
+
+bool TypeRegistry::DoActionTo( BaseObject * const object, const std::string &actionName, const Property::Map &properties)
+{
+  bool done = false;
+
+  Dali::TypeInfo type = GetTypeInfo( object );
+
+  while( type )
+  {
+    if(GetImplementation(type).DoActionTo(object, actionName, properties))
+    {
+      done = true;
+      break;
+    }
+    type = GetTypeInfo( type.GetBaseName() );
+  }
+
+  return done;
+}
+
+bool TypeRegistry::ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( false );
+
+  Dali::TypeInfo type = GetTypeInfo( object );
+
+  while( type )
+  {
+    connected = GetImplementation(type).ConnectSignal( object, connectionTracker, signalName, functor );
+    if( connected )
+    {
+      break;
+    }
+    type = GetTypeInfo( type.GetBaseName() );
+  }
+
+  if( !connected )
+  {
+    // Ownership of functor was not passed to Dali::CallbackBase, so clean-up now
+    delete functor;
+  }
+
+  return connected;
+}
+
+Dali::TypeInfo TypeRegistry::GetTypeInfo(const Dali::BaseObject * const pBaseObject)
+{
+  Dali::TypeInfo type;
+
+  // test for custom actor which has another indirection to get to the type hiearchy we're after
+  const Dali::Internal::CustomActor * const pCustom = dynamic_cast<const Dali::Internal::CustomActor*>(pBaseObject);
+
+  if(pCustom)
+  {
+    type = GetTypeInfo( typeid( pCustom->GetImplementation() ) );
+  }
+  else
+  {
+    type = GetTypeInfo( typeid( *pBaseObject ) );
+  }
+
+  return type;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/common/type-registry-impl.h b/dali/internal/event/common/type-registry-impl.h
new file mode 100644 (file)
index 0000000..5423349
--- /dev/null
@@ -0,0 +1,222 @@
+#ifndef __DALI_INTERNAL_TYPE_REGISTRY_H__
+#define __DALI_INTERNAL_TYPE_REGISTRY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/internal/event/common/type-info-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+////////////////////////////////////////////////////////////////////////////////
+class TypeRegistry;
+
+/*
+* @copydoc Dali::TypeRegistry
+*/
+class TypeRegistry : public Dali::BaseObject
+{
+public:
+  /**
+   * Get the TypeRegistry
+   */
+  static TypeRegistry *Get();
+
+  /*
+   * @copydoc Dali::TypeRegistry::GetTypeInfo
+   */
+  Dali::TypeInfo GetTypeInfo( const std::string &uniqueTypeName );
+
+  /*
+   * @copydoc Dali::TypeRegistry::GetTypeInfo
+   */
+  Dali::TypeInfo GetTypeInfo( const std::type_info& registerType );
+
+  /*
+   * @copydoc Dali::TypeRegistry::GetTypeNameCount
+   */
+  size_t GetTypeNameCount() const;
+
+  /*
+   * @copydoc Dali::TypeRegistry::GetTypeName
+   */
+  std::string GetTypeName(size_t index) const;
+
+  /*
+   * Register a creation function under a unique name.
+   * @param [in] theTypeInfo Type info for the type to be registered
+   * @param [in] baseTypeInfo Type info for its base class
+   * @param [in] createInstance Instance creation function
+   * @param [in] callCreateOnInit If true call createInstance on dali initialisation
+   * @return true if the name could be registered.
+   */
+  bool Register( const std::type_info& theTypeInfo, const std::type_info& baseTypeInfo,
+                 Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit );
+
+  /*
+   * Register a creation function under a unique name.
+   * @param [in] name The name type to be registered (must be unique)
+   * @param [in] baseTypeInfo Type info for its base class
+   * @param [in] createInstance Instance creation function
+   * @param [in] callCreateOnInit If true call createInstance on dali initialisation
+   * @return true if the name could be registered.
+   */
+  bool Register( const std::string& name, const std::type_info& baseTypeInfo,
+                 Dali::TypeInfo::CreateFunction createInstance, bool callCreateOnInit  );
+
+  /*
+   * Register a signal connector function to a type
+   * @param [in] typeRegistration TypeRegistration object used to register the type
+   * @param [in] name Signal name
+   * @param [in] func Signal connector function
+   */
+  void RegisterSignal( TypeRegistration& typeRegistration, const std::string& name, Dali::TypeInfo::SignalConnectorFunction func );
+
+  /*
+   * Register an action function to a type
+   * @param [in] registered TypeRegistration object used to register the type
+   * @param [in] name Action name
+   * @param [in] f Action function
+   * @return true if registered
+   */
+  bool RegisterAction( TypeRegistration &registered, const std::string &name, Dali::TypeInfo::ActionFunction f);
+
+  /**
+   * Register an event-thread only property with a type
+   * @param [in] registered TypeRegistration object used to register the type
+   * @param [in] name Property name
+   * @param [in] index Property index
+   * @param [in] type Property type
+   * @param [in] setFunc The function to set the property (Can be NULL).
+   * @param [in] getFunc The function to get the value of a property.
+   * @return true if registered
+   */
+  bool RegisterProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type, Dali::TypeInfo::SetPropertyFunction setFunc, Dali::TypeInfo::GetPropertyFunction getFunc );
+
+  /**
+   * Register a scene graph only property with a type
+   * @param [in] registered TypeRegistration object used to register the type
+   * @param [in] name Property name
+   * @param [in] index Property index
+   * @param [in] type Property type
+   * @return true if registered
+   */
+  bool RegisterAnimatableProperty( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type );
+
+  /**
+   * Register a component of a scene graph only property that supports components (i.e. Vector2, Vector3 and Vector4)
+   * @param [in] registered TypeRegistration object used to register the type
+   * @param [in] name Component name
+   * @param [in] index Property index
+   * @param [in] baseIndex Base animatable property index
+   * @param [in] componentIndex Component index
+   * @return true if registered
+   */
+  bool RegisterAnimatablePropertyComponent( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex );
+
+  /*
+   * @copydoc Dali::Internal::TypeInfo::DoActionTo
+   * Walks all base types until it finds a doer.
+   */
+  bool DoActionTo( BaseObject * const object, const std::string &actionName, const Property::Map& properties);
+
+  /**
+   * @copydoc Dali::BaseHandle::ConnectSignal()
+   */
+  bool ConnectSignal( BaseObject* object, ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor );
+
+  /*
+   * Return the type info for a given BaseObject pointer
+   * @param [in] pBaseObject Pointer to a BaseObject
+   * @return TypeInfo for the BaseObject.
+   */
+  Dali::TypeInfo GetTypeInfo(const Dali::BaseObject * const pBaseObject);
+
+  /*
+   * Calls any type creation functions that have been flagged as initialization functions
+   */
+  void CallInitFunctions(void) const;
+
+public:
+
+  /*
+   * Return the name derived from type_info used to register the type
+   * @param [in] registerType Type info for the type to be registered
+   * @return registered name
+   */
+  static std::string RegistrationName( const std::type_info& registerType );
+
+private:
+  /*
+   * Map from type name to TypeInfo
+   */
+  typedef std::map<std::string, Dali::TypeInfo> RegistryMap;
+  RegistryMap mRegistryLut;
+
+  typedef std::vector<Dali::TypeInfo::CreateFunction> InitFunctions;
+  InitFunctions mInitFunctions;
+
+private:
+  TypeRegistry();
+  ~TypeRegistry();
+
+  /**
+   * @brief Undefined Copy Constructor
+   */
+  TypeRegistry(TypeRegistry &);
+
+  /**
+   * @brief Undefined Assignment Operator
+   */
+  TypeRegistry& operator=(const TypeRegistry &);
+};
+
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::TypeRegistry& GetImplementation(Dali::TypeRegistry& typeRegistry)
+{
+  DALI_ASSERT_ALWAYS(typeRegistry);
+
+  BaseObject& handle = typeRegistry.GetBaseObject();
+
+  return static_cast<Internal::TypeRegistry&>(handle);
+}
+
+inline const Internal::TypeRegistry& GetImplementation(const Dali::TypeRegistry& typeRegistry)
+{
+  DALI_ASSERT_ALWAYS(typeRegistry);
+
+  const BaseObject& handle = typeRegistry.GetBaseObject();
+
+  return static_cast<const Internal::TypeRegistry&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TYPE_REGISTRY_H__
diff --git a/dali/internal/event/effects/shader-declarations.h b/dali/internal/event/effects/shader-declarations.h
new file mode 100644 (file)
index 0000000..0203922
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __DALI_INTERNAL_SHADER_DECLARATIONS_H__
+#define __DALI_INTERNAL_SHADER_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL HEADERS
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ShaderEffect;
+typedef IntrusivePtr<ShaderEffect> ShaderEffectPtr;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SHADER_DECLARATIONS_H__
diff --git a/dali/internal/event/effects/shader-effect-impl.cpp b/dali/internal/event/effects/shader-effect-impl.cpp
new file mode 100644 (file)
index 0000000..a038ef6
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/effects/shader-effect-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/scripting/scripting.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+#include <dali/internal/event/effects/shader-factory.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/render/shaders/uniform-meta.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include "dali-shaders.h"
+
+using Dali::Internal::SceneGraph::UpdateManager;
+using Dali::Internal::SceneGraph::UniformMeta;
+using Dali::Internal::SceneGraph::Shader;
+using Dali::Internal::SceneGraph::AnimatableProperty;
+using Dali::Internal::SceneGraph::PropertyBase;
+using Dali::Internal::SceneGraph::RenderQueue;
+using std::string;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+//              Name             Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "grid-density",   FLOAT,   true,    false,   false,   Dali::ShaderEffect::Property::GRID_DENSITY   )
+DALI_PROPERTY( "image",          MAP,     true,    false,   false,   Dali::ShaderEffect::Property::IMAGE          )
+DALI_PROPERTY( "program",        MAP,     true,    false,   false,   Dali::ShaderEffect::Property::PROGRAM        )
+DALI_PROPERTY( "geometry-hints", STRING,  true,    false,   false,   Dali::ShaderEffect::Property::GEOMETRY_HINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+BaseHandle Create()
+{
+  Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New();
+
+  return Dali::ShaderEffect(internal.Get());
+}
+
+TypeRegistration mType( typeid(Dali::ShaderEffect), typeid(Dali::Handle), Create );
+
+struct WrapperStrings
+{
+  const char* vertexShaderPrefix;
+  const char* fragmentShaderPrefix;
+  const char* vertexShaderPostfix;
+  const char* fragmentShaderPostfix;
+};
+
+WrapperStrings customImageShaderWrappers =
+{
+  CustomImagePrefixVertex, CustomImagePrefixFragment,
+  CustomImagePostfixVertex, CustomImagePostfixFragment
+};
+
+/**
+ * Helper to wrap the program with our default pre and postfix if needed and then send it to update/render thread
+ * @param[in] effect of the shader
+ * @param[in] vertexPrefix from application
+ * @param[in] fragmentPrefix from application
+ * @param[in] vertexBody from application
+ * @param[in] fragmentBody from application
+ * @param[in] modifiesGeometry based on flags and vertex shader
+ */
+void WrapAndSetProgram( Internal::ShaderEffect& effect,
+                        const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                        const std::string& vertexBody, const std::string& fragmentBody,
+                        bool modifiesGeometry )
+{
+  // if there is some real data in the strings
+  if( ( vertexPrefix.length()   > 0 ) ||
+      ( fragmentPrefix.length() > 0 ) ||
+      ( vertexBody.length()     > 0 ) ||
+      ( fragmentBody.length()   > 0 ) )
+  {
+    std::string vertexSource = vertexPrefix;
+    std::string fragmentSource = fragmentPrefix;
+
+    // Create complete shader program strings:
+
+    vertexSource += customImageShaderWrappers.vertexShaderPrefix;
+
+    // Append the custom vertex shader code if supplied, otherwise append the default
+    if ( vertexBody.length() > 0 )
+    {
+      vertexSource.append( vertexBody );
+    }
+    else
+    {
+      vertexSource.append( customImageShaderWrappers.vertexShaderPostfix );
+    }
+
+    fragmentSource += customImageShaderWrappers.fragmentShaderPrefix;
+
+    // Append the custom fragment shader code if supplied, otherwise append the default
+    if ( fragmentBody.length() > 0 )
+    {
+      fragmentSource.append( fragmentBody );
+    }
+    else
+    {
+      fragmentSource.append( customImageShaderWrappers.fragmentShaderPostfix );
+    }
+
+    effect.SendProgramMessage( vertexSource, fragmentSource, modifiesGeometry );
+  }
+}
+
+std::string GetShader(const std::string& field, const Property::Value& property)
+{
+  std::string retval;
+  const Property::Map* map = property.GetMap();
+  if( map )
+  {
+    const Property::Value* value = map->Find( field );
+    if( value )
+    {
+      value->Get( retval );
+    }
+  }
+
+  return retval;
+}
+
+} // unnamed namespace
+
+ShaderEffectPtr ShaderEffect::New( Dali::ShaderEffect::GeometryHints hints )
+{
+  Stage* stage = Stage::GetCurrent();
+
+  if( stage )
+  {
+    ShaderEffectPtr shaderEffect( new ShaderEffect( *stage, hints ) );
+    shaderEffect->RegisterObject();
+    return shaderEffect;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+ShaderEffect::ShaderEffect( EventThreadServices& eventThreadServices, Dali::ShaderEffect::GeometryHints hints )
+: mEventThreadServices( eventThreadServices ),
+  mConnectionCount (0),
+  mGeometryHints( hints )
+{
+  mSceneObject = new SceneGraph::Shader( hints );
+  DALI_ASSERT_DEBUG( NULL != mSceneObject );
+
+  // Transfer shader ownership to a scene message
+  AddShaderMessage( eventThreadServices.GetUpdateManager(), *mSceneObject );
+}
+
+ShaderEffect::~ShaderEffect()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if ( Stage::IsInstalled() )
+  {
+    // Remove scene-object using a message to the UpdateManager
+    if( mSceneObject )
+    {
+      RemoveShaderMessage( mEventThreadServices.GetUpdateManager(), *mSceneObject );
+    }
+    UnregisterObject();
+  }
+}
+
+void ShaderEffect::SetEffectImage( Dali::Image image )
+{
+  // if images are the same, do nothing
+  if (mImage == image)
+  {
+    return;
+  }
+
+  if (mImage && mConnectionCount > 0)
+  {
+    // unset previous image
+    GetImplementation(mImage).Disconnect();
+  }
+
+  // in case image is empty this will reset our image handle
+  mImage = image;
+
+  if (!image)
+  {
+    // mSceneShader can be in a separate thread; queue a setter message
+    SetTextureIdMessage( mEventThreadServices, *mSceneObject, 0 );
+  }
+  else
+  {
+    // tell image that we're using it
+    if (mConnectionCount > 0)
+    {
+      GetImplementation(mImage).Connect();
+    }
+    // mSceneShader can be in a separate thread; queue a setter message
+    SetTextureIdMessage( mEventThreadServices, *mSceneObject, GetImplementation(mImage).GetResourceId() );
+  }
+}
+
+void ShaderEffect::SetUniform( const std::string& name, Property::Value value, UniformCoordinateType uniformCoordinateType )
+{
+  // Register the property if it does not exist
+  Property::Index index = GetPropertyIndex( name );
+  if ( Property::INVALID_INDEX == index )
+  {
+    index = RegisterProperty( name, value );
+  }
+
+  SetProperty( index, value );
+
+  // RegisterProperty guarantees a positive value as index
+  DALI_ASSERT_DEBUG( static_cast<unsigned int>(index) >= CustomPropertyStartIndex() );
+  unsigned int metaIndex = index - CustomPropertyStartIndex();
+  // check if there's space in cache
+  if( mCoordinateTypes.Count() < (metaIndex + 1) )
+  {
+    mCoordinateTypes.Resize( metaIndex + 1 );
+  }
+  // only send message if the value is different than current, initial value is COORDINATE_TYPE_DEFAULT (0)
+  if( uniformCoordinateType != mCoordinateTypes[ metaIndex ] )
+  {
+    mCoordinateTypes[ metaIndex ] = uniformCoordinateType;
+    SetCoordinateTypeMessage( mEventThreadServices, *mSceneObject, metaIndex, uniformCoordinateType );
+  }
+}
+
+void ShaderEffect::SetPrograms( const string& vertexSource, const string& fragmentSource )
+{
+  SetPrograms( "", "", vertexSource, fragmentSource );
+}
+
+void ShaderEffect::SetPrograms( const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                                const std::string& vertexSource, const std::string& fragmentSource )
+{
+  bool modifiesGeometry = true;
+  // check if the vertex shader is empty (means it cannot modify geometry)
+  if( (vertexPrefix.length() == 0) && (vertexSource.length() == 0) )
+  {
+    modifiesGeometry = false;
+  }
+  // check the hint second
+  if( ( mGeometryHints & Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) != 0 )
+  {
+    modifiesGeometry = false;
+  }
+
+  WrapAndSetProgram( *this, vertexPrefix, fragmentPrefix, vertexSource, fragmentSource, modifiesGeometry );
+}
+
+void ShaderEffect::SendProgramMessage( const string& vertexSource, const string& fragmentSource,
+                                       bool modifiesGeometry )
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  ShaderFactory& shaderFactory = tls.GetShaderFactory();
+  size_t shaderHash;
+
+  Internal::ShaderDataPtr shaderData = shaderFactory.Load( vertexSource, fragmentSource, shaderHash );
+  DALI_ASSERT_DEBUG( shaderHash != 0U );
+
+  // Add shader program to scene-object using a message to the UpdateManager
+  SetShaderProgramMessage( mEventThreadServices.GetUpdateManager(), *mSceneObject, shaderData, modifiesGeometry );
+}
+
+void ShaderEffect::Connect()
+{
+  ++mConnectionCount;
+
+  if (mImage && mConnectionCount == 1)
+  {
+    GetImplementation(mImage).Connect();
+
+    // Image may have changed resource due to load/release policy. Ensure correct texture ID is set on scene graph object
+    SetTextureIdMessage( mEventThreadServices, *mSceneObject, GetImplementation(mImage).GetResourceId() );
+  }
+}
+
+void ShaderEffect::Disconnect()
+{
+  DALI_ASSERT_DEBUG(mConnectionCount > 0);
+  --mConnectionCount;
+
+  if (mImage && mConnectionCount == 0)
+  {
+     GetImplementation(mImage).Disconnect();
+  }
+}
+
+unsigned int ShaderEffect::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void ShaderEffect::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* ShaderEffect::GetDefaultPropertyName(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+
+  return NULL;
+}
+
+Property::Index ShaderEffect::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+
+  return index;
+}
+
+bool ShaderEffect::IsDefaultPropertyWritable(Property::Index index) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].writable;
+}
+
+bool ShaderEffect::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
+}
+
+bool ShaderEffect::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
+}
+
+Property::Type ShaderEffect::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range...return Property::NONE
+  return Property::NONE;
+}
+
+void ShaderEffect::SetDefaultProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  switch ( index )
+  {
+    case Dali::ShaderEffect::Property::GRID_DENSITY:
+    {
+      SetGridDensityMessage( mEventThreadServices, *mSceneObject, propertyValue.Get<float>() );
+      break;
+    }
+
+    case Dali::ShaderEffect::Property::IMAGE:
+    {
+      Dali::Image img(Scripting::NewImage( propertyValue ));
+      if(img)
+      {
+        SetEffectImage( img );
+      }
+      else
+      {
+        DALI_LOG_WARNING("Cannot create image from property value for ShaderEffect image\n");
+      }
+      break;
+    }
+
+    case Dali::ShaderEffect::Property::PROGRAM:
+    {
+      std::string vertexPrefix   = GetShader("vertex-prefix", propertyValue);
+      std::string fragmentPrefix = GetShader("fragment-prefix", propertyValue);
+      std::string vertex         = GetShader("vertex", propertyValue);
+      std::string fragment       = GetShader("fragment", propertyValue);
+
+      SetPrograms( vertexPrefix, fragmentPrefix, vertex, fragment );
+      break;
+    }
+
+    case Dali::ShaderEffect::Property::GEOMETRY_HINTS:
+    {
+      Dali::ShaderEffect::GeometryHints hint = Dali::ShaderEffect::HINT_NONE;
+      std::string s = propertyValue.Get<std::string>();
+      if(s == "HINT_NONE")
+      {
+        hint = Dali::ShaderEffect::HINT_NONE;
+      }
+      else if(s == "HINT_GRID_X")
+      {
+        hint = Dali::ShaderEffect::HINT_GRID_X;
+      }
+      else if(s == "HINT_GRID_Y")
+      {
+        hint = Dali::ShaderEffect::HINT_GRID_Y;
+      }
+      else if(s == "HINT_GRID")
+      {
+        hint = Dali::ShaderEffect::HINT_GRID;
+      }
+      else if(s == "HINT_DEPTH_BUFFER")
+      {
+        hint = Dali::ShaderEffect::HINT_DEPTH_BUFFER;
+      }
+      else if(s == "HINT_BLENDING")
+      {
+        hint = Dali::ShaderEffect::HINT_BLENDING;
+      }
+      else if(s == "HINT_DOESNT_MODIFY_GEOMETRY")
+      {
+        hint = Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY;
+      }
+      else
+      {
+        DALI_ASSERT_ALWAYS(!"Geometry hint unknown" );
+      }
+
+      SetHintsMessage( mEventThreadServices, *mSceneObject, hint );
+
+      break;
+    }
+
+    default:
+    {
+      // nothing to do
+      break;
+    }
+  }
+}
+
+Property::Value ShaderEffect::GetDefaultProperty(Property::Index /*index*/) const
+{
+  // none of our properties are readable so return empty
+  return Property::Value();
+}
+
+void ShaderEffect::NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index ) const
+{
+  // Warning - the property is added to the Shader object in the Update thread and the meta-data is added in the Render thread (through a secondary message)
+
+  // mSceneObject requires metadata for each custom property (uniform)
+  UniformMeta* meta = UniformMeta::New( name, newProperty, Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT );
+  // mSceneObject is being used in a separate thread; queue a message to add the property
+  InstallUniformMetaMessage( mEventThreadServices, *mSceneObject, *meta ); // Message takes ownership
+}
+
+const SceneGraph::PropertyOwner* ShaderEffect::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const PropertyBase* ShaderEffect::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  PropertyMetadata* property = index >= PROPERTY_CUSTOM_START_INDEX ? static_cast<PropertyMetadata*>(FindCustomProperty( index )) : static_cast<PropertyMetadata*>(FindAnimatableProperty( index ));
+  DALI_ASSERT_ALWAYS( property && "Property index is invalid" );
+  return property->GetSceneGraphProperty();
+}
+
+const PropertyInputImpl* ShaderEffect::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  return GetSceneObjectAnimatableProperty( index );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/effects/shader-effect-impl.h b/dali/internal/event/effects/shader-effect-impl.h
new file mode 100644 (file)
index 0000000..2ccc768
--- /dev/null
@@ -0,0 +1,240 @@
+#ifndef __DALI_INTERNAL_SHADER_EFFECT_H__
+#define __DALI_INTERNAL_SHADER_EFFECT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+/**
+ * An abstract base class for a shader effect object.
+ * The corresponding scene-graph object is a collection of shader programs,
+ * which can apply the same effect to different geometry types.
+ */
+class ShaderEffect : public Object
+{
+public:
+  typedef Dali::ShaderEffect::UniformCoordinateType UniformCoordinateType;
+
+  enum GeometryState
+  {
+    DOESNT_MODIFY_GEOMETRY,
+    MODIFIES_GEOMETRY
+  };
+
+  /**
+   * Create a new ShaderEffect with no programs
+   * @param hints GeometryHints to define the geometry of the rendered object
+   * @return A smart-pointer to a newly allocated shader effect.
+   */
+  static ShaderEffectPtr New( Dali::ShaderEffect::GeometryHints hints = Dali::ShaderEffect::HINT_NONE );
+
+  /**
+   * @copydoc Dali::ShaderEffect::SetEffectImage
+   */
+  void SetEffectImage( Dali::Image image );
+
+  /**
+   * @copydoc Dali::ShaderEffect::SetUniform( const std::string& name, Property::Value value, UniformCoordinateType uniformCoordinateType )
+   */
+  void SetUniform( const std::string& name,
+                   Property::Value value,
+                   UniformCoordinateType uniformCoordinateType );
+
+  /**
+   * Add a GeometryType specific default program to this ShaderEffect
+   * @param[in] geometryType    The GeometryType rendered by the shader program
+   * @param[in] vertexSource    The source code for the vertex shader
+   * @param[in] fragmentSource  The source code for the fragment shader
+   */
+  void SetPrograms( const std::string& vertexSource, const std::string& fragmentSource );
+
+  /**
+   * Add a default program to this ShaderEffect.
+   * This overload allows the optional prefixing for both the vertex and fragment shader.
+   * A useful prefix may be shader \#defines for conditional compilation.
+   * @param[in] vertexPrefix    The prefix source code for the vertex shader
+   * @param[in] fragmentPrefix  The prefix source code for the fragment shader
+   * @param[in] vertexSource    The source code for the vertex shader
+   * @param[in] fragmentSource  The source code for the fragment shader
+   */
+  void SetPrograms( const std::string& vertexPrefix, const std::string& fragmentPrefix,
+                    const std::string& vertexSource, const std::string& fragmentSource );
+
+  /**
+   * Send shader program to scene-graph object.
+   * @param[in] vertexSource     The source code for the vertex shader
+   * @param[in] fragmentSource   The source code for the fragment shader
+   * @param[in] modifiesGeometry True if the shader modifies geometry
+   */
+  void SendProgramMessage( const std::string& vertexSource, const std::string& fragmentSource,
+                           bool modifiesGeometry );
+
+  /**
+   * Notify ShaderEffect that it's being used by an Actor.
+   */
+  void Connect();
+
+  /**
+   * Notify ShaderEffect that an Actor is no longer using it.
+   */
+  void Disconnect();
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex( const std::string& name ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty( Property::Index index, const Property::Value& propertyValue );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::NotifyScenePropertyInstalled()
+   */
+  virtual void NotifyScenePropertyInstalled( const SceneGraph::PropertyBase& newProperty, const std::string& name, unsigned int index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+protected:
+
+  /**
+   * Protected constructor.
+   * @param[in] eventThreadServices the interface to use for sending messages to the update thread
+   * @param[in] hints Geometry hints
+   */
+  ShaderEffect( EventThreadServices& eventThreadServices, Dali::ShaderEffect::GeometryHints hints );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ShaderEffect();
+
+private:
+
+  // No copying allowed, thus these are undefined
+  ShaderEffect( const ShaderEffect& );
+  ShaderEffect& operator=( const ShaderEffect& rhs );
+
+private: // Data
+  EventThreadServices& mEventThreadServices; ///< Event thread services, for sending messages
+  SceneGraph::Shader* mSceneObject;         ///< pointer to the scene shader, should not be changed on this thread
+  Dali::Image mImage;                       ///< Client-side handle for the effect image
+  unsigned int  mConnectionCount;           ///< number of on-stage ImageActors using this shader effect
+  Dali::ShaderEffect::GeometryHints  mGeometryHints; ///< shader geometry hints for building the geometry
+  Dali::Vector< UniformCoordinateType > mCoordinateTypes; ///< cached to avoid sending tons of unnecessary messages
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ShaderEffect& GetImplementation(Dali::ShaderEffect& effect)
+{
+  DALI_ASSERT_ALWAYS(effect && "ShaderEffect handle is empty");
+
+  BaseObject& handle = effect.GetBaseObject();
+
+  return static_cast<Internal::ShaderEffect&>(handle);
+}
+
+inline const Internal::ShaderEffect& GetImplementation(const Dali::ShaderEffect& effect)
+{
+  DALI_ASSERT_ALWAYS(effect && "ShaderEffect handle is empty");
+
+  const BaseObject& handle = effect.GetBaseObject();
+
+  return static_cast<const Internal::ShaderEffect&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SHADER_EFFECT_H__
diff --git a/dali/internal/event/effects/shader-factory.cpp b/dali/internal/event/effects/shader-factory.cpp
new file mode 100644 (file)
index 0000000..64100a0
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/effects/shader-factory.h>
+
+// EXTERNAL INCLUDES
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/dali-core-version.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/devel-api/common/hash.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+
+// compile time generated shader strings
+#include "dali-shaders.h"
+
+namespace
+{
+const char* VERSION_SEPARATOR = "-";
+const char* SHADER_SUFFIX = ".dali-bin";
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * @brief Generates a filename for a shader binary based on the hash value passed in.
+ * @param[in] shaderHash A hash over shader sources.
+ * @param[out] filename A string to overwrite with the filename.
+ */
+void shaderBinaryFilename( size_t shaderHash, std::string& filename )
+{
+  std::stringstream binaryShaderFilenameBuilder( std::ios_base::out );
+  binaryShaderFilenameBuilder << CORE_MAJOR_VERSION << VERSION_SEPARATOR << CORE_MINOR_VERSION << VERSION_SEPARATOR << CORE_MICRO_VERSION << VERSION_SEPARATOR
+                              << shaderHash
+                              << SHADER_SUFFIX;
+  filename = binaryShaderFilenameBuilder.str();
+}
+
+}
+
+ShaderFactory::ShaderFactory()
+{
+}
+
+ShaderFactory::~ShaderFactory()
+{
+  // Let all the cached objects destroy themselves:
+  for( int i = 0, cacheSize = mShaderBinaryCache.Size(); i < cacheSize; ++i )
+  {
+    if( mShaderBinaryCache[i] )
+    {
+      mShaderBinaryCache[i]->Unreference();
+    }
+  }
+}
+
+ShaderDataPtr ShaderFactory::Load( const std::string& vertexSource, const std::string& fragmentSource, size_t& shaderHash )
+{
+  // Work out the filename for the binary that the glsl source will be compiled and linked to:
+  shaderHash = CalculateHash( vertexSource.c_str(), fragmentSource.c_str() );
+  std::string binaryShaderFilename;
+  shaderBinaryFilename( shaderHash, binaryShaderFilename );
+
+  ShaderDataPtr shaderData;
+
+  /// Check a cache of previously loaded shaders:
+  for( int i = 0, cacheSize = mShaderBinaryCache.Size(); i < cacheSize; ++i )
+  {
+    if( mShaderBinaryCache[i]->GetHashValue() == shaderHash )
+    {
+      shaderData = mShaderBinaryCache[i];
+
+      DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Mem cache hit on path: \"%s\"\n", binaryShaderFilename.c_str() );
+      break;
+    }
+  }
+
+  // If memory cache failed check the file system for a binary or return a source-only ShaderData:
+  if( shaderData.Get() == NULL )
+  {
+    // Allocate the structure that returns the loaded shader:
+    shaderData = new ShaderData( vertexSource, fragmentSource );
+    shaderData->SetHashValue( shaderHash );
+    shaderData->GetBuffer().Clear();
+
+    // Try to load the binary (this will fail if the shader source has never been compiled before):
+    ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+    Integration::PlatformAbstraction& platformAbstraction = tls.GetPlatformAbstraction();
+    const bool loaded = platformAbstraction.LoadShaderBinaryFile( binaryShaderFilename, shaderData->GetBuffer() );
+
+    if( loaded )
+    {
+      MemoryCacheInsert( *shaderData );
+    }
+
+    DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, loaded ?
+        "loaded on path: \"%s\"\n" :
+        "failed to load on path: \"%s\"\n",
+        binaryShaderFilename.c_str());
+  }
+
+  return shaderData;
+}
+
+void ShaderFactory::SaveBinary( Internal::ShaderDataPtr shaderData )
+{
+  // Save the binary to the file system:
+  std::string binaryShaderFilename;
+  shaderBinaryFilename( shaderData->GetHashValue(), binaryShaderFilename );
+
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  Integration::PlatformAbstraction& platformAbstraction = tls.GetPlatformAbstraction();
+  const bool saved = platformAbstraction.SaveShaderBinaryFile( binaryShaderFilename, &shaderData->GetBuffer()[0], shaderData->GetBufferSize() );
+
+  // Save the binary into to memory cache:
+  MemoryCacheInsert( *shaderData );
+
+  DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, saved ? "Saved to file: %s\n" : "Save to file failed: %s\n", binaryShaderFilename.c_str() );
+  if( saved ) {} // Avoid unused variable warning in release builds
+}
+
+void ShaderFactory::LoadDefaultShaders()
+{
+  mDefaultShader = ShaderEffect::New();
+
+  mDefaultShader->SendProgramMessage( ImageVertex, ImageFragment, false );
+}
+
+void ShaderFactory::MemoryCacheInsert( ShaderData& shaderData )
+{
+  DALI_ASSERT_DEBUG( shaderData.GetBufferSize() > 0 );
+
+  // Save the binary into to memory cache:
+  if( shaderData.GetBufferSize() > 0 )
+  {
+    mShaderBinaryCache.Reserve( mShaderBinaryCache.Size() + 1 ); // Make sure the push won't throw after we inc the ref count.
+    shaderData.Reference();
+    mShaderBinaryCache.PushBack( &shaderData );
+    DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "CACHED BINARY FOR HASH: %u\n", shaderData.GetHashValue() );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/effects/shader-factory.h b/dali/internal/event/effects/shader-factory.h
new file mode 100644 (file)
index 0000000..17a4204
--- /dev/null
@@ -0,0 +1,113 @@
+#ifndef __DALI_INTERNAL_SHADER_FACTORY_H__
+#define __DALI_INTERNAL_SHADER_FACTORY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/shader-saver.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ShaderData;
+typedef IntrusivePtr<ShaderData> ShaderDataPtr;
+
+/**
+ * ShaderFactory is an object which manages shader binary resource load requests,
+ * It triggers the load requests during core initialization and sends a message to the
+ * render manager with information about all the requested shader binaries.
+ */
+class ShaderFactory : public ShaderSaver
+{
+public:
+
+  /**
+   * Default constructor
+   */
+  ShaderFactory();
+
+  /**
+   * Destructor
+   */
+  virtual ~ShaderFactory();
+
+  /**
+   * @brief Looks for precompiled binary version of shader program in memory and file caches.
+   *
+   * Tries to load a binary version of a shader program identified by a hash over the two source
+   * files, checking an in-memory cache first.
+   * If the cache hits or the load succeeds, the buffer member of the returned ShaderData will
+   * contain a precompiled shader binary program which can be uploaded directly to GLES.
+   *
+   * @param [in] vertexSource   The vertex shader source code
+   * @param [in] fragmentSource The fragment shader source code
+   * @param [out] shaderHash    Hash key created from vertex and fragment shader code
+   * @return                    ShaderData containing the source and hash value, and additionally,
+   *                            a compiled shader program binary if one could be found, else an
+   *                            empty binary buffer cleared to size zero.
+   */
+  Internal::ShaderDataPtr Load( const std::string& vertexSource, const std::string& fragmentSource, size_t& shaderHash );
+
+  /**
+   * @brief Saves shader to memory cache and filesystem.
+   * This is called when a shader binary is ready to be saved to the memory cache file system.
+   * Shaders that pass through here become available to subsequent invocations of Load.
+   * @param[in] shader The data to be saved.
+   * @sa Load
+   */
+  virtual void SaveBinary( Internal::ShaderDataPtr shader );
+
+  /**
+   * Called during Core initialization to load the default shader.
+   */
+  void LoadDefaultShaders();
+
+private:
+
+  void MemoryCacheInsert( Internal::ShaderData& shaderData );
+
+  // Undefined
+  ShaderFactory( const ShaderFactory& );
+
+  // Undefined
+  ShaderFactory& operator=( const ShaderFactory& rhs );
+
+private:
+  ShaderEffectPtr                           mDefaultShader;
+  Dali::Vector< Internal::ShaderData* > mShaderBinaryCache; ///< Cache of pre-compiled shaders.
+
+}; // class ShaderFactory
+
+inline MessageBase* ShaderCompiledMessage( ShaderSaver& factory, Internal::ShaderDataPtr shaderData )
+{
+  return new MessageValue1< ShaderSaver, Internal::ShaderDataPtr >( &factory,
+                                                            &ShaderSaver::SaveBinary,
+                                                            shaderData );
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SHADER_FACTORY_H__
diff --git a/dali/internal/event/events/actor-gesture-data.cpp b/dali/internal/event/events/actor-gesture-data.cpp
new file mode 100644 (file)
index 0000000..c331c56
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/actor-gesture-data.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ActorGestureData::ActorGestureData()
+: gesturesRequired( Gesture::Type( 0 ) ),
+  panDetectors( NULL ),
+  pinchDetectors( NULL ),
+  longPressDetectors( NULL ),
+  tapDetectors( NULL )
+{
+}
+
+ActorGestureData::~ActorGestureData()
+{
+  delete panDetectors;
+  delete pinchDetectors;
+  delete longPressDetectors;
+  delete tapDetectors;
+}
+
+void ActorGestureData::AddGestureDetector( GestureDetector& detector )
+{
+  const Gesture::Type type( detector.GetType() );
+
+  GestureDetectorContainer*& containerPtr( GetContainerPtr( type ) );
+  if ( NULL == containerPtr )
+  {
+    containerPtr = new GestureDetectorContainer;
+  }
+  containerPtr->push_back( &detector );
+
+  gesturesRequired = Gesture::Type( gesturesRequired | type );
+}
+
+void ActorGestureData::RemoveGestureDetector( GestureDetector& detector )
+{
+  const Gesture::Type type( detector.GetType() );
+
+  GestureDetectorContainer*& containerPtr( GetContainerPtr( type ) );
+  DALI_ASSERT_DEBUG( containerPtr && "Container had not been created" );
+
+  GestureDetectorContainer& container( *containerPtr );
+  GestureDetectorContainer::iterator match( std::remove( container.begin(), container.end(), &detector ) );
+  DALI_ASSERT_DEBUG( match != container.end() && "Actor does not have the detector" );
+  container.erase( match, container.end() );
+
+  if ( container.empty() )
+  {
+    gesturesRequired = Gesture::Type( gesturesRequired & ~type );
+    delete containerPtr;
+    containerPtr = NULL;
+  }
+}
+
+GestureDetectorContainer& ActorGestureData::GetGestureDetectorContainer( Gesture::Type type )
+{
+  return *GetContainerPtr( type );
+}
+
+GestureDetectorContainer*& ActorGestureData::GetContainerPtr( Gesture::Type type )
+{
+  switch ( type )
+  {
+    case Gesture::Pan:
+    {
+      return panDetectors;
+    }
+
+    case Gesture::Pinch:
+    {
+      return pinchDetectors;
+    }
+
+    case Gesture::LongPress:
+    {
+      return longPressDetectors;
+    }
+
+    case Gesture::Tap:
+    {
+      return tapDetectors;
+    }
+  }
+
+  DALI_ASSERT_DEBUG( ! "Invalid Type" );
+  static GestureDetectorContainer* invalidType( NULL );
+  return invalidType;
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/events/actor-gesture-data.h b/dali/internal/event/events/actor-gesture-data.h
new file mode 100644 (file)
index 0000000..2742ef1
--- /dev/null
@@ -0,0 +1,104 @@
+#ifndef __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+#define __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Holds gesture specific data for an Actor
+ */
+class ActorGestureData
+{
+public:
+
+  /**
+   * Constructor
+   */
+  ActorGestureData();
+
+  /**
+   * Non-virtual Destructor
+   */
+  ~ActorGestureData();
+
+  /**
+   * Adds a gesture detector to the data so that the owning actor is aware that it requires this
+   * type of gesture.
+   * @param[in] detector The detector being added.
+   * @note A raw pointer to the detector is stored, so the detector MUST remove itself when it is
+   * destroyed using RemoveGestureDetector()
+   */
+  void AddGestureDetector( GestureDetector& detector );
+
+  /**
+   * Removes a previously added gesture detector from the data. If no more gesture detectors of
+   * this type are registered then the actor owning this data will no longer be hit-tested for that
+   * gesture.
+   * @param[in] detector The detector to remove.
+   */
+  void RemoveGestureDetector( GestureDetector& detector );
+
+  /**
+   * Queries whether the actor requires the gesture type.
+   * @param[in] type The gesture type.
+   * @return true if the gesture is required, false otherwise.
+   */
+  inline bool IsGestureRequred( Gesture::Type type ) const
+  {
+    return type & gesturesRequired;
+  }
+
+  /**
+   * Retrieve a reference to the detectors for the given type.
+   * @param[in] type The container type required
+   * @pre Ensure IsGestureRequired() is used to check if the container is actually available.
+   */
+  GestureDetectorContainer& GetGestureDetectorContainer( Gesture::Type type );
+
+private:
+
+  /**
+   * Helper to retrieve the appropriate container type.
+   * @param[in] type The container type required.
+   */
+  inline GestureDetectorContainer*& GetContainerPtr( Gesture::Type type );
+
+private:
+
+  Gesture::Type gesturesRequired; ///< Stores which gestures are required
+
+  GestureDetectorContainer* panDetectors;       ///< Pointer to a container of pan-detectors
+  GestureDetectorContainer* pinchDetectors;     ///< Pointer to a container of pinch-detectors
+  GestureDetectorContainer* longPressDetectors; ///< Pointer to a container of long-press-detectors
+  GestureDetectorContainer* tapDetectors;       ///< Pointer to a container of tap-detectors
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_GESTURE_DATA_H__
+
diff --git a/dali/internal/event/events/actor-observer.cpp b/dali/internal/event/events/actor-observer.cpp
new file mode 100644 (file)
index 0000000..42b9120
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/actor-observer.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_ACTOR_OBSERVER" );
+#endif // defined(DEBUG_ENABLED)
+}
+
+ActorObserver::ActorObserver()
+: mActor ( NULL ),
+  mActorDisconnected( false ),
+  mRemoveCallback( NULL )
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+ActorObserver::ActorObserver( CallbackBase* callback )
+: mActor ( NULL ),
+  mActorDisconnected( false ),
+  mRemoveCallback( callback )
+{
+}
+
+ActorObserver::~ActorObserver()
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+  SetActor( NULL );
+
+  delete mRemoveCallback;
+}
+
+Actor* ActorObserver::GetActor()
+{
+  return mActorDisconnected ? NULL : mActor;
+}
+
+void ActorObserver::SetActor( Actor* actor )
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+
+  if ( mActor != actor )
+  {
+    ResetActor();
+
+    mActor = actor;
+
+    if ( mActor )
+    {
+      mActor->AddObserver( *this );
+      DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Start Observing:            %p\n", mActor);
+    }
+  }
+
+  // Make sure this flag is unset (as we may have been disconnected if it's the same actor)
+  mActorDisconnected = false;
+}
+
+void ActorObserver::ResetActor()
+{
+  if ( mActor )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing:             %p\n", mActor);
+    mActor->RemoveObserver( *this );
+    mActor = NULL;
+    mActorDisconnected = false;
+  }
+}
+
+void ActorObserver::SceneObjectRemoved( Object& object )
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+
+  if ( mActor == &object )
+  {
+    if ( mRemoveCallback )
+    {
+//      CallbackBase::Execute( *mRemoveCallback, mActor );
+    }
+
+    // do not call object.RemoveObserver here, object is currently iterating through observers
+    mActorDisconnected = true;
+  }
+}
+
+void ActorObserver::ObjectDestroyed(Object& object)
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+
+  if ( mActor == &object )
+  {
+    DALI_LOG_INFO(gLogFilter, Debug::Verbose, "Stop Observing:             %p\n", mActor);
+    mActor = NULL;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/events/actor-observer.h b/dali/internal/event/events/actor-observer.h
new file mode 100644 (file)
index 0000000..bb9e5aa
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef __DALI_INTERNAL_ACTOR_OBSERVER_H__
+#define __DALI_INTERNAL_ACTOR_OBSERVER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/signals/callback.h>
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Actor;
+
+/**
+ * Stores an actor pointer and connects/disconnects to any required signals appropriately when set/unset.
+ */
+struct ActorObserver : public Object::Observer
+{
+public:
+
+  // Construction & Destruction
+
+  /**
+   * Constructor.
+   */
+  ActorObserver();
+
+  /**
+   * Constructor with a callback which is called when the observed actor is removed from the scene.
+   *
+   * The callback should have the following signature:
+   * @code
+   * void MyCallback( Actor* actor );
+   * @endcode
+   * Where actor is a pointer to the object that has been removed from the scene.
+   *
+   * @param[in]  callback  The callback to connect to.
+   *
+   * @note Ownership of callback is passed onto this class.
+   */
+  ActorObserver( CallbackBase* callback );
+
+  /**
+   * Non virtual destructor
+   */
+  ~ActorObserver();
+
+  // Methods
+
+  /**
+   * Return the stored Actor pointer.
+   * @return The Actor pointer.
+   */
+  Actor* GetActor();
+
+  /**
+   * Assignment operator.
+   * This disconnects the required signals from the currently set actor and connects to the required
+   * signals for the the actor specified (if set).
+   */
+  void SetActor( Actor* actor );
+
+  /**
+   * Resets the set actor and disconnects any connected signals.
+   */
+  void ResetActor();
+
+private:
+
+  // Undefined
+  ActorObserver( const ActorObserver& );
+  ActorObserver& operator=( const ActorObserver& );
+
+private:
+
+  /**
+   * This will never get called as we do not observe objects that have not been added to the scene.
+   * @param[in] object The object object.
+   * @see Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded(Object& object) { }
+
+  /**
+   * This will be called when the actor is removed from the stage, we should clear and stop
+   * observing it.
+   * @param[in] object The object object.
+   * @see Object::Observer::SceneObjectRemoved()
+   */
+  virtual void SceneObjectRemoved(Object& object);
+
+  /**
+   * This will be called when the actor is destroyed. We should clear the actor.
+   * No need to stop observing as the object is being destroyed anyway.
+   * @see Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed(Object& object);
+
+private:
+  Actor* mActor;                 ///< Raw pointer to an Actor.
+  bool  mActorDisconnected;      ///< Indicates whether the actor has been disconnected from the scene
+  CallbackBase* mRemoveCallback; ///< Callback to call when the observed actor is removed from the scene
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ACTOR_OBSERVER_H__
+
diff --git a/dali/internal/event/events/event-processor.cpp b/dali/internal/event/events/event-processor.cpp
new file mode 100644 (file)
index 0000000..560b48a
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/event-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/event.h>
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/integration-api/events/key-event-integ.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/integration-api/events/pinch-gesture-event.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/integration-api/events/long-press-gesture-event.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/common/core-impl.h>
+#include <dali/internal/event/common/notification-manager.h>
+
+using Dali::Integration::Event;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+static const std::size_t MAX_MESSAGE_SIZE = std::max( sizeof(Integration::TouchEvent),
+                                                      std::max( sizeof(Integration::KeyEvent),
+                                                                std::max( sizeof(Integration::WheelEvent), sizeof(Integration::GestureEvent) ) ) );
+
+static const std::size_t INITIAL_MIN_CAPACITY = 4;
+
+static const std::size_t INITIAL_BUFFER_SIZE = MAX_MESSAGE_SIZE * INITIAL_MIN_CAPACITY;
+
+} // unnamed namespace
+
+EventProcessor::EventProcessor(Stage& stage, NotificationManager& /* notificationManager */, GestureEventProcessor& gestureEventProcessor)
+: mTouchEventProcessor(stage),
+  mHoverEventProcessor(stage),
+  mGestureEventProcessor(gestureEventProcessor),
+  mKeyEventProcessor(stage),
+  mWheelEventProcessor(stage),
+  mEventQueue0( INITIAL_BUFFER_SIZE ),
+  mEventQueue1( INITIAL_BUFFER_SIZE ),
+  mCurrentEventQueue( &mEventQueue0 )
+{
+}
+
+EventProcessor::~EventProcessor()
+{
+  for( MessageBuffer::Iterator iter = mEventQueue0.Begin(); iter.IsValid(); iter.Next() )
+  {
+    // Call virtual destructor explictly; since delete will not be called after placement new
+    Event* event = reinterpret_cast< Event* >( iter.Get() );
+    event->~Event();
+  }
+
+  for( MessageBuffer::Iterator iter = mEventQueue1.Begin(); iter.IsValid(); iter.Next() )
+  {
+    // Call virtual destructor explictly; since delete will not be called after placement new
+    Event* event = reinterpret_cast< Event* >( iter.Get() );
+    event->~Event();
+  }
+}
+
+void EventProcessor::QueueEvent( const Event& event )
+{
+  switch( event.type )
+  {
+    case Event::Touch:
+    {
+      typedef Integration::TouchEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Event::Hover:
+    {
+      typedef Integration::HoverEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Event::Key:
+    {
+      typedef Integration::KeyEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Event::Wheel:
+    {
+      typedef Integration::WheelEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Event::Gesture:
+    {
+      QueueGestureEvent( static_cast<const Integration::GestureEvent&>(event) );
+      break;
+    }
+
+  }
+}
+
+void EventProcessor::QueueGestureEvent(const Integration::GestureEvent& event)
+{
+  switch( event.gestureType )
+  {
+    case Gesture::Pinch:
+    {
+      typedef Integration::PinchGestureEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Gesture::Pan:
+    {
+      typedef Integration::PanGestureEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      typedef Integration::TapGestureEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+
+    case Gesture::LongPress:
+    {
+      typedef Integration::LongPressGestureEvent DerivedType;
+
+      // Reserve some memory inside the message queue
+      unsigned int* slot = mCurrentEventQueue->ReserveMessageSlot( sizeof( DerivedType ) );
+
+      // Construct message in the message queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( static_cast<const DerivedType&>(event) );
+
+      break;
+    }
+  }
+}
+
+void EventProcessor::ProcessEvents()
+{
+  MessageBuffer* queueToProcess = mCurrentEventQueue;
+
+  // Switch current queue; events can be added safely while iterating through the other queue.
+  mCurrentEventQueue = (&mEventQueue0 == mCurrentEventQueue) ? &mEventQueue1 : &mEventQueue0;
+
+  for( MessageBuffer::Iterator iter = queueToProcess->Begin(); iter.IsValid(); iter.Next() )
+  {
+    Event* event = reinterpret_cast< Event* >( iter.Get() );
+
+    switch( event->type )
+    {
+      case Event::Touch:
+      {
+        mTouchEventProcessor.ProcessTouchEvent( static_cast<const Integration::TouchEvent&>(*event) );
+        break;
+      }
+
+      case Event::Hover:
+      {
+        mHoverEventProcessor.ProcessHoverEvent( static_cast<const Integration::HoverEvent&>(*event) );
+        break;
+      }
+
+      case Event::Key:
+      {
+        mKeyEventProcessor.ProcessKeyEvent( static_cast<const Integration::KeyEvent&>(*event) );
+        break;
+      }
+
+      case Event::Wheel:
+      {
+        mWheelEventProcessor.ProcessWheelEvent( static_cast<const Integration::WheelEvent&>(*event) );
+        break;
+      }
+
+      case Event::Gesture:
+      {
+        mGestureEventProcessor.ProcessGestureEvent( static_cast<const Integration::GestureEvent&>(*event) );
+        break;
+      }
+
+    }
+    // Call virtual destructor explictly; since delete will not be called after placement new
+    event->~Event();
+  }
+
+  queueToProcess->Reset();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/event-processor.h b/dali/internal/event/events/event-processor.h
new file mode 100644 (file)
index 0000000..bc5300e
--- /dev/null
@@ -0,0 +1,107 @@
+#ifndef __DALI_INTERNAL_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/touch-event-processor.h>
+#include <dali/internal/event/events/hover-event-processor.h>
+#include <dali/internal/event/events/key-event-processor.h>
+#include <dali/internal/event/events/wheel-event-processor.h>
+#include <dali/internal/common/message-buffer.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+struct Event;
+struct GestureEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+class GestureEventProcessor;
+class NotificationManager;
+
+/**
+ * The EventProcessor processes any events that are received by Dali.  Such events include
+ * touch events, key events, wheel events, and notification events.
+ *
+ * When the EventProcessor receives an event, it determines its type and passes it on to the
+ * appropriate processor.
+ */
+class EventProcessor
+{
+public:
+
+  /**
+   * Constructor
+   * @param[in] stage                  The stage.
+   * @param[in] notificationManager    The Notification Manager.
+   * @param[in] gestureEventProcessor  The gesture event processor.
+   */
+  EventProcessor(Stage& stage, NotificationManager& notificationManager, GestureEventProcessor& gestureEventProcessor);
+
+  /**
+   * Destructor
+   */
+  virtual ~EventProcessor();
+
+public:
+
+  /**
+   * This function is called by Core when an event is queued.
+   * @param[in] event A event to queue.
+   */
+  void QueueEvent( const Integration::Event& event );
+
+  /**
+   * This function is called by Core when events are processed.
+   */
+  void ProcessEvents();
+
+private:
+
+  /**
+   * Helper for QueueEvent()
+   */
+  void QueueGestureEvent(const Integration::GestureEvent& event);
+
+private:
+
+  TouchEventProcessor      mTouchEventProcessor;        ///< Processes touch events.
+  HoverEventProcessor      mHoverEventProcessor;        ///< Processes hover events.
+  GestureEventProcessor&   mGestureEventProcessor;      ///< Processes gesture events.
+  KeyEventProcessor        mKeyEventProcessor;          ///< Processes key events.
+  WheelEventProcessor      mWheelEventProcessor;        ///< Processes wheel events.
+
+  // Allow messages to be added safely to one queue, while processing (iterating through) the second queue.
+  MessageBuffer mEventQueue0;        ///< An event queue.
+  MessageBuffer mEventQueue1;        ///< Another event queue.
+  MessageBuffer* mCurrentEventQueue; ///< QueueEvent() will queue here.
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_EVENT_PROCESSOR_H__
+
diff --git a/dali/internal/event/events/gesture-detector-impl.cpp b/dali/internal/event/events/gesture-detector-impl.cpp
new file mode 100644 (file)
index 0000000..b3ef831
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+GestureDetector::GestureDetector(Gesture::Type type)
+: mType(type),
+  mGestureEventProcessor(ThreadLocalStorage::Get().GetGestureEventProcessor())
+{
+}
+
+GestureDetector::~GestureDetector()
+{
+  if ( !mAttachedActors.empty() )
+  {
+    for ( GestureDetectorActorContainer::iterator iter = mAttachedActors.begin(), endIter = mAttachedActors.end(); iter != endIter; ++iter )
+    {
+      Actor* actor( *iter );
+      actor->RemoveObserver( *this );
+      actor->GetGestureData().RemoveGestureDetector( *this );
+    }
+
+    mAttachedActors.clear();
+
+    // Guard to allow handle destruction after Core has been destroyed
+    if ( Stage::IsInstalled() )
+    {
+      mGestureEventProcessor.RemoveGestureDetector( this );
+    }
+  }
+}
+
+void GestureDetector::Attach(Actor& actor)
+{
+  if ( !IsAttached(actor) )
+  {
+    // Register with EventProcessor if first actor being added
+    if ( mAttachedActors.empty() )
+    {
+      mGestureEventProcessor.AddGestureDetector(this);
+    }
+
+    mAttachedActors.push_back(&actor);
+
+    // We need to observe the actor's destruction
+    actor.AddObserver(*this);
+
+    // Add the detector to the actor (so the actor knows it requires this gesture when going through hit-test algorithm)
+    actor.GetGestureData().AddGestureDetector( *this );
+
+    // Notification for derived classes
+    OnActorAttach(actor);
+  }
+}
+
+void GestureDetector::Detach(Actor& actor)
+{
+  if ( !mAttachedActors.empty() )
+  {
+    GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &actor);
+
+    if ( match != mAttachedActors.end() )
+    {
+      // We no longer need to observe the actor's destruction
+      actor.RemoveObserver(*this);
+
+      // Remove detector from actor-gesture-data
+      actor.GetGestureData().RemoveGestureDetector( *this );
+
+      mAttachedActors.erase(match);
+
+      // Notification for derived classes
+      OnActorDetach(actor);
+
+      // Unregister from gesture event processor if we do not have any actors
+      if ( mAttachedActors.empty() )
+      {
+        mGestureEventProcessor.RemoveGestureDetector(this);
+      }
+    }
+  }
+}
+
+void GestureDetector::DetachAll()
+{
+  if ( !mAttachedActors.empty() )
+  {
+    GestureDetectorActorContainer attachedActors(mAttachedActors);
+
+    // Clear mAttachedActors before we call OnActorDetach in case derived classes call a method which manipulates mAttachedActors.
+    mAttachedActors.clear();
+
+    for ( GestureDetectorActorContainer::iterator iter = attachedActors.begin(), endIter = attachedActors.end(); iter != endIter; ++iter )
+    {
+      Actor* actor(*iter);
+
+      // We no longer need to observe the actor's destruction
+      actor->RemoveObserver(*this);
+
+      // Remove detector from actor-gesture-data
+      actor->GetGestureData().RemoveGestureDetector( *this );
+
+      // Notification for derived classes
+      OnActorDetach(*actor);
+    }
+
+    // Unregister from gesture event processor
+    mGestureEventProcessor.RemoveGestureDetector(this);
+  }
+}
+
+size_t GestureDetector::GetAttachedActorCount() const
+{
+  return mAttachedActors.size();
+}
+
+Dali::Actor GestureDetector::GetAttachedActor(size_t index) const
+{
+  Dali::Actor actor;
+
+  if( index < mAttachedActors.size() )
+  {
+    actor = Dali::Actor( mAttachedActors[index] );
+  }
+
+  return actor;
+}
+
+bool GestureDetector::IsAttached(Actor& actor) const
+{
+  return find(mAttachedActors.begin(), mAttachedActors.end(), &actor) != mAttachedActors.end();
+}
+
+void GestureDetector::ObjectDestroyed(Object& object)
+{
+  if ( !mAttachedActors.empty() )
+  {
+    GestureDetectorActorContainer::iterator match = find(mAttachedActors.begin(), mAttachedActors.end(), &object);
+
+    if ( match != mAttachedActors.end() )
+    {
+      mAttachedActors.erase(match);
+
+      // Notification for derived classes
+      OnActorDestroyed(object);
+
+      // Unregister from gesture event processor if we do not have any actors
+      if ( mAttachedActors.empty() )
+      {
+        mGestureEventProcessor.RemoveGestureDetector(this);
+      }
+    }
+  }
+}
+
+unsigned int GestureDetector::GetDefaultPropertyCount() const
+{
+  return 0;
+}
+
+void GestureDetector::GetDefaultPropertyIndices( Property::IndexContainer& ) const
+{
+}
+
+const char* GestureDetector::GetDefaultPropertyName( Property::Index index ) const
+{
+  return NULL;
+}
+
+Property::Index GestureDetector::GetDefaultPropertyIndex(const std::string& name) const
+{
+  return 0;
+}
+
+bool GestureDetector::IsDefaultPropertyWritable(Property::Index index) const
+{
+  return false;
+}
+
+bool GestureDetector::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  return false;
+}
+
+bool GestureDetector::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return false;
+}
+
+Property::Type GestureDetector::GetDefaultPropertyType(Property::Index index) const
+{
+  return Property::NONE;
+}
+
+void GestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  // None of our properties should be settable from Public API
+}
+
+Property::Value GestureDetector::GetDefaultProperty(Property::Index index) const
+{
+  return Property::Value();
+}
+
+const SceneGraph::PropertyOwner* GestureDetector::GetSceneObject() const
+{
+  return NULL;
+}
+
+const SceneGraph::PropertyBase* GestureDetector::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  return NULL;
+}
+
+const PropertyInputImpl* GestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  return NULL;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/gesture-detector-impl.h b/dali/internal/event/events/gesture-detector-impl.h
new file mode 100644 (file)
index 0000000..5168a4b
--- /dev/null
@@ -0,0 +1,266 @@
+#ifndef __DALI_INTERNAL_GESTURE_DETECTOR_H__
+#define __DALI_INTERNAL_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/signals/slot-delegate.h>
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+struct GestureEvent;
+}
+
+namespace Internal
+{
+
+class GestureDetector;
+class GestureEventProcessor;
+
+typedef IntrusivePtr<GestureDetector> GestureDetectorPtr;
+typedef std::vector<GestureDetector*> GestureDetectorContainer;
+typedef std::vector<Actor*> GestureDetectorActorContainer;
+
+/**
+ * This is a type trait that should be used by deriving gesture detectors for their container type.
+ */
+template< typename Detector >
+struct DerivedGestureDetectorContainer
+{
+  typedef std::vector<Detector*> type;
+};
+
+/**
+ * @copydoc Dali::GestureDetector
+ */
+class GestureDetector : public Object, public Object::Observer
+{
+public:
+
+  /**
+   * @copydoc Dali::GestureDetector::Attach()
+   */
+  void Attach(Actor& actor);
+
+  /**
+   * @copydoc Dali::GestureDetector::Detach()
+   */
+  void Detach(Actor& actor);
+
+  /**
+   * @copydoc Dali::GestureDetector::DetachAll()
+   */
+  void DetachAll();
+
+  /**
+   * @copydoc Dali::GestureDetector::GetAttachedActorCount() const
+   */
+  size_t GetAttachedActorCount() const;
+
+  /**
+   * @copydoc Dali::GestureDetector::GetAttachedActor() const
+   */
+  Dali::Actor GetAttachedActor(size_t index) const;
+
+  /**
+   * Returns a const reference to the container of attached actor pointers.
+   * @return A const reference to the attached internal actors.
+   */
+  const GestureDetectorActorContainer& GetAttachedActorPointers() const
+  {
+    return mAttachedActors;
+  }
+
+  /**
+   * Retrieves the type of GestureDetector
+   * @return The GestureDetector Type
+   */
+  Gesture::Type GetType() const
+  {
+    return mType;
+  }
+
+  /**
+   * Checks if the specified actor is still attached.
+   * @param[in]  actor  The actor to check.
+   * @return true, if the actor is attached, false otherwise.
+   */
+  bool IsAttached(Actor& actor) const;
+
+protected: // Creation & Destruction
+
+  /**
+   * Construct a new GestureDetector.
+   */
+  GestureDetector(Gesture::Type mType);
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~GestureDetector();
+
+private:
+
+  // Undefined
+  GestureDetector(const GestureDetector&);
+
+  // Undefined
+  GestureDetector& operator=(const GestureDetector& rhs);
+
+  /**
+   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded(Object& object) {}
+
+  /**
+   * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectRemoved(Object& object) {}
+
+  /**
+   * @copydoc Dali::Internal::Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed(Object& object);
+
+  /**
+   * For use in derived classes, called after an actor is attached.
+   * @param[in]  actor  The actor that is being attached.
+   */
+  virtual void OnActorAttach(Actor& actor) = 0;
+
+  /**
+   * For use in derived classes, called after an actor is detached.
+   * @param[in] actor The actor that is being detached.
+   */
+  virtual void OnActorDetach(Actor& actor) = 0;
+
+  /**
+   * For use in derived classes, called when an attached actor is destroyed.
+   * @param[in] object The object (Actor's base class) that has been destroyed.
+   * @note Derived classes should not call any Actor specific APIs in this method as the Actor's
+   *       destructor would have already been called.
+   */
+  virtual void OnActorDestroyed(Object& object) = 0;
+
+private: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+protected:
+
+  Gesture::Type                 mType;                  ///< The gesture detector will detect this type of gesture.
+  GestureDetectorActorContainer mAttachedActors;        ///< Object::Observer is used to provide weak-pointer behaviour
+  GestureEventProcessor&        mGestureEventProcessor; ///< A reference to the gesture event processor.
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::GestureDetector& GetImplementation(Dali::GestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "GestureDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::GestureDetector&>(handle);
+}
+
+inline const Internal::GestureDetector& GetImplementation(const Dali::GestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "GestureDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::GestureDetector&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_GESTURE_DETECTOR_H__
diff --git a/dali/internal/event/events/gesture-event-processor.cpp b/dali/internal/event/events/gesture-event-processor.cpp
new file mode 100644 (file)
index 0000000..6ca2c1d
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/gesture-event-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/events/gesture-event.h>
+#include <dali/integration-api/events/long-press-gesture-event.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/integration-api/events/pinch-gesture-event.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/integration-api/render-controller.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/public-api/events/pan-gesture.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+GestureEventProcessor::GestureEventProcessor(Stage& stage, Integration::GestureManager& gestureManager, Integration::RenderController& renderController)
+: mStage(stage),
+  mGestureManager(gestureManager),
+  mLongPressGestureProcessor(stage, gestureManager),
+  mPanGestureProcessor(stage, gestureManager),
+  mPinchGestureProcessor(stage, gestureManager),
+  mTapGestureProcessor(stage, gestureManager),
+  mRenderController(renderController),
+  mUpdateRequired( false )
+{
+}
+
+GestureEventProcessor::~GestureEventProcessor()
+{
+}
+
+void GestureEventProcessor::ProcessGestureEvent(const Integration::GestureEvent& event)
+{
+  if( Gesture::Started == event.state || Gesture::Continuing == event.state )
+  {
+    SetUpdateRequired();
+  }
+
+  switch(event.gestureType)
+  {
+    case Gesture::LongPress:
+      mLongPressGestureProcessor.Process(static_cast<const Integration::LongPressGestureEvent&>(event));
+      break;
+
+    case Gesture::Pan:
+      mPanGestureProcessor.Process(static_cast<const Integration::PanGestureEvent&>(event));
+      break;
+
+    case Gesture::Pinch:
+      mPinchGestureProcessor.Process(static_cast<const Integration::PinchGestureEvent&>(event));
+      break;
+
+    case Gesture::Tap:
+      mTapGestureProcessor.Process(static_cast<const Integration::TapGestureEvent&>(event));
+      break;
+  }
+}
+
+void GestureEventProcessor::AddGestureDetector(GestureDetector* gestureDetector)
+{
+  switch (gestureDetector->GetType())
+  {
+    case Gesture::LongPress:
+    {
+      LongPressGestureDetector* longPress = static_cast<LongPressGestureDetector*>(gestureDetector);
+      mLongPressGestureProcessor.AddGestureDetector(longPress);
+      break;
+    }
+
+    case Gesture::Pan:
+    {
+      PanGestureDetector* pan = static_cast<PanGestureDetector*>(gestureDetector);
+      mPanGestureProcessor.AddGestureDetector(pan);
+      break;
+    }
+
+    case Gesture::Pinch:
+    {
+      PinchGestureDetector* pinch = static_cast<PinchGestureDetector*>(gestureDetector);
+      mPinchGestureProcessor.AddGestureDetector(pinch);
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      TapGestureDetector* tap = static_cast<TapGestureDetector*>(gestureDetector);
+      mTapGestureProcessor.AddGestureDetector(tap);
+      break;
+    }
+  }
+}
+
+void GestureEventProcessor::RemoveGestureDetector(GestureDetector* gestureDetector)
+{
+  switch (gestureDetector->GetType())
+  {
+    case Gesture::LongPress:
+    {
+      LongPressGestureDetector* longPress = static_cast<LongPressGestureDetector*>(gestureDetector);
+      mLongPressGestureProcessor.RemoveGestureDetector(longPress);
+      break;
+    }
+
+    case Gesture::Pan:
+    {
+      PanGestureDetector* pan = static_cast<PanGestureDetector*>(gestureDetector);
+      mPanGestureProcessor.RemoveGestureDetector(pan);
+      break;
+    }
+
+    case Gesture::Pinch:
+    {
+      PinchGestureDetector* pinch = static_cast<PinchGestureDetector*>(gestureDetector);
+      mPinchGestureProcessor.RemoveGestureDetector(pinch);
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      TapGestureDetector* tap = static_cast<TapGestureDetector*>(gestureDetector);
+      mTapGestureProcessor.RemoveGestureDetector(tap);
+      break;
+    }
+  }
+}
+
+void GestureEventProcessor::GestureDetectorUpdated(GestureDetector* gestureDetector)
+{
+  switch (gestureDetector->GetType())
+  {
+    case Gesture::LongPress:
+    {
+      LongPressGestureDetector* longPress = static_cast<LongPressGestureDetector*>(gestureDetector);
+      mLongPressGestureProcessor.GestureDetectorUpdated(longPress);
+      break;
+    }
+
+    case Gesture::Pan:
+    {
+      PanGestureDetector* pan = static_cast<PanGestureDetector*>(gestureDetector);
+      mPanGestureProcessor.GestureDetectorUpdated(pan);
+      break;
+    }
+
+    case Gesture::Pinch:
+    {
+      PinchGestureDetector* pinch = static_cast<PinchGestureDetector*>(gestureDetector);
+      mPinchGestureProcessor.GestureDetectorUpdated(pinch);
+      break;
+    }
+
+    case Gesture::Tap:
+    {
+      TapGestureDetector* tap = static_cast<TapGestureDetector*>(gestureDetector);
+      mTapGestureProcessor.GestureDetectorUpdated(tap);
+      break;
+    }
+  }
+}
+
+void GestureEventProcessor::SetUpdateRequired()
+{
+  mUpdateRequired = true;
+}
+
+void GestureEventProcessor::SetGestureProperties( const Gesture& gesture )
+{
+  if( Gesture::Started == gesture.state || Gesture::Continuing == gesture.state )
+  {
+    SetUpdateRequired();
+
+    // We may not be updating so we need to ask the render controller for an update.
+    mRenderController.RequestUpdate();
+  }
+
+  switch ( gesture.type )
+  {
+    case Gesture::Pan:
+    {
+      const PanGesture& pan = static_cast< const PanGesture& >( gesture );
+      mPanGestureProcessor.SetPanGestureProperties( pan );
+      break;
+    }
+
+    case Gesture::LongPress:
+    case Gesture::Pinch:
+    case Gesture::Tap:
+    {
+      DALI_ASSERT_DEBUG( false && "Gesture type does not have scene object\n" );
+      break;
+    }
+  }
+}
+
+bool GestureEventProcessor::NeedsUpdate()
+{
+  bool updateRequired( mUpdateRequired );
+
+  mUpdateRequired = false;
+
+  return updateRequired;
+}
+
+void GestureEventProcessor::EnablePanGestureProfiling()
+{
+  mPanGestureProcessor.EnableProfiling();
+}
+
+void GestureEventProcessor::SetPanGesturePredictionMode(int mode)
+{
+  mPanGestureProcessor.SetPredictionMode(mode);
+}
+
+void GestureEventProcessor::SetPanGesturePredictionAmount( unsigned int amount )
+{
+  mPanGestureProcessor.SetPredictionAmount(amount);
+}
+
+void GestureEventProcessor::SetPanGestureMaximumPredictionAmount( unsigned int amount )
+{
+  mPanGestureProcessor.SetMaximumPredictionAmount(amount);
+}
+
+void GestureEventProcessor::SetPanGestureMinimumPredictionAmount( unsigned int amount )
+{
+  mPanGestureProcessor.SetMinimumPredictionAmount(amount);
+}
+
+void GestureEventProcessor::SetPanGesturePredictionAmountAdjustment( unsigned int amount )
+{
+  mPanGestureProcessor.SetPredictionAmountAdjustment(amount);
+}
+
+void GestureEventProcessor::SetPanGestureSmoothingMode(int mode)
+{
+  mPanGestureProcessor.SetSmoothingMode(mode);
+}
+
+void GestureEventProcessor::SetPanGestureSmoothingAmount( float amount )
+{
+  mPanGestureProcessor.SetSmoothingAmount(amount);
+}
+
+void GestureEventProcessor::SetPanGestureUseActualTimes( bool value )
+{
+  mPanGestureProcessor.SetUseActualTimes( value );
+}
+
+void GestureEventProcessor::SetPanGestureInterpolationTimeRange( int value )
+{
+  mPanGestureProcessor.SetInterpolationTimeRange( value );
+}
+
+void GestureEventProcessor::SetPanGestureScalarOnlyPredictionEnabled( bool value )
+{
+  mPanGestureProcessor.SetScalarOnlyPredictionEnabled( value );
+}
+
+void GestureEventProcessor::SetPanGestureTwoPointPredictionEnabled( bool value )
+{
+  mPanGestureProcessor.SetTwoPointPredictionEnabled( value );
+}
+
+void GestureEventProcessor::SetPanGestureTwoPointInterpolatePastTime( int value )
+{
+  mPanGestureProcessor.SetTwoPointInterpolatePastTime( value );
+}
+
+void GestureEventProcessor::SetPanGestureTwoPointVelocityBias( float value )
+{
+  mPanGestureProcessor.SetTwoPointVelocityBias( value );
+}
+
+void GestureEventProcessor::SetPanGestureTwoPointAccelerationBias( float value )
+{
+  mPanGestureProcessor.SetTwoPointAccelerationBias( value );
+}
+
+void GestureEventProcessor::SetPanGestureMultitapSmoothingRange( int value )
+{
+  mPanGestureProcessor.SetMultitapSmoothingRange( value );
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/gesture-event-processor.h b/dali/internal/event/events/gesture-event-processor.h
new file mode 100644 (file)
index 0000000..c12fa36
--- /dev/null
@@ -0,0 +1,258 @@
+#ifndef __DALI_INTERNAL_GESTURE_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_GESTURE_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/internal/event/events/gesture-detector-impl.h>
+#include <dali/internal/event/events/long-press-gesture-processor.h>
+#include <dali/internal/event/events/pan-gesture-processor.h>
+#include <dali/internal/event/events/pinch-gesture-processor.h>
+#include <dali/internal/event/events/tap-gesture-processor.h>
+
+namespace Dali
+{
+
+struct Gesture;
+
+namespace Integration
+{
+struct GestureEvent;
+class GestureManager;
+class RenderController;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+/**
+ * Gesture Event Processing:
+ *
+ * The GestureEventProcessor determines what type of gesture event we have received and sends it to
+ * the appropriate gesture processor for processing.
+ */
+class GestureEventProcessor
+{
+public:
+
+  /**
+   * Create a gesture event processor.
+   * @param[in] stage The stage.
+   * @param[in] gestureManager The gesture manager
+   * @param[in] renderController The render controller
+   */
+  GestureEventProcessor(Stage& stage, Integration::GestureManager& gestureManager, Integration::RenderController& renderController);
+
+  /**
+   * Non-virtual destructor; GestureProcessor is not a base class
+   */
+  ~GestureEventProcessor();
+
+public: // To be called by EventProcessor
+
+  /**
+   * This function is called by Core whenever a gesture event occurs.
+   * @param[in] event The event that has occurred.
+   */
+  void ProcessGestureEvent(const Integration::GestureEvent& event);
+
+public: // To be called by gesture detectors
+
+  /**
+   * This method adds the specified gesture detector to the relevant gesture processor.
+   * @param[in]  gestureDetector  The gesture detector to add
+   */
+  void AddGestureDetector(GestureDetector* gestureDetector);
+
+  /**
+   * This method removes the specified gesture detector from the relevant gesture processor.
+   * @param[in]  gestureDetector  The gesture detector to remove.
+   */
+  void RemoveGestureDetector(GestureDetector* gestureDetector);
+
+  /**
+   * This method informs the appropriate processor that the gesture detector has been updated.
+   * @param[in]  gestureDetector  The gesture detector that has been updated.
+   */
+  void GestureDetectorUpdated(GestureDetector* gestureDetector);
+
+  /**
+   * This method is called by GestureDetectors on Started or Continue state events.
+   * Status is queried and reset by Core in ProcessEvents
+   */
+  void SetUpdateRequired();
+
+  /**
+   * Called by GestureDetectors to set the gesture properties in the update thread.
+   * @param[in]  gesture  The gesture whose values will be used in the Update object.
+   * @note If we are in the middle of processing the gesture being set, then this call is ignored.
+   */
+  void SetGestureProperties( const Gesture& gesture );
+
+public: // Called by Core
+
+  /**
+   * Returns true if any GestureDetector requires a Core::Update. Clears
+   * the state flag after reading.
+   *
+   * @return true if any GestureDetector requires a Core::Update
+   */
+  bool NeedsUpdate();
+
+  /**
+   * Called to provide pan-gesture profiling information.
+   */
+  void EnablePanGestureProfiling();
+
+  /**
+   * @brief Called to set how pan gestures predict input
+   *
+   * @param[in] mode The prediction mode to use
+   */
+  void SetPanGesturePredictionMode( int mode );
+
+  /**
+   * @brief Sets the prediction amount of the pan gesture
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPanGesturePredictionAmount( unsigned int amount );
+
+  /**
+   * @brief Sets the upper bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPanGestureMaximumPredictionAmount( unsigned int amount );
+
+  /**
+   * @brief Sets the lower bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPanGestureMinimumPredictionAmount( unsigned int amount );
+
+  /**
+   * @brief Sets the prediction amount to adjust when the pan velocity is changed.
+   * If the pan velocity is accelerating, the prediction amount will be increased
+   * by the specified amount until it reaches the upper bound. If the pan velocity
+   * is decelerating, the prediction amount will be decreased by the specified amount
+   * until it reaches the lower bound.
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPanGesturePredictionAmountAdjustment( unsigned int amount );
+
+  /**
+   * @brief Called to set how pan gestures smooth input
+   *
+   * @param[in] mode The smoothing mode to use
+   */
+  void SetPanGestureSmoothingMode( int mode );
+
+  /**
+   * @brief Sets the prediction amount of the pan gesture
+   *
+   * @param[in] amount The smoothing amount [0.0f,1.0f] - 0.0f would be no smoothing, 1.0f maximum smoothing
+   */
+  void SetPanGestureSmoothingAmount( float amount );
+
+  /*
+   * @brief Sets whether to use actual times of the real gesture and frames or not.
+   *
+   * @param[in] value True = use actual times, False = use perfect values
+   */
+  void SetPanGestureUseActualTimes( bool value );
+
+  /**
+   * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
+   *
+   * @param[in] value Time range in ms
+   */
+  void SetPanGestureInterpolationTimeRange( int value );
+
+  /**
+   * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
+   *
+   * @param[in] value True = use scalar prediction only
+   */
+  void SetPanGestureScalarOnlyPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
+   *
+   * @param[in] value True = use two point prediction
+   */
+  void SetPanGestureTwoPointPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetPanGestureTwoPointInterpolatePastTime( int value );
+
+  /**
+   * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetPanGestureTwoPointVelocityBias( float value );
+
+  /**
+   * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetPanGestureTwoPointAccelerationBias( float value );
+
+  /**
+   * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetPanGestureMultitapSmoothingRange( int value );
+
+private:
+
+  // Undefined
+  GestureEventProcessor(const GestureEventProcessor&);
+  GestureEventProcessor& operator=(const GestureEventProcessor& rhs);
+
+private:
+
+  Stage& mStage;
+  Integration::GestureManager& mGestureManager;
+
+  LongPressGestureProcessor mLongPressGestureProcessor;
+  PanGestureProcessor mPanGestureProcessor;
+  PinchGestureProcessor mPinchGestureProcessor;
+  TapGestureProcessor mTapGestureProcessor;
+  Integration::RenderController& mRenderController;
+
+  bool mUpdateRequired;     ///< set to true by gesture detectors if they require a Core::Update
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_GESTURE_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/gesture-processor.cpp b/dali/internal/event/events/gesture-processor.cpp
new file mode 100644 (file)
index 0000000..a196d1a
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/gesture-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/actor-gesture-data.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * Functor to check whether an actor requires a particular gesture or not
+ */
+struct GestureHitTestCheck : public HitTestAlgorithm::HitTestInterface
+{
+  GestureHitTestCheck( Gesture::Type type )
+  : mType( type )
+  {
+  }
+
+  virtual bool IsActorHittable( Actor* actor )
+  {
+    return actor->IsGestureRequred( mType ) && // Does the Application or derived actor type require the gesture?
+           actor->IsHittable();                // Is actor sensitive, visible and on the scene?
+  }
+
+  virtual bool DescendActorHierarchy( Actor* actor )
+  {
+    return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+           actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
+  }
+
+  virtual bool DoesLayerConsumeHit( Layer* layer )
+  {
+    return layer->IsTouchConsumed();
+  }
+
+  Gesture::Type mType;
+};
+
+} // unnamed namespace
+
+
+GestureProcessor::GestureProcessor( Gesture::Type type )
+: mType( type ),
+  mCurrentGesturedActor( NULL ),
+  mGesturedActorDisconnected( false )
+{
+}
+
+GestureProcessor::~GestureProcessor()
+{
+  ResetActor();
+}
+
+void GestureProcessor::GetGesturedActor( Actor*& actor, GestureDetectorContainer& gestureDetectors )
+{
+  while ( actor )
+  {
+    // We may be checking a parent so ensure the parent requires this gesture (and do not unintentionally create the gesture data for the parent)
+    if ( actor->IsGestureRequred( mType ) )
+    {
+      // Retrieve the actor's detectors and check if they satisfy current gesture
+      const GestureDetectorContainer& connectedDetectors( actor->GetGestureData().GetGestureDetectorContainer( mType ) );
+      const GestureDetectorContainer::const_iterator endIter( connectedDetectors.end() );
+      for ( GestureDetectorContainer::const_iterator iter = connectedDetectors.begin(); iter != endIter; ++iter )
+      {
+        GestureDetector* current(*iter);
+
+        // Check deriving class for whether the current gesture satisfies the gesture detector's parameters.
+        if ( CheckGestureDetector( current, actor ) )
+        {
+          gestureDetectors.push_back(current);
+        }
+      }
+
+      // The hit actor or one of the parents is a gestured actor, break out.
+      if ( !gestureDetectors.empty() )
+      {
+        break;
+      }
+    }
+
+    // No match, we should now check the hit actor's parent.
+    actor = actor->GetParent();
+  }
+}
+
+void GestureProcessor::ProcessAndEmit( HitTestAlgorithm::Results& hitTestResults )
+{
+  if ( hitTestResults.actor )
+  {
+    Actor* hitTestActor( &GetImplementation( hitTestResults.actor ) );
+    Actor* actor( hitTestActor );
+
+    while ( actor )
+    {
+      GestureDetectorContainer gestureDetectors;
+      GetGesturedActor( actor, gestureDetectors );
+
+      if ( actor && !gestureDetectors.empty() )
+      {
+        // We have a match but check if the hit point is within the gestured actor's bounds.
+        // If it is not then continue up the actor hierarchy.
+
+        if ( actor == hitTestActor )
+        {
+          // Our gesture detector's attached actor WAS the hit actor so we can can emit the signal.
+          EmitGestureSignal( actor, gestureDetectors, hitTestResults.actorCoordinates );
+          break; // We have found AND emitted a signal on the gestured actor, break out.
+        }
+        else
+        {
+          if ( actor->IsHittable() )
+          {
+            const Vector3 size( actor->GetCurrentSize() );
+
+            if ( ( size.x > 0.0f ) && ( size.y > 0.0f ) )
+            {
+              // Ensure tap is within the actor's area
+              if ( actor->RaySphereTest( hitTestResults.rayOrigin, hitTestResults.rayDirection ) ) // Quick check
+              {
+                Vector4 hitPointLocal;
+                float distance( 0.0f );
+                if( actor->RayActorTest( hitTestResults.rayOrigin, hitTestResults.rayDirection, hitPointLocal, distance ) )
+                {
+                  // One of the parents was the gestured actor so we can emit the signal for that actor.
+                  EmitGestureSignal( actor, gestureDetectors, Vector2( hitPointLocal.x, hitPointLocal.y ) );
+                  break; // We have found AND emitted a signal on the gestured actor, break out.
+                }
+              }
+            }
+          }
+        }
+      }
+
+      // Continue up hierarchy to see if any of the parents require this gesture.
+      if ( actor )
+      {
+        actor = actor->GetParent();
+      }
+    }
+  }
+}
+
+bool GestureProcessor::HitTest(
+  Stage&                     stage,
+  Vector2                    screenCoordinates,
+  HitTestAlgorithm::Results& hitTestResults)
+{
+  GestureHitTestCheck hitCheck( mType );
+  HitTestAlgorithm::HitTest( stage, screenCoordinates, hitTestResults, hitCheck );
+  return hitTestResults.renderTask && hitTestResults.actor;
+}
+
+void GestureProcessor::SetActor( Actor* actor )
+{
+  if ( actor && actor != mCurrentGesturedActor )
+  {
+    ResetActor();
+
+    mCurrentGesturedActor = actor;
+    mCurrentGesturedActor->AddObserver( *this );
+  }
+  mGesturedActorDisconnected = false;
+}
+
+void GestureProcessor::ResetActor()
+{
+  if ( mCurrentGesturedActor )
+  {
+    mCurrentGesturedActor->RemoveObserver( *this );
+    mCurrentGesturedActor = NULL;
+    mGesturedActorDisconnected = false;
+  }
+}
+
+Actor* GestureProcessor::GetCurrentGesturedActor()
+{
+  return mGesturedActorDisconnected ? NULL : mCurrentGesturedActor;
+}
+
+void GestureProcessor::SceneObjectRemoved(Object& object)
+{
+  if ( mCurrentGesturedActor == &object &&
+      !mGesturedActorDisconnected )
+  {
+    // Inform deriving classes.
+    OnGesturedActorStageDisconnection();
+
+    // do not call object.RemoveObserver here, object is currently iterating through observers... you wouldnt want to upset object now would you?
+    mGesturedActorDisconnected = true;
+  }
+}
+
+void GestureProcessor::ObjectDestroyed(Object& object)
+{
+  if ( mCurrentGesturedActor == &object )
+  {
+    // Inform deriving classes.
+    OnGesturedActorStageDisconnection();
+
+    mCurrentGesturedActor = NULL;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/gesture-processor.h b/dali/internal/event/events/gesture-processor.h
new file mode 100644 (file)
index 0000000..8b661b3
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef __DALI_INTERNAL_GESTURE_PROCESSOR_H__
+#define __DALI_INTERNAL_GESTURE_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/gesture-detector-impl.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+class Actor;
+
+namespace Internal
+{
+
+/**
+ * Base class for the different Gesture Processors.
+ */
+class GestureProcessor : public Object::Observer
+{
+protected:
+
+  // Construction & Destruction
+
+  /**
+   * Protected constructor.  Cannot create an instance of GestureProcessor
+   */
+  GestureProcessor( Gesture::Type type );
+
+  /**
+   * Virtual protected destructor.
+   */
+  virtual ~GestureProcessor();
+
+  // Methods to be used by deriving classes
+
+  /**
+   * Given the hit actor, this walks up the actor tree to determine the actor that is connected to one (or several) gesture detectors.
+   *
+   * @param[in,out]  actor               The gestured actor. When this function returns, this is the actor that has been hit by the gesture.
+   * @param[out]     gestureDetectors    A container containing all the gesture detectors that have the hit actor attached and satisfy the functor parameters.
+   *
+   * @note Uses CheckGestureDetector() to check if a the current gesture matches the criteria the gesture detector requires.
+   * @pre gestureDetectors should be empty.
+   */
+  void GetGesturedActor( Actor*& actor, GestureDetectorContainer& gestureDetectors );
+
+  /**
+   * Calls the emission method in the deriving class for matching gesture-detectors with the hit-actor (or one of its parents).
+   *
+   * @param[in]  hitTestResults      The Hit Test Results.
+   *
+   * @note Uses the CheckGestureDetector() to check if the gesture matches the criteria of the given gesture detector
+   *       and EmitGestureSignal() to emit the signal.
+   * @pre Hit Testing should already be done.
+   */
+  void ProcessAndEmit( HitTestAlgorithm::Results& hitTestResults );
+
+  /**
+   * Hit test the screen coordinates, and place the results in hitTestResults.
+   * @param[in] stage Stage.
+   * @param[in] screenCoordinates The screen coordinates to test.
+   * @param[out] hitTestResults Structure to write results into.
+   * @return false if the system overlay was hit or no actor was hit.
+   */
+  virtual bool HitTest(Stage& stage, Vector2 screenCoordinates, HitTestAlgorithm::Results& hitTestResults);
+
+  /**
+   * Sets the mCurrentGesturedActor and connects to the required signals.
+   * @actor  actor  The actor so set.
+   */
+  void SetActor( Actor* actor );
+
+  /**
+   * Resets the set actor and disconnects any connected signals.
+   */
+  void ResetActor();
+
+  /**
+   * Returns the current gestured actor if it is on stage
+   *
+   * @return The current gestured actor
+   */
+  Actor* GetCurrentGesturedActor();
+
+private:
+
+  // For derived classes to override
+
+  /**
+   * Called when the gestured actor is removed from the stage.
+   */
+  virtual void OnGesturedActorStageDisconnection() = 0;
+
+  /**
+   * Called by the ProcessAndEmit() & GetGesturedActor() methods to check if the provided
+   * gesture-detector meets the parameters of the current gesture.
+   *
+   * @param[in]  detector  The gesture detector to check.
+   * @param[in]  actor     The actor that has been gestured.
+   *
+   * @return true, if the detector meets the parameters, false otherwise.
+   */
+  virtual bool CheckGestureDetector( GestureDetector* detector, Actor* actor ) = 0;
+
+  /**
+   * Called by the ProcessAndEmit() method when the gesture meets all applicable criteria and
+   * should be overridden by deriving classes to emit the gesture signal on gesture-detectors
+   * provided for the actor the gesture has occurred on.
+   *
+   * @param[in]  actor             The actor which has been gestured.
+   * @param[in]  gestureDetectors  The detectors that should emit the signal.
+   * @param[in]  actorCoordinates  The local actor coordinates where the gesture took place.
+   */
+  virtual void EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates ) = 0;
+
+  // Undefined
+
+  GestureProcessor( const GestureProcessor& );
+  GestureProcessor& operator=( const GestureProcessor& );
+
+  // SceneObject overrides
+
+  /**
+   * This will never get called as we do not observe objects that have not been added to the scene.
+   * @param[in] object The object object.
+   * @see Object::Observer::SceneObjectAdded()
+   */
+  virtual void SceneObjectAdded(Object& object) { }
+
+  /**
+   * This will be called when the actor is removed from the stage, we should clear and stop
+   * observing it.
+   * @param[in] object The object object.
+   * @see Object::Observer::SceneObjectRemoved()
+   */
+  virtual void SceneObjectRemoved(Object& object);
+
+  /**
+   * This will be called when the actor is destroyed. We should clear the actor.
+   * No need to stop observing as the object is being destroyed anyway.
+   * @see Object::Observer::ObjectDestroyed()
+   */
+  virtual void ObjectDestroyed(Object& object);
+
+private: // Data
+
+  Gesture::Type mType;                 ///< Type of GestureProcessor
+  Actor* mCurrentGesturedActor;        ///< The current actor that has been gestured.
+  bool   mGesturedActorDisconnected:1; ///< Indicates whether the gestured actor has been disconnected from the scene
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_GESTURE_PROCESSOR_H__
diff --git a/dali/internal/event/events/hit-test-algorithm-impl.cpp b/dali/internal/event/events/hit-test-algorithm-impl.cpp
new file mode 100644 (file)
index 0000000..a9ed698
--- /dev/null
@@ -0,0 +1,655 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/system-overlay.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/actors/image-actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/actors/layer-list.h>
+#include <dali/internal/event/common/system-overlay-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/projection.h>
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace HitTestAlgorithm
+{
+
+namespace
+{
+
+struct HitActor
+{
+  HitActor()
+  : actor( NULL ),
+    x( 0 ),
+    y( 0 ),
+    distance( std::numeric_limits<float>::max() ),
+    depth( std::numeric_limits<int>::min() )
+  {
+  }
+
+  Actor *actor;                         ///< the actor hit. (if actor hit, then initialised)
+  float x;                              ///< x position of hit (only valid if actor valid)
+  float y;                              ///< y position of hit (only valid if actor valid)
+  float distance;                       ///< distance from ray origin to hit actor
+  int depth;                            ///< depth index of this actor
+
+};
+
+/**
+ * Creates an Actor handle so that a HitTestFunction provided via the public API can be called.
+ */
+struct HitTestFunctionWrapper : public HitTestInterface
+{
+  /**
+   * Constructor
+   *
+   * @param[in] func HitTestFunction to call with an Actor handle.
+   */
+  HitTestFunctionWrapper( Dali::HitTestAlgorithm::HitTestFunction func )
+  : mFunc( func )
+  {
+  }
+
+  virtual bool IsActorHittable( Actor* actor )
+  {
+    return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::CHECK_ACTOR );
+  }
+
+  virtual bool DescendActorHierarchy( Actor* actor )
+  {
+    return mFunc( Dali::Actor( actor ), Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE );
+  }
+
+  virtual bool DoesLayerConsumeHit( Layer* layer )
+  {
+    // Layer::IsTouchConsumed() focuses on touch only. Here we are a wrapper for the public-api
+    // where the caller may want to check for something completely different.
+    // TODO: Should provide a means to let caller decide. For now do not allow layers to consume
+    return false;
+  }
+
+  Dali::HitTestAlgorithm::HitTestFunction mFunc;
+};
+
+/**
+ * Used in the hit-test algorithm to check whether the actor is touchable.
+ * It is used by the touch event processor.
+ */
+struct ActorTouchableCheck : public HitTestInterface
+{
+  virtual bool IsActorHittable( Actor* actor )
+  {
+    return actor->GetTouchRequired() && // Does the Application or derived actor type require a touch event?
+           actor->IsHittable();         // Is actor sensitive, visible and on the scene?
+  }
+
+  virtual bool DescendActorHierarchy( Actor* actor )
+  {
+    return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+           actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
+  }
+
+  virtual bool DoesLayerConsumeHit( Layer* layer )
+  {
+    return layer->IsTouchConsumed();
+  }
+};
+
+/**
+ * Check to see if the actor we're about to hit test is exclusively owned by another rendertask?
+ */
+bool IsActorExclusiveToAnotherRenderTask( const Actor& actor,
+                                          const RenderTask& renderTask,
+                                          const Vector< RenderTaskList::Exclusive >& exclusives )
+
+{
+  if ( exclusives.Size() )
+  {
+    for ( Vector< RenderTaskList::Exclusive >::Iterator exclusiveIt = exclusives.Begin(); exclusives.End() != exclusiveIt; ++exclusiveIt )
+    {
+      if ( exclusiveIt->renderTaskPtr != &renderTask )
+      {
+        if ( exclusiveIt->actorPtr == &actor )
+        {
+          return true;
+        }
+      }
+    }
+  }
+  return false;
+}
+
+/**
+ * Recursively hit test all the actors, without crossing into other layers.
+ * This algorithm performs a Depth-First-Search (DFS) on all Actors within Layer.
+ * Hit-Testing each Actor, noting the distance from the Ray-Origin (3D origin
+ * of touch vector). The closest Hit-Tested Actor is that which is returned.
+ * Exceptions to this rule are:
+ * - When comparing against renderable parents, if Actor is the same distance
+ * or closer than it's renderable parent, then it takes priority.
+ */
+HitActor HitTestWithinLayer( Actor& actor,
+                             const RenderTask& renderTask,
+                             const Vector< RenderTaskList::Exclusive >& exclusives,
+                             const Vector4& rayOrigin,
+                             const Vector4& rayDir,
+                             float& nearClippingPlane,
+                             float& farClippingPlane,
+                             HitTestInterface& hitCheck,
+                             bool& stencilOnLayer,
+                             bool& stencilHit,
+                             bool parentIsStencil,
+                             bool layerIs3d )
+{
+  HitActor hit;
+
+  if ( IsActorExclusiveToAnotherRenderTask( actor, renderTask, exclusives ) )
+  {
+    return hit;
+  }
+
+  // Children should inherit the stencil draw mode
+  bool isStencil = parentIsStencil;
+
+  if ( actor.GetDrawMode() == DrawMode::STENCIL && actor.IsVisible() )
+  {
+    isStencil = true;
+    stencilOnLayer = true;
+  }
+
+  // If we are a stencil or hittable...
+  if ( isStencil || hitCheck.IsActorHittable( &actor ) )
+  {
+    Vector3 size( actor.GetCurrentSize() );
+
+    if ( size.x > 0.0f && size.y > 0.0f &&          // Ensure the actor has a valid size.
+         actor.RaySphereTest( rayOrigin, rayDir ) ) // Perform quicker ray sphere test to see if our ray is close to the actor.
+    {
+      Vector4 hitPointLocal;
+      float distance;
+
+      // Finally, perform a more accurate ray test to see if our ray actually hits the actor.
+      if( actor.RayActorTest( rayOrigin, rayDir, hitPointLocal, distance ) )
+      {
+        if( distance >= nearClippingPlane && distance <= farClippingPlane )
+        {
+          // If the hit has happened on a stencil then register, but don't record as hit result
+          if ( isStencil )
+          {
+            stencilHit = true;
+          }
+          else
+          {
+            hit.actor = &actor;
+            hit.x = hitPointLocal.x;
+            hit.y = hitPointLocal.y;
+            hit.distance = distance;
+            hit.depth = actor.GetHierarchyDepth() * Dali::Layer::TREE_DEPTH_MULTIPLIER;
+
+            // Is this actor an Image Actor or contains a renderer?
+            if ( ImageActor* imageActor = dynamic_cast< ImageActor* >( &actor ) )
+            {
+              hit.depth += imageActor->GetDepthIndex();
+            }
+            else if ( actor.GetRendererCount() )
+            {
+              hit.depth += actor.GetRendererAt( 0 ).GetDepthIndex();
+            }
+          }
+        }
+      }
+    }
+  }
+
+  // If we are a stencil (or a child of a stencil) and we have already ascertained that the stencil has been hit then there is no need to hit-test the children of this stencil-actor
+  if ( isStencil && stencilHit  )
+  {
+    return hit;
+  }
+
+  // Find a child hit, until we run out of actors in the current layer.
+  HitActor childHit;
+  if( actor.GetChildCount() > 0 )
+  {
+    childHit.distance = std::numeric_limits<float>::max();
+    childHit.depth = std::numeric_limits<int>::min();
+    ActorContainer& children = actor.GetChildrenInternal();
+
+    // Hit test ALL children and calculate their distance.
+    bool parentIsRenderable = actor.IsRenderable();
+
+    for( ActorIter iter = children.begin(), endIter = children.end(); iter != endIter; ++iter )
+    {
+      // Descend tree only if...
+      if ( !(*iter)->IsLayer() &&    // Child is NOT a layer, hit testing current layer only or Child is not a layer and we've inherited the stencil draw mode
+           ( isStencil || hitCheck.DescendActorHierarchy( ( *iter ).Get() ) ) ) // We are a stencil OR we can descend into child hierarchy
+      {
+        HitActor currentHit( HitTestWithinLayer(  (*iter->Get()),
+                                                  renderTask,
+                                                  exclusives,
+                                                  rayOrigin,
+                                                  rayDir,
+                                                  nearClippingPlane,
+                                                  farClippingPlane,
+                                                  hitCheck,
+                                                  stencilOnLayer,
+                                                  stencilHit,
+                                                  isStencil,
+                                                  layerIs3d) );
+
+        bool updateChildHit = false;
+        if ( currentHit.distance >= 0.0f )
+        {
+          if( layerIs3d )
+          {
+            updateChildHit = ( ( currentHit.depth > childHit.depth ) ||
+                ( ( currentHit.depth == childHit.depth ) && ( currentHit.distance < childHit.distance ) ) );
+          }
+          else
+          {
+            updateChildHit = currentHit.depth >= childHit.depth;
+          }
+        }
+
+        if ( updateChildHit )
+        {
+          if( !parentIsRenderable || currentHit.depth > hit.depth ||
+            ( layerIs3d && ( currentHit.depth == hit.depth && currentHit.distance < hit.distance )) )
+            {
+              childHit = currentHit;
+            }
+        }
+      }
+    }
+  }
+  return ( childHit.actor ) ? childHit : hit;
+}
+
+/**
+ * Return true if actor is sourceActor or a descendent of sourceActor
+ */
+bool IsWithinSourceActors( const Actor& sourceActor, const Actor& actor )
+{
+  if ( &sourceActor == &actor )
+  {
+    return true;
+  }
+  else
+  {
+    Actor* parent = actor.GetParent();
+    if ( parent )
+    {
+      return IsWithinSourceActors( sourceActor, *parent );
+    }
+  }
+
+  // Not within source actors
+  return false;
+}
+
+/**
+ * Returns true if the layer and all of the layer's parents are visible and sensitive.
+ */
+inline bool IsActuallyHittable( Layer& layer, const Vector2& screenCoordinates, const Vector2& stageSize, HitTestInterface& hitCheck )
+{
+  bool hittable( true );
+
+  if(layer.IsClipping())
+  {
+    ClippingBox box = layer.GetClippingBox();
+
+    if( screenCoordinates.x < box.x ||
+        screenCoordinates.x > box.x + box.width ||
+        screenCoordinates.y < stageSize.y - (box.y + box.height) ||
+        screenCoordinates.y > stageSize.y - box.y)
+    {
+      // Not touchable if clipping is enabled in the layer and the screen coordinate is outside the clip region.
+      hittable = false;
+    }
+  }
+
+  if(hittable)
+  {
+    Actor* actor( &layer );
+
+    // Ensure that we can descend into the layer's (or any of its parent's) hierarchy.
+    while ( actor && hittable )
+    {
+      if ( ! hitCheck.DescendActorHierarchy( actor ) )
+      {
+        hittable = false;
+        break;
+      }
+      actor = actor->GetParent();
+    }
+  }
+
+  return hittable;
+}
+
+/**
+ * Gets the near and far clipping planes of the camera from which the scene is viewed in the render task.
+ */
+void GetCameraClippingPlane( RenderTask& renderTask, float& nearClippingPlane, float& farClippingPlane )
+{
+  CameraActor* cameraActor = renderTask.GetCameraActor();
+  nearClippingPlane = cameraActor->GetNearClippingPlane();
+  farClippingPlane = cameraActor->GetFarClippingPlane();
+}
+
+/**
+ * Hit test a RenderTask
+ */
+bool HitTestRenderTask( const Vector< RenderTaskList::Exclusive >& exclusives,
+                        Stage& stage,
+                        LayerList& layers,
+                        RenderTask& renderTask,
+                        Vector2 screenCoordinates,
+                        Results& results,
+                        HitTestInterface& hitCheck )
+{
+  if ( renderTask.IsHittable( screenCoordinates ) )
+  {
+    Viewport viewport;
+    renderTask.GetViewport( viewport );
+    if( screenCoordinates.x < viewport.x ||
+        screenCoordinates.x > viewport.x + viewport.width ||
+        screenCoordinates.y < viewport.y ||
+        screenCoordinates.y > viewport.y + viewport.height )
+    {
+      // The screen coordinate is outside the viewport of render task. The viewport clips all layers.
+      return false;
+    }
+
+    float nearClippingPlane, farClippingPlane;
+    GetCameraClippingPlane(renderTask, nearClippingPlane, farClippingPlane);
+
+    // Determine the layer depth of the source actor
+    Actor* sourceActor( renderTask.GetSourceActor() );
+    if ( sourceActor )
+    {
+      Dali::Layer layer( sourceActor->GetLayer() );
+      if ( layer )
+      {
+        const unsigned int sourceActorDepth( layer.GetDepth() );
+
+        CameraActor* cameraActor = renderTask.GetCameraActor();
+        bool pickingPossible = cameraActor->BuildPickingRay(
+            screenCoordinates,
+            viewport,
+            results.rayOrigin,
+            results.rayDirection );
+        if( !pickingPossible )
+        {
+          return false;
+        }
+
+        // Hit test starting with the top layer, working towards the bottom layer.
+        HitActor hit;
+        bool stencilOnLayer = false;
+        bool stencilHit = false;
+        bool layerConsumesHit = false;
+
+        const Vector2& stageSize = stage.GetSize();
+
+        for (int i=layers.GetLayerCount()-1; i>=0 && !(hit.actor); --i)
+        {
+          Layer* layer( layers.GetLayer(i) );
+          HitActor previousHit = hit;
+          stencilOnLayer = false;
+          stencilHit = false;
+
+          // Ensure layer is touchable (also checks whether ancestors are also touchable)
+          if ( IsActuallyHittable ( *layer, screenCoordinates, stageSize, hitCheck ) )
+          {
+            // Always hit-test the source actor; otherwise test whether the layer is below the source actor in the hierarchy
+            if ( sourceActorDepth == static_cast<unsigned int>(i) )
+            {
+              // Recursively hit test the source actor & children, without crossing into other layers.
+              hit = HitTestWithinLayer( *sourceActor,
+                                        renderTask,
+                                        exclusives,
+                                        results.rayOrigin,
+                                        results.rayDirection,
+                                        nearClippingPlane,
+                                        farClippingPlane,
+                                        hitCheck,
+                                        stencilOnLayer,
+                                        stencilHit,
+                                        false,
+                                        layer->GetBehavior() == Dali::Layer::LAYER_3D);
+            }
+            else if ( IsWithinSourceActors( *sourceActor, *layer ) )
+            {
+              // Recursively hit test all the actors, without crossing into other layers.
+              hit = HitTestWithinLayer( *layer,
+                                        renderTask,
+                                        exclusives,
+                                        results.rayOrigin,
+                                        results.rayDirection,
+                                        nearClippingPlane,
+                                        farClippingPlane,
+                                        hitCheck,
+                                        stencilOnLayer,
+                                        stencilHit,
+                                        false,
+                                        layer->GetBehavior() == Dali::Layer::LAYER_3D);
+            }
+
+            // If a stencil on this layer hasn't been hit, then discard hit results for this layer if our current hit actor is renderable
+            if ( stencilOnLayer && !stencilHit &&
+                 hit.actor && hit.actor->IsRenderable() )
+            {
+              hit = previousHit;
+            }
+
+            // If this layer is set to consume the hit, then do not check any layers behind it
+            if ( hitCheck.DoesLayerConsumeHit( layer ) )
+            {
+              layerConsumesHit = true;
+              break;
+            }
+          }
+        }
+        if ( hit.actor )
+        {
+          results.renderTask = Dali::RenderTask(&renderTask);
+          results.actor = Dali::Actor(hit.actor);
+          results.actorCoordinates.x = hit.x;
+          results.actorCoordinates.y = hit.y;
+          return true; // Success
+        }
+        else if ( layerConsumesHit )
+        {
+          return true; // Also success if layer is consuming the hit
+        }
+      }
+    }
+  }
+  return false;
+}
+
+/**
+ * Iterate through RenderTaskList and perform hit test.
+ *
+ * @return true if we have a hit, false otherwise
+ */
+bool HitTestForEachRenderTask( Stage& stage,
+                               LayerList& layers,
+                               RenderTaskList& taskList,
+                               const Vector2& screenCoordinates,
+                               Results& results,
+                               HitTestInterface& hitCheck )
+{
+  RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
+  RenderTaskList::RenderTaskContainer::reverse_iterator endIter = tasks.rend();
+
+  const Vector< RenderTaskList::Exclusive >& exclusives = taskList.GetExclusivesList();
+
+  // Check onscreen tasks before offscreen ones, hit test order should be reverse of draw order (see ProcessRenderTasks() where offscreen tasks are drawn first).
+
+  // on screen
+  for ( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter )
+  {
+    RenderTask& renderTask = GetImplementation( *iter );
+    Dali::FrameBufferImage frameBufferImage = renderTask.GetTargetFrameBuffer();
+
+    // Note that if frameBufferImage is NULL we are using the default (on screen) render target
+    if(frameBufferImage)
+    {
+      ResourceId id = GetImplementation(frameBufferImage).GetResourceId();
+
+      // on screen only
+      if(0 != id)
+      {
+        // Skip to next task
+        continue;
+      }
+    }
+
+    if ( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) )
+    {
+      // Return true when an actor is hit (or layer in our render-task consumes the hit)
+      return true; // don't bother checking off screen tasks
+    }
+  }
+
+  // off screen
+  for ( RenderTaskList::RenderTaskContainer::reverse_iterator iter = tasks.rbegin(); endIter != iter; ++iter )
+  {
+    RenderTask& renderTask = GetImplementation( *iter );
+    Dali::FrameBufferImage frameBufferImage = renderTask.GetTargetFrameBuffer();
+
+    // Note that if frameBufferImage is NULL we are using the default (on screen) render target
+    if(frameBufferImage)
+    {
+      ResourceId id = GetImplementation(frameBufferImage).GetResourceId();
+
+      // off screen only
+      if(0 == id)
+      {
+        // Skip to next task
+        continue;
+      }
+
+      if ( HitTestRenderTask( exclusives, stage, layers, renderTask, screenCoordinates, results, hitCheck ) )
+      {
+        // Return true when an actor is hit (or a layer in our render-task consumes the hit)
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+} // unnamed namespace
+
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func )
+{
+  bool wasHit( false );
+  // Hit-test the regular on-stage actors
+  RenderTaskList& taskList = stage.GetRenderTaskList();
+  LayerList& layerList = stage.GetLayerList();
+
+  Results hitTestResults;
+  HitTestFunctionWrapper hitTestFunctionWrapper( func );
+  if (  HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+  {
+    results.actor = hitTestResults.actor;
+    results.actorCoordinates = hitTestResults.actorCoordinates;
+    wasHit = true;
+  }
+  return wasHit;
+}
+
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface )
+{
+  bool wasHit( false );
+
+  // Hit-test the system-overlay actors first
+  SystemOverlay* systemOverlay = stage.GetSystemOverlayInternal();
+
+  if ( systemOverlay )
+  {
+    RenderTaskList& overlayTaskList = systemOverlay->GetOverlayRenderTasks();
+    LayerList& overlayLayerList = systemOverlay->GetLayerList();
+
+    wasHit = HitTestForEachRenderTask( stage, overlayLayerList, overlayTaskList, screenCoordinates, results, hitTestInterface );
+  }
+
+  // Hit-test the regular on-stage actors
+  if ( !wasHit )
+  {
+    RenderTaskList& taskList = stage.GetRenderTaskList();
+    LayerList& layerList = stage.GetLayerList();
+
+    wasHit = HitTestForEachRenderTask( stage, layerList, taskList, screenCoordinates, results, hitTestInterface );
+  }
+  return wasHit;
+}
+
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results )
+{
+  ActorTouchableCheck actorTouchableCheck;
+  return HitTest( stage, screenCoordinates, results, actorTouchableCheck );
+}
+
+bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates,
+              Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func )
+{
+  bool wasHit( false );
+  Results hitTestResults;
+
+  if( Stage::GetCurrent() == NULL )
+  {
+    return false;
+  }
+
+  const Vector< RenderTaskList::Exclusive >& exclusives = Stage::GetCurrent()->GetRenderTaskList().GetExclusivesList();
+  HitTestFunctionWrapper hitTestFunctionWrapper( func );
+  if ( HitTestRenderTask( exclusives, stage, stage.GetLayerList(), renderTask, screenCoordinates, hitTestResults, hitTestFunctionWrapper ) )
+  {
+    results.actor = hitTestResults.actor;
+    results.actorCoordinates = hitTestResults.actorCoordinates;
+    wasHit = true;
+  }
+  return wasHit;
+}
+
+} // namespace HitTestAlgorithm
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/hit-test-algorithm-impl.h b/dali/internal/event/events/hit-test-algorithm-impl.h
new file mode 100644 (file)
index 0000000..07b2291
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__
+#define __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/public-api/render-tasks/render-task.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Layer;
+
+/**
+ * This namespace is provided for application developers to do hit test for the actors.
+ */
+namespace HitTestAlgorithm
+{
+
+struct Results
+{
+  Dali::RenderTask renderTask;       ///< The render-task displaying the actor.
+  Dali::Actor      actor;            ///< The hit actor.
+  Vector2          actorCoordinates; ///< The actor coordinates.
+  Vector4          rayOrigin;        ///< The point of origin of the ray.
+  Vector4          rayDirection;     ///< The direction vector of the ray.
+};
+
+/**
+ * Interface used by the hit-test-algorithm to determine whether the actor is hittable or whether
+ * we walk down its hierarchy.
+ */
+struct HitTestInterface
+{
+  /**
+   * Called by the hit-test algorithm to determine whether the actor is hittable or not.
+   *
+   * @param[in] actor Raw pointer to an Actor object.
+   *
+   * @return true if actor is hittable, false otherwise.
+   */
+  virtual bool IsActorHittable( Actor* actor ) = 0;
+
+  /**
+   * Called by the hit-test algorithm to determine whether the algorithm should descend the actor's
+   * hierarchy (and hit-test its children as well).
+   *
+   * @param[in] actor Raw pointer to an Actor object.
+   *
+   * @return true if we should descend the actor's hierarchy, false otherwise.
+   */
+  virtual bool DescendActorHierarchy( Actor* actor ) = 0;
+
+  /**
+   * Called by the hit-test algorithm to determine whether the layer specified consumes the hit
+   * regardless of whether an actor in the layer requires it or not.
+   *
+   * @note If true is returned, then no layers behind this layer will be hit-test.
+   *
+   * @param[in] layer Raw pointer to a Layer object.
+   *
+   * @return true if the layer should consume the hit, false otherwise.
+   */
+  virtual bool DoesLayerConsumeHit( Layer* layer ) = 0;
+};
+
+/**
+ * @copydoc Dali::HitTestAlgorithm::HitTest(Stage stage, const Vector2& screenCoordinates, Results& results, HitTestFunction func )
+ */
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func );
+
+/**
+ * Given screen coordinates, this method returns the hit actor & the local coordinates relative to the actor etc.
+ * @param[in] stage The stage.
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] results The results of the hit-test.
+ * @param[in] hitTestInterface Used to determine whether the actor is hit or whether we walk down its hierarchy
+ * @return true if something was hit
+ *
+ * <h3>Hit Test Algorithm:</h3>
+ *
+ * - The system overlay RenderTaskList is hit-tested first.
+ * - If no hit then the regular RenderTaskList is used to hit test the on stage actors.
+ * - The bulk of the hit test algorithm is described in Dali::Actor.
+ * - In each RenderTask's its viewing parameters (the view and projection matrices, and the viewport)
+ *   are used to build a picking ray into the scene which is used for our ray tests when hit testing
+ *   an actor within each layer.
+ * - If an actor is deemed to be hittable, then a quicker ray sphere test on the actor is performed
+ *   first to determine if the ray is in the actor's proximity.
+ * - If this is also successful, then a more accurate ray test is performed to see if we have a hit.
+ *
+ * @note Currently, we prefer a child hit over a parent (regardless of the distance from the
+ *       camera) unless the parent is a RenderableActor but this is subject to change.
+ */
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results, HitTestInterface& hitTestInterface );
+
+/**
+ * Default HitTest where we check if a touch is required.
+ *
+ * @param[in] stage The stage.
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] results The results of the hit-test.
+ * @return true if something was hit
+ *
+ * @see HitTest(Stage&, const Vector2&, Results&, HitTestInterface&)
+ */
+bool HitTest( Stage& stage, const Vector2& screenCoordinates, Results& results );
+
+/**
+ * Hit test specific to a given RenderTask
+ *
+ * @param[in] stage The stage.
+ * @param[in] renderTask The render task for hit test
+ * @param[in] screenCoordinates The screen coordinates.
+ * @param[out] results The results of the hit-test.
+ * @param[in] func The function to use in the hit-test algorithm.
+ * @return true if something was hit
+ */
+bool HitTest( Stage& stage, RenderTask& renderTask, const Vector2& screenCoordinates,
+              Dali::HitTestAlgorithm::Results& results, Dali::HitTestAlgorithm::HitTestFunction func );
+
+} // namespace HitTestAlgorithm
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_HIT_TEST_ALGORITHM_H__
diff --git a/dali/internal/event/events/hover-event-processor.cpp b/dali/internal/event/events/hover-event-processor.cpp
new file mode 100644 (file)
index 0000000..c4d5440
--- /dev/null
@@ -0,0 +1,422 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/hover-event-processor.h>
+
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#endif
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/hover-event-integ.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_HOVER_PROCESSOR" );
+
+const char * TOUCH_POINT_STATE[TouchPoint::Last] =
+{
+  "Started",
+  "Finished",
+  "Motion",
+  "Leave",
+  "Stationary",
+  "Interrupted",
+};
+
+#endif // defined(DEBUG_ENABLED)
+
+/**
+ *  Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitHoverSignals( Dali::Actor actor, const HoverEvent& event )
+{
+  Dali::Actor consumedActor;
+
+  if ( actor )
+  {
+    Dali::Actor oldParent( actor.GetParent() );
+
+    Actor& actorImpl( GetImplementation(actor) );
+
+    bool consumed( false );
+
+    // Only emit the signal if the actor's hover signal has connections (or derived actor implementation requires hover).
+    if ( actorImpl.GetHoverRequired() )
+    {
+      consumed = actorImpl.EmitHoverEventSignal( event );
+    }
+
+    if ( consumed )
+    {
+      // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+      consumedActor = Dali::Actor( &actorImpl );
+    }
+    else
+    {
+      // The actor may have been removed/reparented during the signal callbacks.
+      Dali::Actor parent = actor.GetParent();
+
+      if ( parent &&
+           (parent == oldParent) )
+      {
+        // One of the actor's parents may consumed the event and they should be set as the consumed actor.
+        consumedActor = EmitHoverSignals( parent, event );
+      }
+    }
+  }
+
+  return consumedActor;
+}
+
+/**
+ * Changes the state of the primary point to leave and emits the hover signals
+ */
+Dali::Actor EmitHoverSignals( Actor* actor, RenderTask& renderTask, const HoverEvent& originalEvent, TouchPoint::State state )
+{
+  HoverEvent hoverEvent( originalEvent );
+
+  DALI_ASSERT_DEBUG( NULL != actor && "NULL actor pointer" );
+  if( actor )
+  {
+    TouchPoint& primaryPoint = hoverEvent.points[0];
+
+    actor->ScreenToLocal( renderTask, primaryPoint.local.x, primaryPoint.local.y, primaryPoint.screen.x, primaryPoint.screen.y );
+
+    primaryPoint.hitActor = Dali::Actor(actor);
+    primaryPoint.state = state;
+  }
+
+  return EmitHoverSignals( Dali::Actor(actor), hoverEvent );
+}
+
+/**
+ * Used in the hit-test algorithm to check whether the actor is hoverable.
+ */
+struct ActorHoverableCheck : public HitTestAlgorithm::HitTestInterface
+{
+  bool IsActorHittable( Actor* actor )
+  {
+    return actor->GetHoverRequired() && // Does the Application or derived actor type require a hover event?
+           actor->IsHittable();         // Is actor sensitive, visible and on the scene?
+  }
+
+  bool DescendActorHierarchy( Actor* actor )
+  {
+    return actor->IsVisible() && // Actor is visible, if not visible then none of its children are visible.
+           actor->IsSensitive(); // Actor is sensitive, if insensitive none of its children should be hittable either.
+  }
+
+  bool DoesLayerConsumeHit( Layer* layer )
+  {
+    return layer->IsHoverConsumed();
+  }
+};
+
+} // unnamed namespace
+
+HoverEventProcessor::HoverEventProcessor( Stage& stage )
+: mStage( stage ),
+  mLastPrimaryHitActor(),
+  mLastConsumedActor(),
+  mHoverStartConsumedActor(),
+  mLastRenderTask()
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+HoverEventProcessor::~HoverEventProcessor()
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+void HoverEventProcessor::ProcessHoverEvent( const Integration::HoverEvent& event )
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+
+  DALI_ASSERT_ALWAYS( !event.points.empty() && "Empty HoverEvent sent from Integration\n" );
+
+  Stage& stage = mStage;
+
+  PRINT_HIERARCHY(gLogFilter);
+
+  // Copy so we can add the results of a hit-test.
+  HoverEvent hoverEvent( event.time );
+
+  // 1) Check if it is an interrupted event - we should inform our last primary hit actor about this
+  //    and emit the stage signal as well.
+
+  if ( event.points[0].state == TouchPoint::Interrupted )
+  {
+    Dali::Actor consumingActor;
+    hoverEvent.points.push_back(event.points[0]);
+
+    Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+    if ( lastPrimaryHitActor )
+    {
+      Dali::Actor lastPrimaryHitActorHandle( lastPrimaryHitActor );
+      hoverEvent.points[0].hitActor = lastPrimaryHitActorHandle;
+      consumingActor = EmitHoverSignals( lastPrimaryHitActorHandle, hoverEvent );
+    }
+
+    // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
+    Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+    if ( lastConsumedActor &&
+         lastConsumedActor != lastPrimaryHitActor &&
+         lastConsumedActor != consumingActor )
+    {
+      Dali::Actor lastConsumedActorHandle( lastConsumedActor );
+      hoverEvent.points[0].hitActor = lastConsumedActorHandle;
+      EmitHoverSignals( lastConsumedActorHandle, hoverEvent );
+    }
+
+    // Tell the hover-start consuming actor as well, if required
+    Actor* hoverStartConsumedActor( mHoverStartConsumedActor.GetActor() );
+    if ( hoverStartConsumedActor &&
+         hoverStartConsumedActor != lastPrimaryHitActor &&
+         hoverStartConsumedActor != lastConsumedActor &&
+         hoverStartConsumedActor != consumingActor )
+    {
+      Dali::Actor hoverStartConsumedActorHandle( hoverStartConsumedActor );
+      hoverEvent.points[0].hitActor = hoverStartConsumedActorHandle;
+      EmitHoverSignals( hoverStartConsumedActorHandle, hoverEvent );
+    }
+
+    mLastPrimaryHitActor.SetActor( NULL );
+    mLastConsumedActor.SetActor( NULL );
+    mHoverStartConsumedActor.SetActor( NULL );
+    mLastRenderTask.Reset();
+
+    hoverEvent.points[0].hitActor.Reset();
+
+    return; // No need for hit testing
+  }
+
+  // 2) Hit Testing.
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Point(s): %d\n", event.GetPointCount() );
+
+  Dali::RenderTask currentRenderTask;
+
+  for ( TouchPointContainerConstIterator iter = event.points.begin(), beginIter = event.points.begin(), endIter = event.points.end(); iter != endIter; ++iter )
+  {
+    HitTestAlgorithm::Results hitTestResults;
+    ActorHoverableCheck actorHoverableCheck;
+    HitTestAlgorithm::HitTest( stage, iter->screen, hitTestResults, actorHoverableCheck );
+
+    TouchPoint newPoint( iter->deviceId, iter->state, iter->screen.x, iter->screen.y );
+    newPoint.hitActor = hitTestResults.actor;
+    newPoint.local = hitTestResults.actorCoordinates;
+
+    hoverEvent.points.push_back( newPoint );
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  State(%s), Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n",
+                   TOUCH_POINT_STATE[iter->state], iter->screen.x, iter->screen.y,
+                   ( hitTestResults.actor ? (void*)&hitTestResults.actor.GetBaseObject() : NULL ),
+                   ( hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" ),
+                   hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y );
+
+    // Only set the currentRenderTask for the primary hit actor.
+    if ( iter == beginIter && hitTestResults.renderTask )
+    {
+      currentRenderTask = hitTestResults.renderTask;
+    }
+  }
+
+  // 3) Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+
+  // Emit the touch signal
+  Dali::Actor consumedActor;
+  if ( currentRenderTask )
+  {
+    consumedActor = EmitHoverSignals( hoverEvent.points[0].hitActor, hoverEvent );
+  }
+
+  TouchPoint& primaryPoint = hoverEvent.points[0];
+  Dali::Actor primaryHitActor = primaryPoint.hitActor;
+  TouchPoint::State primaryPointState = primaryPoint.state;
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "PrimaryHitActor:     (%p) %s\n", primaryPoint.hitActor ? (void*)&primaryPoint.hitActor.GetBaseObject() : NULL, primaryPoint.hitActor ? primaryPoint.hitActor.GetName().c_str() : "" );
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "ConsumedActor:       (%p) %s\n", consumedActor ? (void*)&consumedActor.GetBaseObject() : NULL, consumedActor ? consumedActor.GetName().c_str() : "" );
+
+  if ( ( primaryPointState == TouchPoint::Started ) &&
+       ( hoverEvent.GetPointCount() == 1 ) &&
+       ( consumedActor && consumedActor.OnStage() ) )
+  {
+    mHoverStartConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+  }
+
+  // 4) Check if the last primary hit actor requires a leave event and if it was different to the current primary
+  //    hit actor.  Also process the last consumed actor in the same manner.
+
+  Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+  Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+  if( (primaryPointState == TouchPoint::Motion) || (primaryPointState == TouchPoint::Finished) || (primaryPointState == TouchPoint::Stationary) )
+  {
+    if ( mLastRenderTask )
+    {
+      Dali::Actor leaveEventConsumer;
+      RenderTask& lastRenderTaskImpl( GetImplementation( mLastRenderTask ) );
+
+      if( lastPrimaryHitActor &&
+          lastPrimaryHitActor != primaryHitActor &&
+          lastPrimaryHitActor != consumedActor )
+      {
+        if( lastPrimaryHitActor->IsHittable() && IsActuallySensitive( lastPrimaryHitActor ) )
+        {
+          if ( lastPrimaryHitActor->GetLeaveRequired() )
+          {
+            DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Hit):     (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+            leaveEventConsumer = EmitHoverSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Leave );
+          }
+        }
+        else
+        {
+          // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
+          // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+          DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Hit):     (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+          leaveEventConsumer = EmitHoverSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Interrupted );
+        }
+      }
+
+      // Check if the motion event has been consumed by another actor's listener.  In this case, the previously
+      // consumed actor's listeners may need to be informed (through a leave event).
+      // Further checks here to ensure we do not signal the same actor twice for the same event.
+      if ( lastConsumedActor &&
+           lastConsumedActor != consumedActor &&
+           lastConsumedActor != lastPrimaryHitActor &&
+           lastConsumedActor != primaryHitActor &&
+           lastConsumedActor != leaveEventConsumer )
+      {
+        if( lastConsumedActor->IsHittable() && IsActuallySensitive( lastConsumedActor ) )
+        {
+          if( lastConsumedActor->GetLeaveRequired() )
+          {
+            DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Consume): (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+            EmitHoverSignals( lastConsumedActor, lastRenderTaskImpl, hoverEvent, TouchPoint::Leave );
+          }
+        }
+        else
+        {
+          // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
+          // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+          DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Consume):     (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+          EmitHoverSignals( mLastConsumedActor.GetActor(), lastRenderTaskImpl, hoverEvent, TouchPoint::Interrupted );
+        }
+      }
+    }
+  }
+
+  // 5) If our primary point is an Finished event, then the primary point (in multi-touch) will change next
+  //    time so set our last primary actor to NULL.  Do the same to the last consumed actor as well.
+
+  if ( primaryPointState == TouchPoint::Finished )
+  {
+    mLastPrimaryHitActor.SetActor( NULL );
+    mLastConsumedActor.SetActor( NULL );
+    mLastRenderTask.Reset();
+  }
+  else
+  {
+    // The primaryHitActor may have been removed from the stage so ensure it is still on the stage before setting members.
+    if ( primaryHitActor && primaryHitActor.OnStage() )
+    {
+      mLastPrimaryHitActor.SetActor( &GetImplementation( primaryHitActor ) );
+
+      // Only observe the consumed actor if we have a primaryHitActor (check if it is still on stage).
+      if ( consumedActor && consumedActor.OnStage() )
+      {
+        mLastConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+      }
+      else
+      {
+        mLastConsumedActor.SetActor( NULL );
+      }
+
+      mLastRenderTask = currentRenderTask;
+    }
+    else
+    {
+      mLastPrimaryHitActor.SetActor( NULL );
+      mLastConsumedActor.SetActor( NULL );
+      mLastRenderTask.Reset();
+    }
+  }
+
+  // 6) Emit an interrupted event to the hover-started actor if it hasn't consumed the Finished.
+
+  if ( hoverEvent.GetPointCount() == 1 ) // Only want the first hover started
+  {
+    switch ( primaryPointState )
+    {
+      case TouchPoint::Finished:
+      {
+        Actor* hoverStartConsumedActor( mHoverStartConsumedActor.GetActor() );
+        if ( hoverStartConsumedActor &&
+             hoverStartConsumedActor != consumedActor &&
+             hoverStartConsumedActor != lastPrimaryHitActor &&
+             hoverStartConsumedActor != lastConsumedActor )
+        {
+          Dali::Actor hoverStartConsumedActorHandle( hoverStartConsumedActor );
+          hoverEvent.points[0].hitActor = hoverStartConsumedActorHandle;
+          hoverEvent.points[0].state = TouchPoint::Interrupted;
+          EmitHoverSignals( hoverStartConsumedActorHandle, hoverEvent );
+
+          // Restore hover-event to original state
+          hoverEvent.points[0].hitActor = primaryHitActor;
+          hoverEvent.points[0].state = primaryPointState;
+        }
+
+        mHoverStartConsumedActor.SetActor( NULL );
+      }
+      // No break, Fallthrough
+
+      case TouchPoint::Started:
+      case TouchPoint::Motion:
+      case TouchPoint::Leave:
+      case TouchPoint::Stationary:
+      case TouchPoint::Interrupted:
+      case TouchPoint::Last:
+      {
+        // Ignore
+        break;
+      }
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/hover-event-processor.h b/dali/internal/event/events/hover-event-processor.h
new file mode 100644 (file)
index 0000000..d28989e
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/actor-observer.h>
+
+namespace Dali
+{
+
+class Actor;
+struct Vector2;
+struct Vector4;
+
+namespace Integration
+{
+struct HoverEvent;
+}
+
+namespace Internal
+{
+
+struct ActorObserver;
+class Stage;
+
+/**
+ * <h3>Multi-Hover Event Processing:</h3>
+ *
+ * The HoverEventProcessor processes hover events and emits the Hovered signal on the hit actor (and
+ * its parents).
+ *
+ * - Hit Testing & Hover Event Delivery are described in Dali::Actor.
+ */
+class HoverEventProcessor
+{
+public:
+
+  /**
+   * Create an event processor.
+   * @param[in] stage The stage.
+   */
+  HoverEventProcessor( Stage& stage );
+
+  /**
+   * Non-virtual destructor; HoverEventProcessor is not a base class
+   */
+  ~HoverEventProcessor();
+
+  /**
+   * This function is called by the event processor whenever a hover event occurs.
+   * @param[in] event The hover event that has occurred.
+   */
+  void ProcessHoverEvent( const Integration::HoverEvent& event );
+
+private:
+
+  // Undefined
+  HoverEventProcessor(const HoverEventProcessor&);
+
+  // Undefined
+  HoverEventProcessor& operator=(const HoverEventProcessor& rhs);
+
+  Stage& mStage; ///< Used to deliver touch events
+  ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
+  ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
+  ActorObserver mHoverStartConsumedActor; ///< Stores the hover-start consumed actor
+  Dali::RenderTask mLastRenderTask; ///< The RenderTask used for the last hit actor
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_HOVER_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/key-event-processor.cpp b/dali/internal/event/events/key-event-processor.cpp
new file mode 100644 (file)
index 0000000..5261d26
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/key-event-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/key-event.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/integration-api/events/key-event-integ.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+KeyEventProcessor::KeyEventProcessor(Stage& stage)
+: mStage(stage)
+{
+}
+
+KeyEventProcessor::~KeyEventProcessor()
+{
+}
+
+void KeyEventProcessor::ProcessKeyEvent(const Integration::KeyEvent& event)
+{
+  KeyEvent keyEvent(event.keyName, event.keyString, event.keyCode, event.keyModifier, event.time, static_cast<KeyEvent::State>(event.state));
+
+  // Emit the key event signal from stage.
+  mStage.EmitKeyEventSignal(keyEvent);
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/key-event-processor.h b/dali/internal/event/events/key-event-processor.h
new file mode 100644 (file)
index 0000000..9f8fc23
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __DALI_INTERNAL_KEY_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_KEY_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Integration
+{
+struct KeyEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+/**
+ *  KeyEventProcessor receives the filtered key events from the Dali Event processor.
+ *
+ *  When a key event is received the KeyEvent Processor queries the Stage to get the actor in focus.
+ *  Any actor can be set by the actor api to be the focus of key events.  The actor is then sent the key event.
+ *  If no actor is set for focus then the key event is discarded.
+ */
+class KeyEventProcessor
+{
+public:
+
+  /**
+   * Create a Key event processor.
+   */
+  KeyEventProcessor(Stage& stage);
+
+  /**
+   * Non-virtual destructor; KeyEventProcessor is not a base class
+   */
+  ~KeyEventProcessor();
+
+  /**
+   * This function is called by the event processor whenever a key event occurs.
+   * @param[in] event The key event that has occurred.
+   */
+  void ProcessKeyEvent(const Integration::KeyEvent& event);
+
+private:
+
+  // Undefined
+  KeyEventProcessor(const KeyEventProcessor&);
+
+  // Undefined
+  KeyEventProcessor& operator=(const KeyEventProcessor& rhs);
+
+private:
+
+  Stage& mStage; ///< Used to deliver touch events
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_KEY_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/long-press-gesture-detector-impl.cpp b/dali/internal/event/events/long-press-gesture-detector-impl.cpp
new file mode 100644 (file)
index 0000000..69ce40b
--- /dev/null
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "long-press-gesture-detector-impl.h"
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/long-press-gesture.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_LONG_PRESS_DETECTED = "long-press-detected";
+
+BaseHandle Create()
+{
+  return Dali::LongPressGestureDetector::New();
+}
+
+TypeRegistration mType( typeid(Dali::LongPressGestureDetector), typeid(Dali::GestureDetector), Create );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_LONG_PRESS_DETECTED, &LongPressGestureDetector::DoConnectSignal );
+
+}
+
+
+namespace
+{
+const unsigned int DEFAULT_TOUCHES_REQUIRED = 1;
+} // unnamed namespace
+
+LongPressGestureDetectorPtr LongPressGestureDetector::New()
+{
+  return new LongPressGestureDetector;
+}
+
+LongPressGestureDetectorPtr LongPressGestureDetector::New(unsigned int touchesRequired)
+{
+  return new LongPressGestureDetector(touchesRequired, touchesRequired);
+}
+
+LongPressGestureDetectorPtr LongPressGestureDetector::New(unsigned int minTouches, unsigned int maxTouches)
+{
+  return new LongPressGestureDetector(minTouches, maxTouches);
+}
+
+LongPressGestureDetector::LongPressGestureDetector()
+: GestureDetector(Gesture::LongPress),
+  mMinimumTouchesRequired(DEFAULT_TOUCHES_REQUIRED),
+  mMaximumTouchesRequired(DEFAULT_TOUCHES_REQUIRED)
+{
+}
+
+LongPressGestureDetector::LongPressGestureDetector(unsigned int minTouches, unsigned int maxTouches)
+: GestureDetector(Gesture::LongPress),
+  mMinimumTouchesRequired(minTouches),
+  mMaximumTouchesRequired(maxTouches)
+{
+}
+
+LongPressGestureDetector::~LongPressGestureDetector()
+{
+}
+
+void LongPressGestureDetector::SetTouchesRequired(unsigned int touches)
+{
+  DALI_ASSERT_ALWAYS( touches > 0 && "Can only set a positive number of required touches" );
+
+  if (mMinimumTouchesRequired != touches || mMaximumTouchesRequired != touches)
+  {
+    mMinimumTouchesRequired = mMaximumTouchesRequired = touches;
+
+    if (!mAttachedActors.empty())
+    {
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+void LongPressGestureDetector::SetTouchesRequired(unsigned int minTouches, unsigned int maxTouches)
+{
+  DALI_ASSERT_ALWAYS(minTouches > 0 && "Can only set a positive number of minimum touches");
+  DALI_ASSERT_ALWAYS(maxTouches > 0 && "Can only set a positive number of minimum touches");
+  DALI_ASSERT_ALWAYS(minTouches <= maxTouches && "Number of minimum touches must be less than maximum");
+
+  if (mMinimumTouchesRequired != minTouches || mMaximumTouchesRequired != maxTouches)
+  {
+    mMinimumTouchesRequired = minTouches;
+    mMaximumTouchesRequired = maxTouches;
+
+    if (!mAttachedActors.empty())
+    {
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+unsigned int LongPressGestureDetector::GetMinimumTouchesRequired() const
+{
+  return mMinimumTouchesRequired;
+}
+
+unsigned int LongPressGestureDetector::GetMaximumTouchesRequired() const
+{
+  return mMaximumTouchesRequired;
+}
+
+void LongPressGestureDetector::EmitLongPressGestureSignal(Dali::Actor pressedActor, const LongPressGesture& longPress)
+{
+  // Guard against destruction during signal emission
+  Dali::LongPressGestureDetector handle( this );
+
+  mDetectedSignal.Emit( pressedActor, longPress );
+}
+
+bool LongPressGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  LongPressGestureDetector* gesture = dynamic_cast<LongPressGestureDetector*>(object);
+
+  if ( 0 == strcmp( signalName.c_str(), SIGNAL_LONG_PRESS_DETECTED ) )
+  {
+    gesture->DetectedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void LongPressGestureDetector::OnActorAttach(Actor& actor)
+{
+  // Do nothing
+}
+
+void LongPressGestureDetector::OnActorDetach(Actor& actor)
+{
+  // Do nothing
+}
+
+void LongPressGestureDetector::OnActorDestroyed(Object& object)
+{
+  // Do nothing
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/long-press-gesture-detector-impl.h b/dali/internal/event/events/long-press-gesture-detector-impl.h
new file mode 100644 (file)
index 0000000..fc72eb4
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef __DALI_INTERNAL_LONG_PRESS_GESTURE_DETECTOR_H__
+#define __DALI_INTERNAL_LONG_PRESS_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/long-press-gesture-detector.h>
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+struct LongPressGesture;
+
+namespace Internal
+{
+
+class LongPressGestureDetector;
+
+typedef IntrusivePtr<LongPressGestureDetector> LongPressGestureDetectorPtr;
+typedef DerivedGestureDetectorContainer<LongPressGestureDetector>::type LongPressGestureDetectorContainer;
+
+/**
+ * @copydoc Dali::LongPressGestureDetector
+ */
+class LongPressGestureDetector : public GestureDetector
+{
+public: // Creation
+
+  /**
+   * Create a new gesture detector.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static LongPressGestureDetectorPtr New();
+
+  /**
+   * Create a new gesture detector with the specified touches.
+   * @param[in]  touchesRequired  The number of touches required.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static LongPressGestureDetectorPtr New(unsigned int touchesRequired);
+
+  /**
+   * Create a new gesture detector with the specified minimum and maximum touches.
+   * @param[in]  minTouches  The minimum number of touches required.
+   * @param[in]  maxTouches  The maximum number of touches required.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static LongPressGestureDetectorPtr New(unsigned int minTouches, unsigned int maxTouches);
+
+  /**
+   * Construct a new GestureDetector.
+   */
+  LongPressGestureDetector();
+
+  /**
+   * Create a new gesture detector with the specified minimum and maximum touches.
+   * @param[in]  minTouches  The minimum number of touches required.
+   * @param[in]  maxTouches  The maximum number of touches required.
+   */
+  LongPressGestureDetector(unsigned int minTouches, unsigned int maxTouches);
+
+public:
+
+  /**
+   * @copydoc Dali::LongPressGestureDetector::SetTouchesRequired(unsigned int)
+   */
+  void SetTouchesRequired(unsigned int touches);
+
+  /**
+   * @copydoc Dali::LongPressGestureDetector::SetTouchesRequired(unsigned int, unsigned int)
+   */
+  void SetTouchesRequired(unsigned int minTouches, unsigned int maxTouches);
+
+  /**
+   * @copydoc Dali::LongPressGestureDetector::GetMinimumTouchesRequired()
+   */
+  unsigned int GetMinimumTouchesRequired() const;
+
+  /**
+   * @copydoc Dali::LongPressGestureDetector::GetMaximumTouchesRequired()
+   */
+  unsigned int GetMaximumTouchesRequired() const;
+
+public:
+
+  /**
+   * Called by the LongPressGestureProcessor when a tap gesture event occurs within the bounds of our
+   * attached actor.
+   * @param[in]  pressedActor  The pressed actor.
+   * @param[in]  longPress     The long press
+   */
+  void EmitLongPressGestureSignal(Dali::Actor pressedActor, const LongPressGesture& longPress);
+
+public: // Signals
+
+  /**
+   * @copydoc Dali::LongPressGestureDetector::DetectedSignal()
+   */
+  Dali::LongPressGestureDetector::DetectedSignalType& DetectedSignal()
+  {
+    return mDetectedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~LongPressGestureDetector();
+
+private:
+
+  // Undefined
+  LongPressGestureDetector(const LongPressGestureDetector&);
+  LongPressGestureDetector& operator=(const LongPressGestureDetector& rhs);
+
+private: // GestureDetector overrides
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorAttach(Actor&)
+   */
+  virtual void OnActorAttach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDetach(Actor&)
+   */
+  virtual void OnActorDetach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDestroyed(Object&)
+   */
+  virtual void OnActorDestroyed(Object& object);
+
+private:
+
+  Dali::LongPressGestureDetector::DetectedSignalType mDetectedSignal;
+
+  unsigned int mMinimumTouchesRequired;
+  unsigned int mMaximumTouchesRequired;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::LongPressGestureDetector& GetImplementation(Dali::LongPressGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "LongPressGestureDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::LongPressGestureDetector&>(handle);
+}
+
+inline const Internal::LongPressGestureDetector& GetImplementation(const Dali::LongPressGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "LongPressGestureDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::LongPressGestureDetector&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_LONG_PRESS_GESTURE_DETECTOR_H__
diff --git a/dali/internal/event/events/long-press-gesture-processor.cpp b/dali/internal/event/events/long-press-gesture-processor.cpp
new file mode 100644 (file)
index 0000000..6fc846a
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "long-press-gesture-processor.h"
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/long-press-gesture.h>
+#include <dali/integration-api/events/long-press-gesture-event.h>
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * Creates a LongPressGesture and asks the specified detector to emit its detected signal.
+ * @param[in]  actor             The actor on which the long press gesture has occurred.
+ * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
+ * @param[in]  longPressEvent    The longPressEvent received from the adaptor.
+ * @param[in]  localPoint        Relative to the actor attached to the detector.
+ */
+void EmitLongPressSignal(
+    Actor* actor,
+    const GestureDetectorContainer& gestureDetectors,
+    const Integration::LongPressGestureEvent& longPressEvent,
+    Vector2 localPoint)
+{
+  LongPressGesture longPress(longPressEvent.state);
+  longPress.time = longPressEvent.time;
+  longPress.numberOfTouches = longPressEvent.numberOfTouches;
+  longPress.screenPoint = longPressEvent.point;
+  longPress.localPoint = localPoint;
+
+  Dali::Actor actorHandle( actor );
+  const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
+  for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
+  {
+    static_cast< LongPressGestureDetector* >( *iter )->EmitLongPressGestureSignal( actorHandle, longPress );
+  }
+}
+
+/**
+ * Functor which checks whether the specified actor is attached to the gesture detector.
+ * It returns true if it is no longer attached.  This can be used in remove_if functions.
+ */
+struct IsNotAttachedFunctor
+{
+  /**
+   * Constructor
+   * @param[in]  actor  The actor to check whether it is attached.
+   */
+  IsNotAttachedFunctor( Actor* actor )
+  : actorToCheck( actor )
+  {
+  }
+
+  /**
+   * Returns true if not attached, false if it is still attached.
+   * @param[in]  detector  The detector to check.
+   * @return true, if not attached, false otherwise.
+   */
+  bool operator()( const GestureDetector* detector ) const
+  {
+    return !detector->IsAttached( *actorToCheck );
+  }
+
+  Actor* actorToCheck; ///< The actor to check whether it is attached or not.
+};
+
+} // unnamed namespace
+
+LongPressGestureProcessor::LongPressGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager)
+: GestureProcessor( Gesture::LongPress ),
+  mStage( stage ),
+  mGestureManager( gestureManager ),
+  mGestureDetectors(),
+  mCurrentEmitters(),
+  mCurrentRenderTask(),
+  mMinTouchesRequired( 1 ),
+  mMaxTouchesRequired( 1 ),
+  mCurrentLongPressEvent( NULL )
+{
+}
+
+LongPressGestureProcessor::~LongPressGestureProcessor()
+{
+}
+
+void LongPressGestureProcessor::Process( const Integration::LongPressGestureEvent& longPressEvent )
+{
+  switch ( longPressEvent.state )
+  {
+    case Gesture::Possible:
+    {
+      mCurrentEmitters.clear();
+      ResetActor();
+
+      HitTestAlgorithm::Results hitTestResults;
+      if( HitTest( mStage, longPressEvent.point, hitTestResults ) )
+      {
+        SetActor( &GetImplementation( hitTestResults.actor ) );
+      }
+      break;
+    }
+
+    case Gesture::Started:
+    {
+      Actor* currentGesturedActor = GetCurrentGesturedActor();
+      if ( currentGesturedActor )
+      {
+        HitTestAlgorithm::Results hitTestResults;
+        HitTest( mStage, longPressEvent.point, hitTestResults );
+
+        if ( hitTestResults.actor && ( currentGesturedActor == &GetImplementation( hitTestResults.actor ) ) )
+        {
+          // Record the current render-task for Screen->Actor coordinate conversions
+          mCurrentRenderTask = hitTestResults.renderTask;
+
+          // Set mCurrentLongPressEvent to use inside overridden methods called from ProcessAndEmit()
+          mCurrentLongPressEvent = &longPressEvent;
+          ProcessAndEmit( hitTestResults );
+          mCurrentLongPressEvent = NULL;
+        }
+        else
+        {
+          mCurrentEmitters.clear();
+          ResetActor();
+        }
+      }
+      break;
+    }
+
+    case Gesture::Finished:
+    {
+      // The gesture should only be sent to the gesture detector which first received it so that it
+      // can be told when the gesture ends as well.
+
+      // Only send subsequent long press gesture signals if we processed the gesture when it started.
+      // Check if actor is still touchable.
+
+      Actor* currentGesturedActor = GetCurrentGesturedActor();
+      if ( currentGesturedActor )
+      {
+        if ( currentGesturedActor->IsHittable() && !mCurrentEmitters.empty() && mCurrentRenderTask )
+        {
+          // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
+          GestureDetectorContainer::iterator endIter = std::remove_if( mCurrentEmitters.begin(), mCurrentEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
+          mCurrentEmitters.erase( endIter, mCurrentEmitters.end() );
+
+          if ( !mCurrentEmitters.empty() )
+          {
+            Vector2 actorCoords;
+            RenderTask& renderTaskImpl( GetImplementation( mCurrentRenderTask ) );
+            currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, longPressEvent.point.x, longPressEvent.point.y );
+
+            EmitLongPressSignal( currentGesturedActor, mCurrentEmitters, longPressEvent, actorCoords );
+          }
+        }
+
+        // Clear current emitters and emitted actor
+        mCurrentEmitters.clear();
+        ResetActor();
+      }
+      break;
+    }
+
+    case Gesture::Cancelled:
+    {
+      mCurrentEmitters.clear();
+      ResetActor();
+      break;
+    }
+
+    case Gesture::Continuing:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
+      break;
+
+    case Gesture::Clear:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
+      break;
+  }
+}
+
+void LongPressGestureProcessor::AddGestureDetector( LongPressGestureDetector* gestureDetector )
+{
+  bool firstRegistration(mGestureDetectors.empty());
+
+  mGestureDetectors.push_back(gestureDetector);
+
+  if (firstRegistration)
+  {
+    mMinTouchesRequired = gestureDetector->GetMinimumTouchesRequired();
+    mMaxTouchesRequired = gestureDetector->GetMaximumTouchesRequired();
+
+    Integration::LongPressGestureRequest request;
+    request.minTouches = mMinTouchesRequired;
+    request.maxTouches = mMaxTouchesRequired;
+    mGestureManager.Register( request );
+  }
+  else
+  {
+    UpdateDetection();
+  }
+}
+
+void LongPressGestureProcessor::RemoveGestureDetector( LongPressGestureDetector* gestureDetector )
+{
+  // Find detector ...
+  LongPressGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
+  DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
+
+  // ... and remove it
+  mGestureDetectors.erase( endIter, mGestureDetectors.end() );
+
+  if ( mGestureDetectors.empty() )
+  {
+    Integration::GestureRequest request( Gesture::LongPress );
+    mGestureManager.Unregister(request);
+  }
+  else
+  {
+    UpdateDetection();
+  }
+}
+
+void LongPressGestureProcessor::GestureDetectorUpdated( LongPressGestureDetector* gestureDetector )
+{
+  DALI_ASSERT_DEBUG( find( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector ) != mGestureDetectors.end() );
+
+  UpdateDetection();
+}
+
+void LongPressGestureProcessor::UpdateDetection()
+{
+  DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
+
+  unsigned int minimumRequired = UINT_MAX;
+  unsigned int maximumRequired = 0;
+
+  for ( LongPressGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
+  {
+    LongPressGestureDetector* current(*iter);
+
+    unsigned int minimum = current->GetMinimumTouchesRequired();
+    if (minimum < minimumRequired)
+    {
+      minimumRequired = minimum;
+    }
+
+    unsigned int maximum = current->GetMaximumTouchesRequired();
+    if ( maximum > maximumRequired )
+    {
+      maximumRequired = maximum;
+    }
+  }
+
+  if ( (minimumRequired != mMinTouchesRequired) || (maximumRequired != mMaxTouchesRequired) )
+  {
+    mMinTouchesRequired = minimumRequired;
+    mMaxTouchesRequired = maximumRequired;
+
+    Integration::LongPressGestureRequest request;
+    request.minTouches = mMinTouchesRequired;
+    request.maxTouches = mMaxTouchesRequired;
+    mGestureManager.Update(request);
+  }
+}
+
+void LongPressGestureProcessor::OnGesturedActorStageDisconnection()
+{
+  mCurrentEmitters.clear();
+}
+
+bool LongPressGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
+{
+  DALI_ASSERT_DEBUG( mCurrentLongPressEvent );
+
+  LongPressGestureDetector* longPressDetector ( static_cast< LongPressGestureDetector* >( detector ) );
+
+  return ( longPressDetector->GetMinimumTouchesRequired() <= mCurrentLongPressEvent->numberOfTouches ) &&
+         ( longPressDetector->GetMaximumTouchesRequired() >= mCurrentLongPressEvent->numberOfTouches );
+}
+
+void LongPressGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
+{
+  DALI_ASSERT_DEBUG( mCurrentLongPressEvent );
+
+  mCurrentEmitters.clear();
+  ResetActor();
+
+  EmitLongPressSignal( actor, gestureDetectors, *mCurrentLongPressEvent, actorCoordinates );
+
+  if ( actor->OnStage() )
+  {
+    mCurrentEmitters = gestureDetectors;
+    SetActor( actor );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/long-press-gesture-processor.h b/dali/internal/event/events/long-press-gesture-processor.h
new file mode 100644 (file)
index 0000000..d34f246
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef __DALI_INTERNAL_LONG_PRESS_GESTURE_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_LONG_PRESS_GESTURE_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/long-press-gesture-detector-impl.h>
+#include <dali/internal/event/events/gesture-processor.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GestureManager;
+struct GestureEvent;
+struct LongPressGestureEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+/**
+ * Long Press Gesture Event Processing:
+ *
+ * When we receive a long press gesture event, we do the following:
+ * - Find the actor that requires a long-press at the long press position.
+ * - Emit the gesture if the event satisfies the detector conditions.
+ */
+class LongPressGestureProcessor : public GestureProcessor
+{
+public:
+
+  /**
+   * Create a long press gesture processor.
+   * @param[in] stage The stage.
+   * @param[in] gestureManager The gesture manager.
+   */
+  LongPressGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager );
+
+  /**
+   * Non-virtual destructor; LongPressGestureProcessor is not a base class
+   */
+  ~LongPressGestureProcessor();
+
+public: // To be called by GestureEventProcessor
+
+  /**
+   * This method is called whenever a long press gesture event occurs.
+   * @param[in] longPressEvent The event that has occurred.
+   */
+  void Process( const Integration::LongPressGestureEvent& longPressEvent );
+
+  /**
+   * Adds a gesture detector to this gesture processor.
+   * If this is the first gesture detector being added, then this method registers the required
+   * gesture with the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being added.
+   */
+  void AddGestureDetector( LongPressGestureDetector* gestureDetector );
+
+  /**
+   * Removes the specified gesture detector from this gesture processor.  If, after removing this
+   * gesture detector, there are no more gesture detectors registered, then this method unregisters
+   * the gesture from the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being removed.
+   */
+  void RemoveGestureDetector( LongPressGestureDetector* gestureDetector );
+
+  /**
+   * This method updates the gesture detection parameters.
+   * @param[in]  gestureDetector  The gesture detector that has been updated.
+   */
+  void GestureDetectorUpdated(LongPressGestureDetector* gestureDetector);
+
+private:
+
+  // Undefined
+  LongPressGestureProcessor( const LongPressGestureProcessor& );
+  LongPressGestureProcessor& operator=( const LongPressGestureProcessor& rhs );
+
+private:
+
+  /**
+   * Iterates through our GestureDetectors and determines if we need to ask the adaptor to update
+   * its detection policy.  If it does, it sends the appropriate gesture update request to adaptor.
+   */
+  void UpdateDetection();
+
+  // GestureProcessor overrides
+
+  /**
+   * @copydoc GestureProcessor::OnGesturedActorStageDisconnection()
+   */
+  void OnGesturedActorStageDisconnection();
+
+  /**
+   * @copydoc GestureProcessor::CheckGestureDetector()
+   */
+  bool CheckGestureDetector( GestureDetector* detector, Actor* actor );
+
+  /**
+   * @copydoc GestureProcessor::EmitGestureSignal()
+   */
+  void EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates );
+
+private:
+
+  Stage& mStage;
+  Integration::GestureManager& mGestureManager;
+  LongPressGestureDetectorContainer mGestureDetectors;
+
+  GestureDetectorContainer mCurrentEmitters;
+  Dali::RenderTask mCurrentRenderTask;
+
+  unsigned int mMinTouchesRequired;
+  unsigned int mMaxTouchesRequired;
+
+  const Integration::LongPressGestureEvent* mCurrentLongPressEvent; ///< Pointer to current longPressEvent, used when calling ProcessAndEmit()
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_LONG_PRESS_GESTURE_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/multi-point-event-util.cpp b/dali/internal/event/events/multi-point-event-util.cpp
new file mode 100644 (file)
index 0000000..d762508
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#endif
+
+// CLASS HEADER
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+
+static bool HIERARCHY_GEOMETRY(false);
+static bool HIERARCHY_SENSITIVITY(false);
+static bool HIERARCHY_TOUCH_REQUIRED(false);
+static bool HIERARCHY_HOVER_REQUIRED(false);
+static bool HIERARCHY_HITTABLE(false);
+
+static const Debug::LogLevel HIERARCHY_DEBUG_LOG_LEVEL( Debug::Verbose );
+
+void PrintChildren( Debug::Filter* logFilter, Dali::Actor actor, int level )
+{
+  std::ostringstream output;
+
+  for ( int t = 0; t < level; ++t )
+  {
+    output << " | ";
+  }
+
+  output << actor.GetName() << "(" << actor.GetTypeName() << ", " << actor.GetObjectPtr() << ")";
+
+  if ( HIERARCHY_GEOMETRY )
+  {
+    output << " Pos: " << actor.GetCurrentWorldPosition() << " Size: " << actor.GetCurrentSize() << " Scale: " << actor.GetCurrentWorldScale();
+  }
+
+  if ( HIERARCHY_SENSITIVITY )
+  {
+    output << " Sensitivity: " << ( IsActuallySensitive( &GetImplementation( actor ) ) ? "True " : "False " );
+  }
+
+  if ( HIERARCHY_TOUCH_REQUIRED )
+  {
+    output << " TouchRequired: " << ( GetImplementation(actor).GetTouchRequired() ? "True " : "False " );
+  }
+
+  if ( HIERARCHY_HOVER_REQUIRED )
+  {
+    output << " HoverRequired: " << ( GetImplementation(actor).GetHoverRequired() ? "True " : "False " );
+  }
+
+  if ( HIERARCHY_HITTABLE )
+  {
+    output << " Hittable: " << ( GetImplementation(actor).IsHittable() ? "True " : "False " );
+  }
+
+  output << std::endl;
+
+  if( logFilter )
+  {
+    DALI_LOG_INFO( logFilter, HIERARCHY_DEBUG_LOG_LEVEL, output.str().c_str() );
+  }
+
+  ++level;
+  unsigned int numChildren=actor.GetChildCount();
+  for ( unsigned int i=0; i<numChildren; ++i )
+  {
+    PrintChildren( logFilter, actor.GetChildAt(i), level );
+  }
+  --level;
+}
+
+void PrintHierarchy( Debug::Filter* logFilter )
+{
+  if ( logFilter && logFilter->IsEnabledFor( HIERARCHY_DEBUG_LOG_LEVEL ) )
+  {
+    PrintChildren( logFilter, Dali::Stage().GetCurrent().GetRootLayer(), 0 );
+  }
+}
+
+#endif // defined(DEBUG_ENABLED)
+
+bool IsActuallySensitive( Actor* actor )
+{
+  bool sensitive = true;
+
+  while ( actor && sensitive )
+  {
+    sensitive = actor->IsSensitive();
+    actor = actor->GetParent();
+  }
+
+  return sensitive;
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/events/multi-point-event-util.h b/dali/internal/event/events/multi-point-event-util.h
new file mode 100644 (file)
index 0000000..780c174
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+#define __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+
+/**
+ * Prints out all the children of the given actor when debug is enabled.
+ *
+ * @param[in]  actor  The actor whose children to print.
+ * @param[in]  level  The number of " | " to put in front of the children.
+ */
+void PrintChildren( Debug::Filter* logFilter, Dali::Actor actor, int level );
+
+/**
+ * Prints the entire hierarchy of the scene.
+ */
+void PrintHierarchy( Debug::Filter* logFilter );
+
+#define PRINT_HIERARCHY(f) PrintHierarchy(f)
+
+#else // defined(DEBUG_ENABLED)
+
+#define PRINT_HIERARCHY(f)
+
+#endif // defined(DEBUG_ENABLED)
+
+/**
+ * In the hit test algorithm above we do not descend actor tree if it is insensitive, so here, we
+ * should also check if any of the actor's parents has become insensitive since we last processed
+ * it.
+ */
+bool IsActuallySensitive( Actor* actor );
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_MULTI_POINT_EVENT_UTIL_H__
+
diff --git a/dali/internal/event/events/pan-gesture-detector-impl.cpp b/dali/internal/event/events/pan-gesture-detector-impl.cpp
new file mode 100644 (file)
index 0000000..bb830ab
--- /dev/null
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/pan-gesture-detector-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/pan-gesture.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Properties
+
+//              Name                  Type   writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "screen-position",     VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_POSITION     )
+DALI_PROPERTY( "screen-displacement", VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT )
+DALI_PROPERTY( "screen-velocity",     VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::SCREEN_VELOCITY     )
+DALI_PROPERTY( "local-position",      VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_POSITION      )
+DALI_PROPERTY( "local-displacement",  VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT  )
+DALI_PROPERTY( "local-velocity",      VECTOR2, false, false, true,   Dali::PanGestureDetector::Property::LOCAL_VELOCITY      )
+DALI_PROPERTY( "panning",             BOOLEAN, false, false, true,   Dali::PanGestureDetector::Property::PANNING             )
+DALI_PROPERTY_TABLE_END( DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX )
+
+// Signals
+
+const char* const SIGNAL_PAN_DETECTED = "pan-detected";
+
+BaseHandle Create()
+{
+  return Dali::PanGestureDetector::New();
+}
+
+TypeRegistration mType( typeid(Dali::PanGestureDetector), typeid(Dali::GestureDetector), Create );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_PAN_DETECTED, &PanGestureDetector::DoConnectSignal );
+
+#if defined(DEBUG_ENABLED)
+Integration::Log::Filter* gLogFilter  = Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_PAN_GESTURE_DETECTOR");
+#endif
+
+/**
+ * Returns the angle going in the opposite direction to that specified by angle.
+ */
+float GetOppositeAngle( float angle )
+{
+  // Calculate the opposite angle so that we cover both directions.
+  if ( angle <= 0.0f )
+  {
+    angle += Math::PI;
+  }
+  else
+  {
+    angle -= Math::PI;
+  }
+
+  return angle;
+}
+
+} // unnamed namespace
+
+PanGestureDetectorPtr PanGestureDetector::New()
+{
+  return new PanGestureDetector;
+}
+
+PanGestureDetector::PanGestureDetector()
+: GestureDetector(Gesture::Pan),
+  mMinimumTouches(1),
+  mMaximumTouches(1),
+  mSceneObject(NULL)
+{
+}
+
+PanGestureDetector::~PanGestureDetector()
+{
+}
+
+void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
+{
+  DALI_ASSERT_ALWAYS( minimum > 0 && "Can only set a positive number of required touches" );
+
+  if (mMinimumTouches != minimum)
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "Minimum Touches Set: %d\n", minimum );
+
+    mMinimumTouches = minimum;
+
+    if (!mAttachedActors.empty())
+    {
+      DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
+
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
+{
+  DALI_ASSERT_ALWAYS( maximum > 0 && "Can only set a positive number of maximum touches" );
+
+  if (mMaximumTouches != maximum)
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "Maximum Touches Set: %d\n", maximum );
+
+    mMaximumTouches = maximum;
+
+    if (!mAttachedActors.empty())
+    {
+      DALI_LOG_INFO( gLogFilter, Debug::General, "Updating Gesture Detector\n");
+
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+unsigned int PanGestureDetector::GetMinimumTouchesRequired() const
+{
+  return mMinimumTouches;
+}
+
+unsigned int PanGestureDetector::GetMaximumTouchesRequired() const
+{
+  return mMaximumTouches;
+}
+
+void PanGestureDetector::AddAngle( Radian angle, Radian threshold )
+{
+  threshold = fabsf( threshold ); // Ensure the threshold is positive.
+
+  // If the threshold is greater than PI, then just use PI
+  // This means that any panned angle will invoke the pan gesture. We should still add this angle as
+  // an angle may have been added previously with a small threshold.
+  if ( threshold > Math::PI )
+  {
+    threshold = Math::PI;
+  }
+
+  angle = WrapInDomain( angle, -Math::PI, Math::PI );
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "Angle Added: %.2f, Threshold: %.2f\n", Degree(angle), Degree(threshold) );
+
+  AngleThresholdPair pair( angle, threshold );
+  mAngleContainer.push_back( pair );
+}
+
+void PanGestureDetector::AddDirection( Radian direction, Radian threshold )
+{
+  AddAngle( direction, threshold );
+
+  // Calculate the opposite angle so that we cover the entire direction.
+  direction = GetOppositeAngle( direction );
+
+  AddAngle( direction, threshold );
+}
+
+size_t PanGestureDetector::GetAngleCount() const
+{
+  return mAngleContainer.size();
+}
+
+PanGestureDetector::AngleThresholdPair PanGestureDetector::GetAngle(size_t index) const
+{
+  PanGestureDetector::AngleThresholdPair ret( Radian(0),Radian(0) );
+
+  if( index < mAngleContainer.size() )
+  {
+    ret = mAngleContainer[index];
+  }
+
+  return ret;
+}
+
+
+void PanGestureDetector::ClearAngles()
+{
+  mAngleContainer.clear();
+}
+
+void PanGestureDetector::RemoveAngle( Radian angle )
+{
+  angle = WrapInDomain( angle, -Math::PI, Math::PI );
+
+  for (AngleContainer::iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
+  {
+    if ( iter->first == angle )
+    {
+      mAngleContainer.erase( iter );
+      break;
+    }
+  }
+}
+
+void PanGestureDetector::RemoveDirection( Radian direction )
+{
+  RemoveAngle( direction );
+
+  // Calculate the opposite angle so that we cover the entire direction.
+  direction = GetOppositeAngle( direction );
+
+  RemoveAngle( direction );
+}
+
+bool PanGestureDetector::RequiresDirectionalPan() const
+{
+  // If no directional angles have been added to the container then we do not require directional panning
+  return !mAngleContainer.empty();
+}
+
+bool PanGestureDetector::CheckAngleAllowed( Radian angle ) const
+{
+  bool allowed( false );
+  if ( mAngleContainer.empty() )
+  {
+    allowed = true;
+  }
+  else
+  {
+    for ( AngleContainer::const_iterator iter = mAngleContainer.begin(), endIter = mAngleContainer.end(); iter != endIter; ++iter )
+    {
+      float angleAllowed( iter->first );
+      float threshold ( iter->second );
+
+      DALI_LOG_INFO( gLogFilter, Debug::General,
+                     "AngleToCheck: %.2f, CompareWith: %.2f, Threshold: %.2f\n",
+                     Degree(angle), Degree(angleAllowed), Degree(threshold) );
+
+      float relativeAngle( fabsf( WrapInDomain( angle - angleAllowed, -Math::PI, Math::PI ) ) );
+      if ( relativeAngle <= threshold )
+      {
+        allowed = true;
+        break;
+      }
+    }
+  }
+
+  return allowed;
+}
+
+void PanGestureDetector::EmitPanGestureSignal(Dali::Actor actor, const PanGesture& pan)
+{
+  if ( !mDetectedSignal.Empty() )
+  {
+    // Guard against destruction during signal emission
+    Dali::PanGestureDetector handle( this );
+
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "Emitting Signal (%p)\n", this );
+
+    mDetectedSignal.Emit( actor, pan );
+  }
+}
+
+void PanGestureDetector::SetSceneObject( const SceneGraph::PanGesture* object )
+{
+  mSceneObject = object;
+}
+
+bool PanGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  PanGestureDetector* gesture = dynamic_cast<PanGestureDetector*>(object);
+
+  if ( 0 == strcmp( signalName.c_str(), SIGNAL_PAN_DETECTED ) )
+  {
+    gesture->DetectedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void PanGestureDetector::SetPanGestureProperties( const PanGesture& pan )
+{
+  ThreadLocalStorage::Get().GetGestureEventProcessor().SetGestureProperties( pan );
+}
+
+void PanGestureDetector::OnActorAttach(Actor& actor)
+{
+  // Do nothing
+}
+
+void PanGestureDetector::OnActorDetach(Actor& actor)
+{
+  // Do nothing
+}
+
+void PanGestureDetector::OnActorDestroyed(Object& object)
+{
+  // Do nothing
+}
+
+unsigned int PanGestureDetector::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void PanGestureDetector::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  int index = DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX;
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i, ++index )
+  {
+    indices.PushBack( index );
+  }
+}
+
+const char* PanGestureDetector::GetDefaultPropertyName( Property::Index index ) const
+{
+  index -= DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].name;
+  }
+
+  return NULL;
+}
+
+Property::Index PanGestureDetector::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    const Internal::PropertyDetails* property = &DEFAULT_PROPERTY_DETAILS[ i ];
+    if( 0 == strcmp( name.c_str(), property->name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+  return index;
+}
+
+bool PanGestureDetector::IsDefaultPropertyWritable(Property::Index index) const
+{
+  // None of our properties should be writable through the Public API
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX ].writable;
+}
+
+bool PanGestureDetector::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  // None of our properties are animatable
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX ].animatable;
+}
+
+bool PanGestureDetector::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  // All our properties can be used as an input to a constraint.
+  return DEFAULT_PROPERTY_DETAILS[ index - DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX ].constraintInput;
+}
+
+Property::Type PanGestureDetector::GetDefaultPropertyType(Property::Index index) const
+{
+  index -= DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX;
+  if ( ( index >= 0 ) && ( index < DEFAULT_PROPERTY_COUNT ) )
+  {
+    return DEFAULT_PROPERTY_DETAILS[ index ].type;
+  }
+  else
+  {
+    // Index out-of-range
+    return Property::NONE;
+  }
+}
+
+void PanGestureDetector::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  // None of our properties should be settable from Public API
+}
+
+Property::Value PanGestureDetector::GetDefaultProperty(Property::Index index) const
+{
+  Property::Value value;
+
+  switch ( index )
+  {
+    case Dali::PanGestureDetector::Property::SCREEN_POSITION:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetScreenPositionProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetScreenDisplacementProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetScreenVelocityProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::LOCAL_POSITION:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetLocalPositionProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetLocalDisplacementProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetLocalVelocityProperty().Get();
+      }
+      else
+      {
+        value = Vector2();
+      }
+      break;
+    }
+
+    case Dali::PanGestureDetector::Property::PANNING:
+    {
+      if(mSceneObject)
+      {
+        value = mSceneObject->GetPanningProperty().Get();
+      }
+      else
+      {
+        value = false;
+      }
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false && "PanGestureDetector Property index invalid" ); // should not come here
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* PanGestureDetector::GetSceneObject() const
+{
+  // This method should only return an object connected to the scene-graph
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* PanGestureDetector::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
+
+  // None of our properties are animatable
+  return NULL;
+}
+
+const PropertyInputImpl* PanGestureDetector::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property( NULL );
+
+  // This method should only return a property of an object connected to the scene-graph
+  if ( !mSceneObject )
+  {
+    return property;
+  }
+
+  if ( index >= DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    CustomPropertyMetadata* custom = FindCustomProperty( index );
+    DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+    property = custom->GetSceneGraphProperty();
+  }
+  else
+  {
+    switch ( index )
+    {
+      case Dali::PanGestureDetector::Property::SCREEN_POSITION:
+      {
+        property = &mSceneObject->GetScreenPositionProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::SCREEN_DISPLACEMENT:
+      {
+        property = &mSceneObject->GetScreenDisplacementProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::SCREEN_VELOCITY:
+      {
+        property = &mSceneObject->GetScreenVelocityProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::LOCAL_POSITION:
+      {
+        property = &mSceneObject->GetLocalPositionProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::LOCAL_DISPLACEMENT:
+      {
+        property = &mSceneObject->GetLocalDisplacementProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::LOCAL_VELOCITY:
+      {
+        property = &mSceneObject->GetLocalVelocityProperty();
+        break;
+      }
+
+      case Dali::PanGestureDetector::Property::PANNING:
+      {
+        property = &mSceneObject->GetPanningProperty();
+        break;
+      }
+
+      default:
+        break;
+    }
+  }
+
+  return property;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/pan-gesture-detector-impl.h b/dali/internal/event/events/pan-gesture-detector-impl.h
new file mode 100644 (file)
index 0000000..ebf040e
--- /dev/null
@@ -0,0 +1,318 @@
+#ifndef __DALI_INTERNAL_PAN_GESTURE_DETECTOR_H__
+#define __DALI_INTERNAL_PAN_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/events/pan-gesture-detector.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+struct TouchEvent;
+struct Radian;
+
+namespace Internal
+{
+
+class PanGestureDetector;
+typedef IntrusivePtr<PanGestureDetector> PanGestureDetectorPtr;
+typedef DerivedGestureDetectorContainer<PanGestureDetector>::type PanGestureDetectorContainer;
+
+namespace SceneGraph
+{
+class PanGesture;
+}
+
+/**
+ * @copydoc Dali::PanGestureDetector
+ */
+class PanGestureDetector : public GestureDetector
+{
+public: // Typedefs
+
+  typedef Dali::PanGestureDetector::AngleThresholdPair AngleThresholdPair;
+  typedef std::vector<AngleThresholdPair> AngleContainer;
+
+public: // Creation
+
+  /**
+   * Create a new gesture detector.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static PanGestureDetectorPtr New();
+
+  /**
+   * Construct a new PanGestureDetector.
+   */
+  PanGestureDetector();
+
+public:
+
+  /**
+   * @copydoc Dali::PanGestureDetector::SetMinimumTouchesRequired(unsigned int)
+   */
+  void SetMinimumTouchesRequired(unsigned int minimum);
+
+  /**
+   * @copydoc Dali::PanGestureDetector::SetMaximumTouchesRequired(unsigned int)
+   */
+  void SetMaximumTouchesRequired(unsigned int maximum);
+
+  /**
+   * @copydoc Dali::PanGestureDetector::GetMinimumTouchesRequired() const
+   */
+  unsigned int GetMinimumTouchesRequired() const;
+
+  /**
+   * @copydoc Dali::PanGestureDetector::GetMaximumTouchesRequired() const
+   */
+  unsigned int GetMaximumTouchesRequired() const;
+
+  /**
+   * @copydoc Dali::PanGestureDetector::AddAngle()
+   */
+  void AddAngle( Radian angle, Radian threshold );
+
+  /**
+   * @copydoc Dali::PanGestureDetector::AddDirection()
+   */
+  void AddDirection( Radian direction, Radian threshold );
+
+  /**
+   * @copydoc Dali::PanGestureDetector::GetAngleCount()
+   */
+  size_t GetAngleCount() const;
+
+  /**
+   * @copydoc Dali::PanGestureDetector::GetAngle()
+   */
+  AngleThresholdPair GetAngle(size_t index) const;
+
+  /**
+   * @copydoc Dali::PanGestureDetector::ClearAngles()
+   */
+  void ClearAngles();
+
+  /**
+   * @copydoc Dali::PanGestureDetector::RemoveAngle()
+   */
+  void RemoveAngle( Radian angle );
+
+  /**
+   * @copydoc Dali::PanGestureDetector::RemoveDirection()
+   */
+  void RemoveDirection( Radian direction );
+
+  /**
+   * Checks whether the pan gesture detector requires a directional pan for emission.
+   * @return true, if directional panning required, false otherwise.
+   */
+  bool RequiresDirectionalPan() const;
+
+  /**
+   * Checks whether the given pan angle is allowed for this gesture detector.
+   * @param[in]  angle  The angle to check.
+   */
+  bool CheckAngleAllowed( Radian angle ) const;
+
+public:
+
+  /**
+   * Called by the PanGestureProcessor when a pan gesture event occurs within the bounds of our
+   * attached actor.
+   * @param[in]  actor  The panned actor.
+   * @param[in]  pan    The pan gesture.
+   */
+  void EmitPanGestureSignal(Dali::Actor actor, const PanGesture& pan);
+
+  /**
+   * Called by the PanGestureProcessor to set the scene object.
+   * @param[in]  object  The scene object.
+   */
+  void SetSceneObject( const SceneGraph::PanGesture* object );
+
+public: // Signals
+
+  /**
+   * @copydoc Dali::PanGestureDetector::DetectedSignal()
+   */
+  Dali::PanGestureDetector::DetectedSignalType& DetectedSignal()
+  {
+    return mDetectedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+public: // Override Pan Gesture
+
+  /**
+   * @copydoc Dali::PanGestureDetector::SetPanGestureProperties()
+   */
+  static void SetPanGestureProperties( const PanGesture& pan );
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~PanGestureDetector();
+
+private:
+
+  // Undefined
+  PanGestureDetector(const PanGestureDetector&);
+
+  // Undefined
+  PanGestureDetector& operator=(const PanGestureDetector& rhs);
+
+  // From GestureDetector
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorAttach(Actor&)
+   */
+  virtual void OnActorAttach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDetach(Actor&)
+   */
+  virtual void OnActorDetach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDestroyed(Object&)
+   */
+  virtual void OnActorDestroyed(Object& object);
+
+
+  // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+private:
+
+  Dali::PanGestureDetector::DetectedSignalType mDetectedSignal;
+
+  unsigned int mMinimumTouches; ///< The minimum number of fingers required to be touching for pan.
+  unsigned int mMaximumTouches; ///< The maximum number of fingers required to be touching for pan.
+
+  AngleContainer mAngleContainer; ///< A container of all angles allowed for pan to occur.
+
+  const SceneGraph::PanGesture* mSceneObject; ///< Not owned
+
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::PanGestureDetector& GetImplementation(Dali::PanGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "PanGestureDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::PanGestureDetector&>(handle);
+}
+
+inline const Internal::PanGestureDetector& GetImplementation(const Dali::PanGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "PanGestureDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::PanGestureDetector&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PAN_GESTURE_DETECTOR_H__
diff --git a/dali/internal/event/events/pan-gesture-processor.cpp b/dali/internal/event/events/pan-gesture-processor.cpp
new file mode 100644 (file)
index 0000000..7f44778
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/pan-gesture-processor.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/pan-gesture.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/events/pan-gesture-event.h>
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+const unsigned long MAXIMUM_TIME_WITH_VALID_LAST_VELOCITY( 50u );
+
+/**
+ * Functor which checks whether the specified actor is attached to the gesture detector.
+ * If the actor is attached, it also checks whether the number of touches of the current pan event
+ * are within the range of that expected by the detector.
+ * It returns true if it is no longer attached or the touches are out of range.
+ * This can be used in remove_if functions.
+ */
+struct IsNotAttachedAndOutsideTouchesRangeFunctor
+{
+  /**
+   * Constructor
+   * @param[in]  actor                 The actor to check whether it is attached.
+   * @param[in]  touches               The number of touches in the current pan event.
+   * @param[in]  outsideRangeEmitters  Reference to container where emitters outside of the touches range should be added.
+   */
+  IsNotAttachedAndOutsideTouchesRangeFunctor(Actor* actor, unsigned int touches, GestureDetectorContainer& outsideRangeEmitters)
+  : actorToCheck(actor),
+    numberOfTouches(touches),
+    outsideTouchesRangeEmitters(outsideRangeEmitters)
+  {
+  }
+
+  /**
+   * Returns true if not attached, false if it is still attached.
+   * Additionally, checks if the number of touches has changed and stops sending the pan to a particular
+   * detector if it exceeds the range of that detector.
+   * @param[in]  detector  The detector to check.
+   * @return true, if not attached, false otherwise.
+   */
+  bool operator()(GestureDetector* detector) const
+  {
+    bool remove(!detector->IsAttached(*actorToCheck));
+
+    if (!remove)
+    {
+      PanGestureDetector* panDetector( static_cast< PanGestureDetector* >( detector ) );
+
+      // Ensure number of touch points is within the range of our emitter. If it isn't then remove
+      // this emitter and add it to the outsideTouchesRangeEmitters container
+      if ( (numberOfTouches < panDetector->GetMinimumTouchesRequired()) ||
+           (numberOfTouches > panDetector->GetMaximumTouchesRequired()) )
+      {
+        remove = true;
+        outsideTouchesRangeEmitters.push_back(detector);
+      }
+    }
+
+    return remove;
+  }
+
+  Actor* actorToCheck; ///< The actor to check whether it is attached or not.
+  unsigned int numberOfTouches; ///< The number of touches in the pan event.
+  GestureDetectorContainer& outsideTouchesRangeEmitters; ///< Emitters that are outside of the range of current pan.
+};
+
+} // unnamed namespace
+
+PanGestureProcessor::PanGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager )
+: GestureProcessor( Gesture::Pan ),
+  mStage( stage ),
+  mGestureManager( gestureManager ),
+  mGestureDetectors(),
+  mCurrentPanEmitters(),
+  mCurrentRenderTask(),
+  mPossiblePanPosition(),
+  mMinTouchesRequired( 1 ),
+  mMaxTouchesRequired( 1 ),
+  mCurrentPanEvent( NULL ),
+  mSceneObject( SceneGraph::PanGesture::New() ) // Create scene object to store pan information.
+{
+  // Pass ownership to scene-graph
+  AddGestureMessage( mStage.GetUpdateManager(), mSceneObject );
+}
+
+PanGestureProcessor::~PanGestureProcessor()
+{
+  if( Stage::IsInstalled() && ( mSceneObject != NULL ) )
+  {
+    RemoveGestureMessage( mStage.GetUpdateManager(), mSceneObject );
+    mSceneObject = NULL; // mSceneObject is about to be destroyed
+  }
+}
+
+void PanGestureProcessor::Process( const Integration::PanGestureEvent& panEvent )
+{
+  switch( panEvent.state )
+  {
+    case Gesture::Possible:
+    {
+      mCurrentPanEmitters.clear();
+      ResetActor();
+
+      HitTestAlgorithm::Results hitTestResults;
+      if( HitTest( mStage, panEvent.currentPosition, hitTestResults ) )
+      {
+        SetActor( &GetImplementation( hitTestResults.actor ) );
+        mPossiblePanPosition = panEvent.currentPosition;
+      }
+
+      break;
+    }
+
+    case Gesture::Started:
+    {
+      if ( GetCurrentGesturedActor() )
+      {
+        // The pan gesture should only be sent to the gesture detector which first received it so that
+        // it can be told when the gesture ends as well.
+
+        HitTestAlgorithm::Results hitTestResults;
+        HitTest( mStage, mPossiblePanPosition, hitTestResults ); // Hit test original possible position...
+
+        if ( hitTestResults.actor && ( GetCurrentGesturedActor() == &GetImplementation( hitTestResults.actor ) ) )
+        {
+          // Record the current render-task for Screen->Actor coordinate conversions
+          mCurrentRenderTask = hitTestResults.renderTask;
+
+          // Set mCurrentPanEvent to use inside overridden methods called in ProcessAndEmit()
+          mCurrentPanEvent = &panEvent;
+          ProcessAndEmit( hitTestResults );
+          mCurrentPanEvent = NULL;
+        }
+        else
+        {
+          ResetActor();
+          mCurrentPanEmitters.clear();
+        }
+      }
+      break;
+    }
+
+    case Gesture::Continuing:
+    case Gesture::Finished:
+    case Gesture::Cancelled:
+    {
+      // Only send subsequent pan gesture signals if we processed the pan gesture when it started.
+      // Check if actor is still touchable.
+
+      Actor* currentGesturedActor = GetCurrentGesturedActor();
+      if ( currentGesturedActor )
+      {
+        if ( currentGesturedActor->IsHittable() && !mCurrentPanEmitters.empty() && mCurrentRenderTask )
+        {
+          GestureDetectorContainer outsideTouchesRangeEmitters;
+
+          // Removes emitters that no longer have the actor attached
+          // Also remove emitters whose touches are outside the range of the current pan event and add them to outsideTouchesRangeEmitters
+          GestureDetectorContainer::iterator endIter = std::remove_if( mCurrentPanEmitters.begin(), mCurrentPanEmitters.end(),
+                                                                       IsNotAttachedAndOutsideTouchesRangeFunctor(currentGesturedActor, panEvent.numberOfTouches, outsideTouchesRangeEmitters) );
+          mCurrentPanEmitters.erase( endIter, mCurrentPanEmitters.end() );
+
+          Vector2 actorCoords;
+
+          if ( !outsideTouchesRangeEmitters.empty() || !mCurrentPanEmitters.empty() )
+          {
+            currentGesturedActor->ScreenToLocal( GetImplementation( mCurrentRenderTask ), actorCoords.x, actorCoords.y, panEvent.currentPosition.x, panEvent.currentPosition.y );
+
+            // EmitPanSignal checks whether we have a valid actor and whether the container we are passing in has emitters before it emits the pan.
+            EmitPanSignal( currentGesturedActor, outsideTouchesRangeEmitters, panEvent, actorCoords, Gesture::Finished, mCurrentRenderTask);
+            EmitPanSignal( currentGesturedActor, mCurrentPanEmitters, panEvent, actorCoords, panEvent.state, mCurrentRenderTask);
+          }
+
+          if ( mCurrentPanEmitters.empty() )
+          {
+            // If we have no emitters attached then clear pan actor as well.
+            ResetActor();
+          }
+
+          // Clear current gesture detectors if pan gesture has ended or been cancelled.
+          if ( ( panEvent.state == Gesture::Finished ) || ( panEvent.state == Gesture::Cancelled ) )
+          {
+            mCurrentPanEmitters.clear();
+            ResetActor();
+          }
+        }
+        else
+        {
+          mCurrentPanEmitters.clear();
+          ResetActor();
+        }
+      }
+      break;
+    }
+
+    case Gesture::Clear:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
+      break;
+  }
+}
+
+void PanGestureProcessor::AddGestureDetector( PanGestureDetector* gestureDetector )
+{
+  bool firstRegistration(mGestureDetectors.empty());
+
+  mGestureDetectors.push_back(gestureDetector);
+
+  // Set the pan scene object on the gesture detector
+  gestureDetector->SetSceneObject( mSceneObject );
+
+  if (firstRegistration)
+  {
+    mMinTouchesRequired = gestureDetector->GetMinimumTouchesRequired();
+    mMaxTouchesRequired = gestureDetector->GetMaximumTouchesRequired();
+
+    Integration::PanGestureRequest request;
+    request.minTouches = mMinTouchesRequired;
+    request.maxTouches = mMaxTouchesRequired;
+    mGestureManager.Register(request);
+  }
+  else
+  {
+    UpdateDetection();
+  }
+}
+
+void PanGestureProcessor::RemoveGestureDetector( PanGestureDetector* gestureDetector )
+{
+  if (!mCurrentPanEmitters.empty())
+  {
+    // Check if the removed detector was one that is currently being panned and remove it from emitters.
+    GestureDetectorContainer::iterator endIter = std::remove( mCurrentPanEmitters.begin(), mCurrentPanEmitters.end(), gestureDetector );
+    mCurrentPanEmitters.erase( endIter, mCurrentPanEmitters.end() );
+
+    // If we no longer have any emitters, then we should clear mCurrentGesturedActor as well
+    if ( mCurrentPanEmitters.empty() )
+    {
+      ResetActor();
+    }
+  }
+
+  // Find the detector...
+  PanGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
+  DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
+
+  // ...and remove it
+  mGestureDetectors.erase(endIter, mGestureDetectors.end());
+
+  if (mGestureDetectors.empty())
+  {
+    Integration::GestureRequest request(Gesture::Pan);
+    mGestureManager.Unregister(request);
+  }
+  else
+  {
+    UpdateDetection();
+  }
+}
+
+void PanGestureProcessor::GestureDetectorUpdated( PanGestureDetector* gestureDetector )
+{
+  DALI_ASSERT_DEBUG(find(mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector) != mGestureDetectors.end());
+
+  UpdateDetection();
+}
+
+void PanGestureProcessor::SetPanGestureProperties( const PanGesture& pan )
+{
+  // If we are currently processing a pan gesture then just ignore
+  if ( mCurrentPanEmitters.empty() && mSceneObject )
+  {
+    // We update the scene object directly rather than sending a message.
+    // Sending a message could cause unnecessary delays, the scene object ensure thread safe behaviour.
+    mSceneObject->AddGesture( pan );
+  }
+}
+
+void PanGestureProcessor::EnableProfiling()
+{
+  mSceneObject->EnableProfiling();
+}
+
+void PanGestureProcessor::SetPredictionMode(int mode)
+{
+  if( (mode < 0)
+      || (mode >= SceneGraph::PanGesture::NUM_PREDICTION_MODES) )
+  {
+    mode = SceneGraph::PanGesture::DEFAULT_PREDICTION_MODE;
+  }
+  SceneGraph::PanGesture::PredictionMode modeEnum = static_cast<SceneGraph::PanGesture::PredictionMode>(mode);
+  mSceneObject->SetPredictionMode(modeEnum);
+}
+
+void PanGestureProcessor::SetPredictionAmount(unsigned int amount)
+{
+  mSceneObject->SetPredictionAmount(amount);
+}
+
+void PanGestureProcessor::SetMaximumPredictionAmount(unsigned int amount)
+{
+  mSceneObject->SetMaximumPredictionAmount(amount);
+}
+
+void PanGestureProcessor::SetMinimumPredictionAmount(unsigned int amount)
+{
+  mSceneObject->SetMinimumPredictionAmount(amount);
+}
+
+void PanGestureProcessor::SetPredictionAmountAdjustment(unsigned int amount)
+{
+  mSceneObject->SetPredictionAmountAdjustment(amount);
+}
+
+void PanGestureProcessor::SetSmoothingMode(int mode)
+{
+  if( (mode < 0)
+      || (mode >= SceneGraph::PanGesture::NUM_SMOOTHING_MODES) )
+  {
+    mode = SceneGraph::PanGesture::DEFAULT_SMOOTHING_MODE;
+  }
+  SceneGraph::PanGesture::SmoothingMode modeEnum = static_cast<SceneGraph::PanGesture::SmoothingMode>(mode);
+  mSceneObject->SetSmoothingMode(modeEnum);
+}
+
+void PanGestureProcessor::SetSmoothingAmount(float amount)
+{
+  mSceneObject->SetSmoothingAmount(amount);
+}
+
+void PanGestureProcessor::SetUseActualTimes( bool value )
+{
+  mSceneObject->SetUseActualTimes( value );
+}
+
+void PanGestureProcessor::SetInterpolationTimeRange( int value )
+{
+  mSceneObject->SetInterpolationTimeRange( value );
+}
+
+void PanGestureProcessor::SetScalarOnlyPredictionEnabled( bool value )
+{
+  mSceneObject->SetScalarOnlyPredictionEnabled( value );
+}
+
+void PanGestureProcessor::SetTwoPointPredictionEnabled( bool value )
+{
+  mSceneObject->SetTwoPointPredictionEnabled( value );
+}
+
+void PanGestureProcessor::SetTwoPointInterpolatePastTime( int value )
+{
+  mSceneObject->SetTwoPointInterpolatePastTime( value );
+}
+
+void PanGestureProcessor::SetTwoPointVelocityBias( float value )
+{
+  mSceneObject->SetTwoPointVelocityBias( value );
+}
+
+void PanGestureProcessor::SetTwoPointAccelerationBias( float value )
+{
+  mSceneObject->SetTwoPointAccelerationBias( value );
+}
+
+void PanGestureProcessor::SetMultitapSmoothingRange( int value )
+{
+  mSceneObject->SetMultitapSmoothingRange( value );
+}
+
+void PanGestureProcessor::UpdateDetection()
+{
+  DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
+
+  unsigned int minimumRequired = UINT_MAX;
+  unsigned int maximumRequired = 0;
+
+  for ( PanGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
+  {
+    PanGestureDetector* detector(*iter);
+
+    unsigned int minimum = detector->GetMinimumTouchesRequired();
+    if (minimum < minimumRequired)
+    {
+      minimumRequired = minimum;
+    }
+
+    unsigned int maximum = detector->GetMaximumTouchesRequired();
+    if (maximum > maximumRequired)
+    {
+      maximumRequired = maximum;
+    }
+  }
+
+  if ( (minimumRequired != mMinTouchesRequired)||(maximumRequired != mMaxTouchesRequired) )
+  {
+    mMinTouchesRequired = minimumRequired;
+    mMaxTouchesRequired = maximumRequired;
+
+    Integration::PanGestureRequest request;
+    request.minTouches = mMinTouchesRequired;
+    request.maxTouches = mMaxTouchesRequired;
+    mGestureManager.Update(request);
+  }
+}
+
+void PanGestureProcessor::EmitPanSignal( Actor* actor,
+                                         const GestureDetectorContainer& gestureDetectors,
+                                         const Integration::PanGestureEvent& panEvent,
+                                         Vector2 localCurrent,
+                                         Gesture::State state,
+                                         Dali::RenderTask renderTask )
+{
+  if ( actor && !gestureDetectors.empty() )
+  {
+    PanGesture pan(state);
+    pan.time = panEvent.time;
+
+    pan.numberOfTouches = panEvent.numberOfTouches;
+    pan.screenPosition = panEvent.currentPosition;
+    pan.position = localCurrent;
+
+    RenderTask& renderTaskImpl( GetImplementation( renderTask ) );
+
+    Vector2 localPrevious;
+    actor->ScreenToLocal( renderTaskImpl, localPrevious.x, localPrevious.y, panEvent.previousPosition.x, panEvent.previousPosition.y );
+
+    pan.displacement = localCurrent - localPrevious;
+    Vector2 previousPos( panEvent.previousPosition );
+    if ( state == Gesture::Started )
+    {
+      previousPos = mPossiblePanPosition;
+    }
+
+    pan.screenDisplacement = panEvent.currentPosition - previousPos;
+
+    // Avoid dividing by 0
+    if ( panEvent.timeDelta > 0 )
+    {
+      pan.velocity.x = pan.displacement.x / panEvent.timeDelta;
+      pan.velocity.y = pan.displacement.y / panEvent.timeDelta;
+
+      pan.screenVelocity.x = pan.screenDisplacement.x / panEvent.timeDelta;
+      pan.screenVelocity.y = pan.screenDisplacement.y / panEvent.timeDelta;
+    }
+
+    // When the gesture ends, we may incorrectly get a ZERO velocity (as we have lifted our finger without any movement)
+    // so we should use the last recorded velocity instead in this scenario.
+    if ( ( state == Gesture::Finished ) && ( pan.screenVelocity == Vector2::ZERO ) &&
+         ( panEvent.timeDelta < MAXIMUM_TIME_WITH_VALID_LAST_VELOCITY ) )
+    {
+      pan.velocity = mLastVelocity;
+      pan.screenVelocity = mLastScreenVelocity;
+    }
+    else
+    {
+      // Store the current velocity for future iterations.
+      mLastVelocity = pan.velocity;
+      mLastScreenVelocity = pan.screenVelocity;
+    }
+
+    if ( mSceneObject )
+    {
+      // We update the scene object directly rather than sending a message.
+      // Sending a message could cause unnecessary delays, the scene object ensure thread safe behaviour.
+      mSceneObject->AddGesture( pan );
+    }
+
+    Dali::Actor actorHandle( actor );
+    const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
+    for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
+    {
+      static_cast< PanGestureDetector* >( *iter )->EmitPanGestureSignal( actorHandle, pan );
+    }
+  }
+}
+
+void PanGestureProcessor::OnGesturedActorStageDisconnection()
+{
+  mCurrentPanEmitters.clear();
+}
+
+bool PanGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
+{
+  DALI_ASSERT_DEBUG( mCurrentPanEvent );
+
+  bool retVal( false );
+  PanGestureDetector* panDetector( static_cast< PanGestureDetector* >( detector ) );
+
+  if ( ( mCurrentPanEvent->numberOfTouches >= panDetector->GetMinimumTouchesRequired() ) &&
+       ( mCurrentPanEvent->numberOfTouches <= panDetector->GetMaximumTouchesRequired() ) )
+  {
+    // Check if the detector requires directional panning.
+    if ( panDetector->RequiresDirectionalPan() && mCurrentRenderTask )
+    {
+      // It does, calculate the angle of the pan in local actor coordinates and ensures it fits
+      // the detector's criteria.
+      RenderTask& renderTaskImpl( GetImplementation( mCurrentRenderTask ) );
+
+      Vector2 startPosition, currentPosition;
+      actor->ScreenToLocal( renderTaskImpl, startPosition.x,   startPosition.y,   mPossiblePanPosition.x,              mPossiblePanPosition.y );
+      actor->ScreenToLocal( renderTaskImpl, currentPosition.x, currentPosition.y, mCurrentPanEvent->currentPosition.x, mCurrentPanEvent->currentPosition.y );
+      Vector2 displacement( currentPosition - startPosition );
+
+      Radian angle( atan( displacement.y / displacement.x ) );
+
+      /////////////////////////////
+      //            |            //
+      //            |            //
+      //   Q3 (-,-) | Q4 (+,-)   //
+      //            |            //
+      //    ----------------- +x //
+      //            |            //
+      //   Q2 (-,+) | Q1 (+,+)   //
+      //            |            //
+      //            |            //
+      //           +y            //
+      /////////////////////////////
+      // Quadrant 1: As is
+      // Quadrant 2: 180 degrees + angle
+      // Quadrant 3: angle - 180 degrees
+      // Quadrant 4: As is
+      /////////////////////////////
+
+      if ( displacement.x < 0.0f )
+      {
+        if ( displacement.y >= 0.0f )
+        {
+          // Quadrant 2
+          angle.radian += Math::PI;
+        }
+        else
+        {
+          // Quadrant 3
+          angle.radian -= Math::PI;
+        }
+      }
+
+      if ( panDetector->CheckAngleAllowed( angle ) )
+      {
+        retVal = true;
+      }
+    }
+    else
+    {
+      // Directional panning not required so we can use this actor and gesture detector.
+      retVal = true;
+    }
+  }
+  return retVal;
+}
+
+void PanGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
+{
+  DALI_ASSERT_DEBUG ( mCurrentPanEvent );
+
+  mCurrentPanEmitters.clear();
+  ResetActor();
+
+  actor->ScreenToLocal( GetImplementation(mCurrentRenderTask), actorCoordinates.x, actorCoordinates.y, mCurrentPanEvent->currentPosition.x, mCurrentPanEvent->currentPosition.y );
+
+  EmitPanSignal( actor, gestureDetectors, *mCurrentPanEvent, actorCoordinates, mCurrentPanEvent->state, mCurrentRenderTask );
+
+  if ( actor->OnStage() )
+  {
+    mCurrentPanEmitters = gestureDetectors;
+    SetActor( actor );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/pan-gesture-processor.h b/dali/internal/event/events/pan-gesture-processor.h
new file mode 100644 (file)
index 0000000..557f825
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef __DALI_INTERNAL_PAN_GESTURE_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_PAN_GESTURE_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/pan-gesture-detector-impl.h>
+#include <dali/internal/event/events/gesture-processor.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GestureManager;
+struct GestureEvent;
+struct PanGestureEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+namespace SceneGraph
+{
+class PanGesture;
+}
+
+/**
+ * Pan Gesture Event Processing:
+ *
+ * When we receive a pan gesture event, we do the following:
+ * - Find the actor that requires a pan where the pan started from (i.e. the down position).
+ * - Emit the gesture if the event satisfies the detector conditions.
+ *
+ * The above is only checked when our gesture starts.  We continue sending the pan gesture to the
+ * same actor and detector until the pan ends or is cancelled.
+ */
+class PanGestureProcessor : public GestureProcessor
+{
+public:
+
+  /**
+   * Create a pan gesture processor.
+   * @param[in] stage The stage.
+   * @param[in] gestureManager The gesture manager
+   */
+  PanGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager );
+
+  /**
+   * Non-virtual destructor; PanGestureProcessor is not a base class
+   */
+  ~PanGestureProcessor();
+
+public: // To be called by GestureEventProcessor
+
+  /**
+   * This method is called whenever a pan gesture event occurs.
+   * @param[in] panEvent The event that has occurred.
+   */
+  void Process( const Integration::PanGestureEvent& panEvent );
+
+  /**
+   * Adds a gesture detector to this gesture processor.
+   * If this is the first gesture detector being added, then this method registers the required
+   * gesture with the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being added.
+   */
+  void AddGestureDetector( PanGestureDetector* gestureDetector );
+
+  /**
+   * Removes the specified gesture detector from this gesture processor.  If, after removing this
+   * gesture detector, there are no more gesture detectors registered, then this method unregisters
+   * the gesture from the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being removed.
+   */
+  void RemoveGestureDetector( PanGestureDetector* gestureDetector );
+
+  /**
+   * This method updates the gesture detection parameters.
+   * @param[in]  gestureDetector  The gesture detector that has been updated.
+   */
+  void GestureDetectorUpdated( PanGestureDetector* gestureDetector );
+
+  /**
+   * Sets the pan gesture properties stored in the scene object directly,
+   * @param[in]  pan  The pan gesture to override the properties with.
+   * @note If we are already processing a normal pan, then this call is ignored.
+   */
+  void SetPanGestureProperties( const PanGesture& pan );
+
+  /**
+   * Called to provide pan-gesture profiling information.
+   */
+  void EnableProfiling();
+
+  /**
+   * Called to set the prediction mode for pan gestures
+   *
+   * @param[in] mode The prediction mode
+   *
+   * Valid modes:
+   * 0 - No prediction
+   * 1 - Prediction using average acceleration
+   */
+  void SetPredictionMode(int mode);
+
+  /**
+   * @brief Sets the prediction amount of the pan gesture
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the upper bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetMaximumPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the lower bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetMinimumPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the amount of prediction interpolation to adjust when the pan velocity is changed
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPredictionAmountAdjustment(unsigned int amount);
+
+  /**
+   * Called to set the prediction mode for pan gestures
+   *
+   * @param[in] mode The prediction mode
+   *
+   * Valid modes:
+   * 0 - No smoothing
+   * 1 - average between last 2 values
+   */
+  void SetSmoothingMode(int mode);
+
+  /**
+   * @brief Sets the smoothing amount of the pan gesture
+   *
+   * @param[in] amount The smotthing amount from 0.0f (none) to 1.0f (full)
+   */
+  void SetSmoothingAmount(float amount);
+
+  /*
+   * @brief Sets whether to use actual times of the real gesture and frames or not.
+   *
+   * @param[in] value True = use actual times, False = use perfect values
+   */
+  void SetUseActualTimes( bool value );
+
+  /**
+   * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
+   *
+   * @param[in] value Time range in ms
+   */
+  void SetInterpolationTimeRange( int value );
+
+  /**
+   * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
+   *
+   * @param[in] value True = use scalar prediction only
+   */
+  void SetScalarOnlyPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
+   *
+   * @param[in] value True = use two point prediction
+   */
+  void SetTwoPointPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetTwoPointInterpolatePastTime( int value );
+
+  /**
+   * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetTwoPointVelocityBias( float value );
+
+  /**
+   * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetTwoPointAccelerationBias( float value );
+
+  /**
+   * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetMultitapSmoothingRange( int value );
+
+private:
+
+  // Undefined
+  PanGestureProcessor( const PanGestureProcessor& );
+  PanGestureProcessor& operator=( const PanGestureProcessor& rhs );
+
+  /**
+   * Iterates through our GestureDetectors and determines if we need to ask the adaptor to update
+   * its detection policy.  If it does, it sends the appropriate gesture update request to adaptor.
+   */
+  void UpdateDetection();
+
+  /**
+   * Creates a PanGesture and asks the specified detector to emit its detected signal.
+   * @param[in]  actor             The actor that has been panned.
+   * @param[in]  gestureDetectors  The gesture detector container that should emit the signal.
+   * @param[in]  panEvent          The panEvent received from the adaptor.
+   * @param[in]  localCurrent      Current position relative to the actor attached to the detector.
+   * @param[in]  state             The state of the gesture.
+   * @param[in]  renderTask        The renderTask to use.
+   */
+  void EmitPanSignal( Actor* actor,
+                      const GestureDetectorContainer& gestureDetectors,
+                      const Integration::PanGestureEvent& panEvent,
+                      Vector2 localCurrent,
+                      Gesture::State state,
+                      Dali::RenderTask renderTask );
+
+  // GestureProcessor overrides
+
+  /**
+   * @copydoc GestureProcessor::OnGesturedActorStageDisconnection()
+   */
+  void OnGesturedActorStageDisconnection();
+
+  /**
+   * @copydoc GestureProcessor::CheckGestureDetector()
+   */
+  bool CheckGestureDetector( GestureDetector* detector, Actor* actor );
+
+  /**
+   * @copydoc GestureProcessor::EmitGestureSignal()
+   */
+  void EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates );
+
+private:
+
+  Stage& mStage;
+  Integration::GestureManager& mGestureManager;
+  PanGestureDetectorContainer mGestureDetectors;
+  GestureDetectorContainer mCurrentPanEmitters;
+  Dali::RenderTask mCurrentRenderTask;
+  Vector2 mPossiblePanPosition;
+
+  unsigned int mMinTouchesRequired;
+  unsigned int mMaxTouchesRequired;
+
+  Vector2 mLastVelocity;       ///< The last recorded velocity in local actor coordinates.
+  Vector2 mLastScreenVelocity; ///< The last recorded velocity in screen coordinates.
+
+  const Integration::PanGestureEvent* mCurrentPanEvent; ///< Pointer to current PanEvent, used when calling ProcessAndEmit()
+  SceneGraph::PanGesture* mSceneObject; ///< Not owned, but we write to it directly
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PAN_GESTURE_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/pinch-gesture-detector-impl.cpp b/dali/internal/event/events/pinch-gesture-detector-impl.cpp
new file mode 100644 (file)
index 0000000..43c971e
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/pinch-gesture.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_PINCH_DETECTED = "pinch-detected";
+
+BaseHandle Create()
+{
+  return Dali::PinchGestureDetector::New();
+}
+
+TypeRegistration mType( typeid(Dali::PinchGestureDetector), typeid(Dali::GestureDetector), Create );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_PINCH_DETECTED, &PinchGestureDetector::DoConnectSignal );
+
+}
+
+
+PinchGestureDetectorPtr PinchGestureDetector::New()
+{
+  return new PinchGestureDetector;
+}
+
+PinchGestureDetector::PinchGestureDetector()
+: GestureDetector(Gesture::Pinch)
+{
+}
+
+PinchGestureDetector::~PinchGestureDetector()
+{
+}
+
+void PinchGestureDetector::EmitPinchGestureSignal(Dali::Actor actor, const PinchGesture& pinch)
+{
+  // Guard against destruction during signal emission
+  Dali::PinchGestureDetector handle( this );
+
+  mDetectedSignal.Emit( actor, pinch );
+}
+
+bool PinchGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  PinchGestureDetector* gesture = dynamic_cast<PinchGestureDetector*>(object);
+
+  if ( 0 == strcmp( signalName.c_str(), SIGNAL_PINCH_DETECTED ) )
+  {
+    gesture->DetectedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void PinchGestureDetector::OnActorAttach(Actor& actor)
+{
+  // Do nothing
+}
+
+void PinchGestureDetector::OnActorDetach(Actor& actor)
+{
+  // Do nothing
+}
+
+void PinchGestureDetector::OnActorDestroyed(Object& object)
+{
+  // Do nothing
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/pinch-gesture-detector-impl.h b/dali/internal/event/events/pinch-gesture-detector-impl.h
new file mode 100644 (file)
index 0000000..0b7d50c
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef __DALI_INTERNAL_PINCH_GESTURE_DETECTOR_H__
+#define __DALI_INTERNAL_PINCH_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/pinch-gesture-detector.h>
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+struct PinchGesture;
+
+namespace Internal
+{
+
+class PinchGestureDetector;
+
+typedef IntrusivePtr<PinchGestureDetector> PinchGestureDetectorPtr;
+typedef DerivedGestureDetectorContainer<PinchGestureDetector>::type PinchGestureDetectorContainer;
+
+/**
+ * @copydoc Dali::PinchGestureDetector
+ */
+class PinchGestureDetector : public GestureDetector
+{
+public: // Creation
+
+  /**
+   * Create a new gesture detector.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static PinchGestureDetectorPtr New();
+
+  /**
+   * Construct a new GestureDetector.
+   */
+  PinchGestureDetector();
+
+public:
+
+  /**
+   * Called by the PinchGestureProcessor when a pinch gesture event occurs within the bounds of our
+   * attached actor.
+   * @param[in]  actor  The pinched actor.
+   * @param[in]  pinch  The pinch gesture.
+   */
+  void EmitPinchGestureSignal(Dali::Actor actor, const PinchGesture& pinch);
+
+public: // Signals
+
+  /**
+   * @copydoc Dali::PinchGestureDetector::DetectedSignal()
+   */
+  Dali::PinchGestureDetector::DetectedSignalType& DetectedSignal()
+  {
+    return mDetectedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~PinchGestureDetector();
+
+private:
+
+  // Undefined
+  PinchGestureDetector(const PinchGestureDetector&);
+  PinchGestureDetector& operator=(const PinchGestureDetector& rhs);
+
+private: // GestureDetector overrides
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorAttach(Actor&)
+   */
+  virtual void OnActorAttach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDetach(Actor&)
+   */
+  virtual void OnActorDetach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDestroyed(Object&)
+   */
+  virtual void OnActorDestroyed(Object& object);
+
+private:
+
+  Dali::PinchGestureDetector::DetectedSignalType mDetectedSignal;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::PinchGestureDetector& GetImplementation(Dali::PinchGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "PinchGestureDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::PinchGestureDetector&>(handle);
+}
+
+inline const Internal::PinchGestureDetector& GetImplementation(const Dali::PinchGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "PinchGestureDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::PinchGestureDetector&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PINCH_GESTURE_DETECTOR_H__
diff --git a/dali/internal/event/events/pinch-gesture-processor.cpp b/dali/internal/event/events/pinch-gesture-processor.cpp
new file mode 100644 (file)
index 0000000..07051b6
--- /dev/null
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/pinch-gesture-processor.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/events/pinch-gesture.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/events/pinch-gesture-event.h>
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * Creates a PinchGesture and asks the specified detector to emit its detected signal.
+ * @param[in]  actor             The actor that has been pinched.
+ * @param[in]  gestureDetectors  The gesture detector container that should emit the signal.
+ * @param[in]  pinchEvent        The pinchEvent received from the adaptor.
+ * @param[in]  localCenter       Relative to the actor attached to the detector.
+ */
+void EmitPinchSignal(
+    Actor* actor,
+    const GestureDetectorContainer& gestureDetectors,
+    const Integration::PinchGestureEvent& pinchEvent,
+    Vector2 localCenter)
+{
+  PinchGesture pinch(pinchEvent.state);
+  pinch.time = pinchEvent.time;
+
+  pinch.scale = pinchEvent.scale;
+  pinch.speed = pinchEvent.speed;
+  pinch.screenCenterPoint = pinchEvent.centerPoint;
+
+  pinch.localCenterPoint = localCenter;
+
+  Dali::Actor actorHandle( actor );
+  const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
+  for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
+  {
+    static_cast< PinchGestureDetector* >( *iter )->EmitPinchGestureSignal( actorHandle, pinch );
+  }
+}
+
+/**
+ * Functor which checks whether the specified actor is attached to the gesture detector.
+ * It returns true if it is no longer attached.  This can be used in remove_if functions.
+ */
+struct IsNotAttachedFunctor
+{
+  /**
+   * Constructor
+   * @param[in]  actor  The actor to check whether it is attached.
+   */
+  IsNotAttachedFunctor(Actor* actor)
+  : actorToCheck(actor)
+  {
+  }
+
+  /**
+   * Returns true if not attached, false if it is still attached.
+   * @param[in]  detector  The detector to check.
+   * @return true, if not attached, false otherwise.
+   */
+  bool operator()(const GestureDetector* detector) const
+  {
+    return !detector->IsAttached(*actorToCheck);
+  }
+
+  Actor* actorToCheck; ///< The actor to check whether it is attached or not.
+};
+
+} // unnamed namespace
+
+PinchGestureProcessor::PinchGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager )
+: GestureProcessor( Gesture::Pinch ),
+  mStage(stage),
+  mGestureManager(gestureManager),
+  mGestureDetectors(),
+  mCurrentPinchEmitters(),
+  mCurrentPinchEvent(NULL)
+{
+}
+
+PinchGestureProcessor::~PinchGestureProcessor()
+{
+}
+
+void PinchGestureProcessor::Process( const Integration::PinchGestureEvent& pinchEvent )
+{
+  switch ( pinchEvent.state )
+  {
+    case Gesture::Started:
+    {
+      // The pinch gesture should only be sent to the gesture detector which first received it so that
+      // it can be told when the gesture ends as well.
+
+      mCurrentPinchEmitters.clear();
+      ResetActor();
+
+      HitTestAlgorithm::Results hitTestResults;
+      if( HitTest( mStage, pinchEvent.centerPoint, hitTestResults ) )
+      {
+        // Record the current render-task for Screen->Actor coordinate conversions
+        mCurrentRenderTask = hitTestResults.renderTask;
+
+        // Set mCurrentPinchEvent to use inside overridden methods called from ProcessAndEmit()
+        mCurrentPinchEvent = &pinchEvent;
+        ProcessAndEmit( hitTestResults );
+        mCurrentPinchEvent = NULL;
+      }
+      break;
+    }
+
+    case Gesture::Continuing:
+    case Gesture::Finished:
+    case Gesture::Cancelled:
+    {
+      // Only send subsequent pinch gesture signals if we processed the pinch gesture when it started.
+      // Check if actor is still touchable.
+
+      Actor* currentGesturedActor = GetCurrentGesturedActor();
+      if ( currentGesturedActor )
+      {
+        if ( currentGesturedActor->IsHittable() && !mCurrentPinchEmitters.empty() && mCurrentRenderTask )
+        {
+          // Ensure actor is still attached to the emitters, if it is not then remove the emitter.
+          GestureDetectorContainer::iterator endIter = std::remove_if( mCurrentPinchEmitters.begin(), mCurrentPinchEmitters.end(), IsNotAttachedFunctor(currentGesturedActor) );
+          mCurrentPinchEmitters.erase( endIter, mCurrentPinchEmitters.end() );
+
+          if ( !mCurrentPinchEmitters.empty() )
+          {
+            Vector2 actorCoords;
+            RenderTask& renderTaskImpl( GetImplementation(mCurrentRenderTask) );
+            currentGesturedActor->ScreenToLocal( renderTaskImpl, actorCoords.x, actorCoords.y, pinchEvent.centerPoint.x, pinchEvent.centerPoint.y );
+
+            EmitPinchSignal( currentGesturedActor, mCurrentPinchEmitters, pinchEvent, actorCoords );
+          }
+          else
+          {
+            // If we have no current emitters then clear pinched actor as well.
+            ResetActor();
+          }
+
+          // Clear current emitters if pinch gesture has ended or been cancelled.
+          if ( pinchEvent.state == Gesture::Finished || pinchEvent.state == Gesture::Cancelled )
+          {
+            mCurrentPinchEmitters.clear();
+            ResetActor();
+          }
+        }
+        else
+        {
+          mCurrentPinchEmitters.clear();
+          ResetActor();
+        }
+      }
+      break;
+    }
+
+    case Gesture::Clear:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
+      break;
+
+    case Gesture::Possible:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Possible\n" );
+      break;
+  }
+}
+
+void PinchGestureProcessor::AddGestureDetector( PinchGestureDetector* gestureDetector )
+{
+  bool registerWithAdaptor(mGestureDetectors.empty());
+
+  mGestureDetectors.push_back(gestureDetector);
+
+  if (registerWithAdaptor)
+  {
+    Integration::GestureRequest request(Gesture::Pinch);
+    mGestureManager.Register(request);
+  }
+}
+
+void PinchGestureProcessor::RemoveGestureDetector( PinchGestureDetector* gestureDetector )
+{
+  if ( !mCurrentPinchEmitters.empty() )
+  {
+    // Check if the removed detector was one that is currently being pinched and remove it from emitters.
+    GestureDetectorContainer::iterator endIter = std::remove( mCurrentPinchEmitters.begin(), mCurrentPinchEmitters.end(), gestureDetector );
+    mCurrentPinchEmitters.erase( endIter, mCurrentPinchEmitters.end() );
+
+    // If we no longer have any emitters, then we should clear mCurrentGesturedActor as well
+    if ( mCurrentPinchEmitters.empty() )
+    {
+      ResetActor();
+    }
+  }
+
+  // Find the detector...
+  PinchGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
+  DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
+
+  // ...and remove it
+  mGestureDetectors.erase(endIter, mGestureDetectors.end());
+
+  if (mGestureDetectors.empty())
+  {
+    Integration::GestureRequest request(Gesture::Pinch);
+    mGestureManager.Unregister(request);
+  }
+}
+
+void PinchGestureProcessor::GestureDetectorUpdated( PinchGestureDetector* gestureDetector )
+{
+  // Nothing to do as PinchGestureDetector does not have any specific parameters.
+}
+
+void PinchGestureProcessor::OnGesturedActorStageDisconnection()
+{
+  mCurrentPinchEmitters.clear();
+}
+
+bool PinchGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
+{
+  // No special case required for pinch.
+  return true;
+}
+
+void PinchGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
+{
+  DALI_ASSERT_DEBUG( mCurrentPinchEvent );
+
+  EmitPinchSignal( actor, gestureDetectors, *mCurrentPinchEvent, actorCoordinates );
+
+  if ( actor->OnStage() )
+  {
+    mCurrentPinchEmitters = gestureDetectors;
+    SetActor( actor );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/pinch-gesture-processor.h b/dali/internal/event/events/pinch-gesture-processor.h
new file mode 100644 (file)
index 0000000..c76259c
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef __DALI_INTERNAL_PINCH_GESTURE_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_PINCH_GESTURE_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
+#include <dali/internal/event/events/gesture-processor.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GestureManager;
+struct GestureEvent;
+struct PinchGestureEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+/**
+ * Pinch Gesture Event Processing:
+ *
+ * When we receive a pinch gesture event, we do the following:
+ * - Find the hit actor that requires a pinch underneath the center-point of the pinch.
+ * - Emit the gesture if the event satisfies the detector conditions.
+ *
+ * The above is only checked when our gesture starts. We continue sending the pinch gesture to this
+ * detector until the pinch ends or is cancelled.
+ */
+class PinchGestureProcessor : public GestureProcessor
+{
+public:
+
+  /**
+   * Create a pinch gesture processor.
+   * @param[in] stage The stage.
+   * @param[in] gestureManager The gesture manager
+   */
+  PinchGestureProcessor(Stage& stage, Integration::GestureManager& gestureManager);
+
+  /**
+   * Non-virtual destructor; PinchGestureProcessor is not a base class
+   */
+  ~PinchGestureProcessor();
+
+public: // To be called by GestureEventProcessor
+
+  /**
+   * This method is called whenever a pinch gesture event occurs.
+   * @param[in] pinchEvent The event that has occurred.
+   */
+  void Process(const Integration::PinchGestureEvent& pinchEvent);
+
+  /**
+   * Adds a gesture detector to this gesture processor.
+   * If this is the first gesture detector being added, then this method registers the required
+   * gesture with the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being added.
+   */
+  void AddGestureDetector(PinchGestureDetector* gestureDetector);
+
+  /**
+   * Removes the specified gesture detector from this gesture processor.  If, after removing this
+   * gesture detector, there are no more gesture detectors registered, then this method unregisters
+   * the gesture from the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being removed.
+   */
+  void RemoveGestureDetector(PinchGestureDetector* gestureDetector);
+
+  /**
+   * This method updates the gesture detection parameters.
+   * @param[in]  gestureDetector  The gesture detector that has been updated.
+   */
+  void GestureDetectorUpdated(PinchGestureDetector* gestureDetector);
+
+private:
+
+  // Undefined
+  PinchGestureProcessor(const PinchGestureProcessor&);
+  PinchGestureProcessor& operator=(const PinchGestureProcessor& rhs);
+
+private:
+
+  // GestureProcessor overrides
+
+  /**
+   * @copydoc GestureProcessor::OnGesturedActorStageDisconnection()
+   */
+  void OnGesturedActorStageDisconnection();
+
+  /**
+   * @copydoc GestureProcessor::CheckGestureDetector()
+   */
+  bool CheckGestureDetector( GestureDetector* detector, Actor* actor );
+
+  /**
+   * @copydoc GestureProcessor::EmitGestureSignal()
+   */
+  void EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates );
+
+private:
+
+  Stage& mStage;
+  Integration::GestureManager& mGestureManager;
+  PinchGestureDetectorContainer mGestureDetectors;
+  GestureDetectorContainer mCurrentPinchEmitters;
+  Dali::RenderTask mCurrentRenderTask;
+
+  const Integration::PinchGestureEvent* mCurrentPinchEvent; ///< Pointer to current PinchEvent, used when calling ProcessAndEmit()
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PINCH_GESTURE_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/tap-gesture-detector-impl.cpp b/dali/internal/event/events/tap-gesture-detector-impl.cpp
new file mode 100644 (file)
index 0000000..b7c76b0
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/tap-gesture-detector-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/tap-gesture.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/events/gesture-event-processor.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+const unsigned int DEFAULT_TAPS_REQUIRED = 1u;
+const unsigned int DEFAULT_TOUCHES_REQUIRED = 1u;
+
+// Signals
+const char* const SIGNAL_TAP_DETECTED = "tap-detected";
+
+BaseHandle Create()
+{
+  return Dali::TapGestureDetector::New();
+}
+
+TypeRegistration mType( typeid(Dali::TapGestureDetector), typeid(Dali::GestureDetector), Create );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_TAP_DETECTED, &TapGestureDetector::DoConnectSignal );
+
+}
+
+TapGestureDetectorPtr TapGestureDetector::New()
+{
+  return new TapGestureDetector;
+}
+
+TapGestureDetectorPtr TapGestureDetector::New( unsigned int tapsRequired )
+{
+  return new TapGestureDetector( tapsRequired );
+}
+
+TapGestureDetector::TapGestureDetector()
+: GestureDetector( Gesture::Tap ),
+  mMinimumTapsRequired( DEFAULT_TAPS_REQUIRED ),
+  mMaximumTapsRequired( DEFAULT_TAPS_REQUIRED ),
+  mTouchesRequired( DEFAULT_TOUCHES_REQUIRED )
+{
+}
+
+TapGestureDetector::TapGestureDetector( unsigned int tapsRequired )
+: GestureDetector( Gesture::Tap ),
+  mMinimumTapsRequired( tapsRequired ),
+  mMaximumTapsRequired( tapsRequired ),
+  mTouchesRequired( DEFAULT_TOUCHES_REQUIRED )
+{
+}
+
+TapGestureDetector::~TapGestureDetector()
+{
+}
+
+void TapGestureDetector::SetMinimumTapsRequired(unsigned int taps)
+{
+  if ( mMinimumTapsRequired != taps )
+  {
+    mMinimumTapsRequired = taps;
+
+    if ( !mAttachedActors.empty() )
+    {
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+void TapGestureDetector::SetMaximumTapsRequired(unsigned int taps)
+{
+  if ( mMaximumTapsRequired != taps )
+  {
+    mMaximumTapsRequired = taps;
+
+    if ( !mAttachedActors.empty() )
+    {
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+void TapGestureDetector::SetTouchesRequired(unsigned int touches)
+{
+  if (mTouchesRequired != touches)
+  {
+    mTouchesRequired = touches;
+
+    if (!mAttachedActors.empty())
+    {
+      mGestureEventProcessor.GestureDetectorUpdated(this);
+    }
+  }
+}
+
+unsigned int TapGestureDetector::GetMinimumTapsRequired() const
+{
+  return mMinimumTapsRequired;
+}
+
+unsigned int TapGestureDetector::GetMaximumTapsRequired() const
+{
+  return mMaximumTapsRequired;
+}
+
+unsigned int TapGestureDetector::GetTouchesRequired() const
+{
+  return mTouchesRequired;
+}
+
+void TapGestureDetector::EmitTapGestureSignal(Dali::Actor tappedActor, const TapGesture& tap)
+{
+  // Guard against destruction during signal emission
+  Dali::TapGestureDetector handle( this );
+
+  mDetectedSignal.Emit( tappedActor, tap );
+}
+
+bool TapGestureDetector::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  TapGestureDetector* gesture = dynamic_cast<TapGestureDetector*>(object);
+
+  if ( 0 == strcmp( signalName.c_str(), SIGNAL_TAP_DETECTED ) )
+  {
+    gesture->DetectedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+void TapGestureDetector::OnActorAttach(Actor& actor)
+{
+  // Do nothing
+}
+
+void TapGestureDetector::OnActorDetach(Actor& actor)
+{
+  // Do nothing
+}
+
+void TapGestureDetector::OnActorDestroyed(Object& object)
+{
+  // Do nothing
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/tap-gesture-detector-impl.h b/dali/internal/event/events/tap-gesture-detector-impl.h
new file mode 100644 (file)
index 0000000..9e26d20
--- /dev/null
@@ -0,0 +1,195 @@
+#ifndef __DALI_INTERNAL_TAP_GESTURE_DETECTOR_H__
+#define __DALI_INTERNAL_TAP_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/tap-gesture-detector.h>
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+struct TapGesture;
+
+namespace Internal
+{
+
+class TapGestureDetector;
+
+typedef IntrusivePtr<TapGestureDetector> TapGestureDetectorPtr;
+typedef DerivedGestureDetectorContainer<TapGestureDetector>::type TapGestureDetectorContainer;
+
+/**
+ * @copydoc Dali::TapGestureDetector
+ */
+class TapGestureDetector : public GestureDetector
+{
+public: // Creation
+
+  /**
+   * Create a new gesture detector.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static TapGestureDetectorPtr New();
+
+  /**
+   * Create a new gesture detector with the specified parameters.
+   * @param[in]  tapsRequired     The number of taps required.
+   * @return A smart-pointer to the newly allocated detector.
+   */
+  static TapGestureDetectorPtr New( unsigned int tapsRequired );
+
+  /**
+   * Construct a new GestureDetector.
+   */
+  TapGestureDetector();
+
+  /**
+   * Construct a new GestureDetector with the specified parameters.
+   * @param[in]  tapsRequired     The number of taps required.
+   */
+  TapGestureDetector( unsigned int tapsRequired );
+
+public:
+
+  /**
+   * @copydoc Dali::TapGestureDetector::SetTouchesRequired(unsigned int)
+   */
+  void SetTouchesRequired(unsigned int touches);
+
+  /**
+   * @copydoc Dali::TapGestureDetector::SetMinimumTapsRequired()
+   */
+  void SetMinimumTapsRequired( unsigned int minTaps );
+
+  /**
+   * @copydoc Dali::TapGestureDetector::SetMaximumTapsRequired()
+   */
+  void SetMaximumTapsRequired( unsigned int maxTaps );
+
+  /**
+   * @copydoc Dali::TapGestureDetector::GetMinimumTapsRequired()
+   */
+  unsigned int GetMinimumTapsRequired() const;
+
+  /**
+   * @copydoc Dali::TapGestureDetector::SetMaximumTapsRequired()
+   */
+  unsigned int GetMaximumTapsRequired() const;
+
+  /**
+   * @copydoc Dali::TapGestureDetector::GetTouchesRequired()
+   */
+  unsigned int GetTouchesRequired() const;
+
+public:
+
+  /**
+   * Called by the TapGestureProcessor when a tap gesture event occurs within the bounds of our
+   * attached actor.
+   * @param[in]  tappedActor  The tapped actor.
+   * @param[in]  tap          The tap gesture.
+   */
+  void EmitTapGestureSignal(Dali::Actor tappedActor, const TapGesture& tap);
+
+public: // Signals
+
+  /**
+   * @copydoc Dali::TapGestureDetector::DetectedSignal()
+   */
+  Dali::TapGestureDetector::DetectedSignalType& DetectedSignal()
+  {
+    return mDetectedSignal;
+  }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~TapGestureDetector();
+
+private:
+
+  // Undefined
+  TapGestureDetector(const TapGestureDetector&);
+  TapGestureDetector& operator=(const TapGestureDetector& rhs);
+
+private: // GestureDetector overrides
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorAttach(Actor&)
+   */
+  virtual void OnActorAttach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDetach(Actor&)
+   */
+  virtual void OnActorDetach(Actor& actor);
+
+  /**
+   * @copydoc Dali::Internal::GestureDetector::OnActorDestroyed(Object&)
+   */
+  virtual void OnActorDestroyed(Object& object);
+
+private:
+
+  Dali::TapGestureDetector::DetectedSignalType mDetectedSignal;
+
+  unsigned int mMinimumTapsRequired;
+  unsigned int mMaximumTapsRequired;
+  unsigned int mTouchesRequired;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::TapGestureDetector& GetImplementation(Dali::TapGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "TapGestureDetector handle is empty" );
+
+  BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<Internal::TapGestureDetector&>(handle);
+}
+
+inline const Internal::TapGestureDetector& GetImplementation(const Dali::TapGestureDetector& detector)
+{
+  DALI_ASSERT_ALWAYS( detector && "TapGestureDetector handle is empty" );
+
+  const BaseObject& handle = detector.GetBaseObject();
+
+  return static_cast<const Internal::TapGestureDetector&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TAP_GESTURE_DETECTOR_H__
diff --git a/dali/internal/event/events/tap-gesture-processor.cpp b/dali/internal/event/events/tap-gesture-processor.cpp
new file mode 100644 (file)
index 0000000..2814208
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/tap-gesture-processor.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/tap-gesture.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/events/tap-gesture-event.h>
+#include <dali/integration-api/gesture-manager.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * Creates a TapGesture and asks the specified detector to emit its detected signal.
+ * @param[in]  actor             The actor on which a tap has occurred.
+ * @param[in]  gestureDetectors  A reference to gesture detectors that should emit the signal.
+ * @param[in]  tapEvent          The tapEvent received from the adaptor.
+ * @param[in]  localPoint        Relative to the actor attached to the detector.
+ */
+void EmitTapSignal(
+  Actor* actor,
+  const GestureDetectorContainer& gestureDetectors,
+  const Integration::TapGestureEvent& tapEvent,
+  Vector2 localPoint)
+{
+  TapGesture tap;
+  tap.time = tapEvent.time;
+  tap.numberOfTaps = tapEvent.numberOfTaps;
+  tap.numberOfTouches = tapEvent.numberOfTouches;
+  tap.screenPoint = tapEvent.point;
+  tap.localPoint = localPoint;
+
+  Dali::Actor actorHandle( actor );
+  const GestureDetectorContainer::const_iterator endIter = gestureDetectors.end();
+  for ( GestureDetectorContainer::const_iterator iter = gestureDetectors.begin(); iter != endIter; ++iter )
+  {
+    static_cast< TapGestureDetector* >( *iter )->EmitTapGestureSignal( actorHandle, tap );
+  }
+}
+
+} // unnamed namespace
+
+TapGestureProcessor::TapGestureProcessor( Stage& stage, Integration::GestureManager& gestureManager)
+: GestureProcessor( Gesture::Tap ),
+  mStage( stage ),
+  mGestureManager( gestureManager ),
+  mGestureDetectors(),
+  mMinTapsRequired( 1 ),
+  mMaxTapsRequired( 1 ),
+  mMinTouchesRequired( 1 ),
+  mMaxTouchesRequired( 1 ),
+  mCurrentTapEvent( NULL ),
+  mPossibleProcessed( false )
+{
+}
+
+TapGestureProcessor::~TapGestureProcessor()
+{
+}
+
+void TapGestureProcessor::Process( const Integration::TapGestureEvent& tapEvent )
+{
+  switch ( tapEvent.state )
+  {
+    case Gesture::Possible:
+    {
+      // Do a hit test and if an actor has been hit then save to see if tap event is still valid on a tap( same actor being hit )
+      HitTestAlgorithm::Results hitTestResults;
+      if ( HitTest( mStage, tapEvent.point, hitTestResults ) )
+      {
+        SetActor( &GetImplementation( hitTestResults.actor ) );
+        mCurrentTapActor.SetActor( GetCurrentGesturedActor() );
+
+        // Indicate that we've processed a touch down. Bool should be sufficient as a change in actor will result in a cancellation
+        mPossibleProcessed = true;
+      }
+      else
+      {
+        ResetActor();
+      }
+      break;
+    }
+
+    case Gesture::Started:
+    {
+      // Ensure that we're processing a hit on the current actor and that we've already processed a touch down
+      HitTestAlgorithm::Results hitTestResults;
+      if ( GetCurrentGesturedActor() && HitTest( mStage, tapEvent.point, hitTestResults ) && mPossibleProcessed )
+      {
+        // Check that this actor is still the one that was used for the last touch down ?
+        if ( mCurrentTapActor.GetActor() == &GetImplementation( hitTestResults.actor ) )
+        {
+          mCurrentTapEvent = &tapEvent;
+          ProcessAndEmit( hitTestResults );
+        }
+        mCurrentTapEvent = NULL;
+        mPossibleProcessed = false;
+      }
+      break;
+    }
+
+    case Gesture::Cancelled:
+    {
+      mPossibleProcessed = false;
+      ResetActor();
+      break;
+    }
+
+    case Gesture::Continuing:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Continuing\n" );
+      break;
+
+    case Gesture::Finished:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Finished\n" );
+      break;
+
+    case Gesture::Clear:
+      DALI_ASSERT_ALWAYS( false && "Incorrect state received from Integration layer: Clear\n" );
+      break;
+  }
+}
+
+void TapGestureProcessor::AddGestureDetector( TapGestureDetector* gestureDetector )
+{
+  bool firstRegistration(mGestureDetectors.empty());
+
+  mGestureDetectors.push_back(gestureDetector);
+
+  const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
+  const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
+  const unsigned int touchesRequired = gestureDetector->GetTouchesRequired();
+
+  DALI_ASSERT_ALWAYS( minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested" );
+
+  if (firstRegistration)
+  {
+    // If this is the first tap gesture detector that has been added, then our minimum and maximum
+    // requirements are the same as each other.
+
+    mMinTapsRequired = minTapsRequired;
+    mMaxTapsRequired = maxTapsRequired;
+    mMinTouchesRequired = mMaxTouchesRequired = touchesRequired;
+
+    Integration::TapGestureRequest request;
+    request.minTaps = mMinTapsRequired;
+    request.maxTaps = mMaxTapsRequired;
+    request.minTouches = mMinTouchesRequired;
+    request.maxTouches = mMaxTouchesRequired;
+    mGestureManager.Register(request);
+  }
+  else
+  {
+    // If we have already registered for tap gesture detection before then we need to check our
+    // minimum and maximums and see if our gesture detection requirements have changed, if they
+    // have, then we should ask the adaptor to update its detection policy.
+
+    // This is quicker than calling UpdateDetection as there is no need to iterate through the container
+
+    unsigned int minTaps = mMinTapsRequired < minTapsRequired ? mMinTapsRequired : minTapsRequired;
+    unsigned int maxTaps = mMaxTapsRequired > maxTapsRequired ? mMaxTapsRequired : maxTapsRequired;
+    unsigned int minTouches = mMinTouchesRequired < touchesRequired ? mMinTouchesRequired : touchesRequired;
+    unsigned int maxTouches = mMaxTouchesRequired > touchesRequired ? mMaxTouchesRequired : touchesRequired;
+
+    if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
+         (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
+    {
+      Integration::TapGestureRequest request;
+      request.minTaps = mMinTapsRequired = minTaps;
+      request.maxTaps = mMaxTapsRequired = maxTaps;
+      request.minTouches = mMinTouchesRequired = minTouches;
+      request.maxTouches = mMaxTouchesRequired = maxTouches;
+      mGestureManager.Update(request);
+    }
+  }
+}
+
+void TapGestureProcessor::RemoveGestureDetector( TapGestureDetector* gestureDetector )
+{
+  // Find detector ...
+  TapGestureDetectorContainer::iterator endIter = std::remove( mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector );
+  DALI_ASSERT_DEBUG( endIter != mGestureDetectors.end() );
+
+  // ... and remove it
+  mGestureDetectors.erase( endIter, mGestureDetectors.end() );
+
+  if ( mGestureDetectors.empty() )
+  {
+    Integration::GestureRequest request(Gesture::Tap);
+    mGestureManager.Unregister(request);
+
+    ResetActor();
+  }
+  else
+  {
+    UpdateDetection();
+  }
+}
+
+void TapGestureProcessor::GestureDetectorUpdated( TapGestureDetector* gestureDetector )
+{
+  DALI_ASSERT_DEBUG(find(mGestureDetectors.begin(), mGestureDetectors.end(), gestureDetector) != mGestureDetectors.end());
+
+  const unsigned int minTapsRequired = gestureDetector->GetMinimumTapsRequired();
+  const unsigned int maxTapsRequired = gestureDetector->GetMaximumTapsRequired();
+
+  DALI_ASSERT_ALWAYS( minTapsRequired <= maxTapsRequired && "Minimum taps requested is greater than the maximum requested" );
+
+  UpdateDetection();
+}
+
+void TapGestureProcessor::UpdateDetection()
+{
+  DALI_ASSERT_DEBUG(!mGestureDetectors.empty());
+
+  unsigned int minTaps = UINT_MAX;
+  unsigned int maxTaps = 0;
+  unsigned int minTouches = UINT_MAX;
+  unsigned int maxTouches = 0;
+
+  for ( TapGestureDetectorContainer::iterator iter = mGestureDetectors.begin(), endIter = mGestureDetectors.end(); iter != endIter; ++iter )
+  {
+    TapGestureDetector* detector(*iter);
+
+    const unsigned int minTapsRequired = detector->GetMinimumTapsRequired();
+    const unsigned int maxTapsRequired = detector->GetMaximumTapsRequired();
+    const unsigned int touchesRequired = detector->GetTouchesRequired();
+
+    minTaps = minTapsRequired < minTaps ? minTapsRequired : minTaps;
+    maxTaps = maxTapsRequired > maxTaps ? maxTapsRequired : maxTaps;
+    minTouches = touchesRequired < minTouches ? touchesRequired : minTouches;
+    maxTouches = touchesRequired > maxTouches ? touchesRequired : maxTouches;
+  }
+
+  if ( (minTaps != mMinTapsRequired)||(maxTaps != mMaxTapsRequired) ||
+       (minTouches != mMinTouchesRequired)||(maxTouches != mMaxTouchesRequired) )
+  {
+    Integration::TapGestureRequest request;
+    request.minTaps = mMinTapsRequired = minTaps;
+    request.maxTaps = mMaxTapsRequired = maxTaps;
+    request.minTouches = mMinTouchesRequired = minTouches;
+    request.maxTouches = mMaxTouchesRequired = maxTouches;
+    mGestureManager.Update(request);
+  }
+}
+
+bool TapGestureProcessor::CheckGestureDetector( GestureDetector* detector, Actor* actor )
+{
+  DALI_ASSERT_DEBUG( mCurrentTapEvent );
+
+  TapGestureDetector* tapDetector ( static_cast< TapGestureDetector* >( detector ) );
+
+  return ( ( tapDetector->GetMinimumTapsRequired() <= mCurrentTapEvent->numberOfTaps ) && ( tapDetector->GetMaximumTapsRequired() >= mCurrentTapEvent->numberOfTaps ) ) &&
+         ( tapDetector->GetTouchesRequired() == mCurrentTapEvent->numberOfTouches );
+}
+
+void TapGestureProcessor::EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates )
+{
+  DALI_ASSERT_DEBUG( mCurrentTapEvent );
+
+  EmitTapSignal( actor, gestureDetectors, *mCurrentTapEvent, actorCoordinates );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/tap-gesture-processor.h b/dali/internal/event/events/tap-gesture-processor.h
new file mode 100644 (file)
index 0000000..0f7c6ca
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef __DALI_INTERNAL_TAP_GESTURE_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_TAP_GESTURE_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/tap-gesture-detector-impl.h>
+#include <dali/internal/event/events/gesture-processor.h>
+#include "actor-observer.h"
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GestureManager;
+struct GestureEvent;
+struct TapGestureEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+class Actor;
+
+/**
+ * Tap Gesture Event Processing:
+ *
+ * When we receive a tap gesture event, we do the following:
+ * - Find the actor that requires a tap where the tap occurred.
+ * - Emit the gesture if the tap gesture event satisfies the detector conditions.
+ */
+class TapGestureProcessor : public GestureProcessor
+{
+public:
+
+  /**
+   * Create a tap gesture processor.
+   * @param[in] stage The stage.
+   * @param[in] gestureManager The gesture manager.
+   */
+  TapGestureProcessor(Stage& stage, Integration::GestureManager& gestureManager);
+
+  /**
+   * Non-virtual destructor; TapGestureProcessor is not a base class
+   */
+  ~TapGestureProcessor();
+
+public: // To be called by GestureEventProcessor
+
+  /**
+   * This method is called whenever a tap gesture event occurs.
+   * @param[in] tapEvent The event that has occurred.
+   */
+  void Process(const Integration::TapGestureEvent& tapEvent);
+
+  /**
+   * Adds a gesture detector to this gesture processor.
+   * If this is the first gesture detector being added, then this method registers the required
+   * gesture with the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being added.
+   */
+  void AddGestureDetector(TapGestureDetector* gestureDetector);
+
+  /**
+   * Removes the specified gesture detector from this gesture processor.  If, after removing this
+   * gesture detector, there are no more gesture detectors registered, then this method unregisters
+   * the gesture from the adaptor.
+   * @param[in]  gestureDetector  The gesture detector being removed.
+   */
+  void RemoveGestureDetector(TapGestureDetector* gestureDetector);
+
+  /**
+   * This method updates the gesture detection parameters.
+   * @param[in]  gestureDetector  The gesture detector that has been updated.
+   */
+  void GestureDetectorUpdated(TapGestureDetector* gestureDetector);
+
+private:
+
+  // Undefined
+  TapGestureProcessor(const TapGestureProcessor&);
+  TapGestureProcessor& operator=(const TapGestureProcessor& rhs);
+
+private:
+
+  /**
+   * Iterates through our GestureDetectors and determines if we need to ask the adaptor to update
+   * its detection policy.  If it does, it sends the appropriate gesture update request to adaptor.
+   */
+  void UpdateDetection();
+
+  // GestureProcessor overrides
+
+  /**
+   * @copydoc GestureProcessor::OnGesturedActorStageDisconnection()
+   */
+  void OnGesturedActorStageDisconnection() { /* Nothing to do */ }
+
+  /**
+   * @copydoc GestureProcessor::CheckGestureDetector()
+   */
+  bool CheckGestureDetector( GestureDetector* detector, Actor* actor );
+
+  /**
+   * @copydoc GestureProcessor::EmitGestureSignal()
+   */
+  void EmitGestureSignal( Actor* actor, const GestureDetectorContainer& gestureDetectors, Vector2 actorCoordinates );
+
+private:
+
+  Stage& mStage;
+  Integration::GestureManager& mGestureManager;
+  TapGestureDetectorContainer mGestureDetectors;
+
+  unsigned int mMinTapsRequired;
+  unsigned int mMaxTapsRequired;
+  unsigned int mMinTouchesRequired;
+  unsigned int mMaxTouchesRequired;
+
+  ActorObserver mCurrentTapActor; ///< Observer for the current gesture actor
+  const Integration::TapGestureEvent* mCurrentTapEvent; ///< Pointer to current TapEvent, used when calling ProcessAndEmit()
+  bool mPossibleProcessed; ///< Indication of whether we've processed a touch down for this gestuee
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TAP_GESTURE_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/touch-event-processor.cpp b/dali/internal/event/events/touch-event-processor.cpp
new file mode 100644 (file)
index 0000000..0e58e54
--- /dev/null
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/touch-event-processor.h>
+
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#endif
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/signals/callback.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/events/hit-test-algorithm-impl.h>
+#include <dali/internal/event/events/multi-point-event-util.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_TOUCH_PROCESSOR" );
+
+const char * TOUCH_POINT_STATE[TouchPoint::Last] =
+{
+  "Down",
+  "Up",
+  "Motion",
+  "Leave",
+  "Stationary",
+  "Interrupted",
+};
+
+#endif // defined(DEBUG_ENABLED)
+
+/**
+ *  Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitTouchSignals( Dali::Actor actor, const TouchEvent& event )
+{
+  Dali::Actor consumedActor;
+
+  if ( actor )
+  {
+    Dali::Actor oldParent( actor.GetParent() );
+
+    Actor& actorImpl( GetImplementation(actor) );
+
+    bool consumed( false );
+
+    // Only emit the signal if the actor's touch signal has connections (or derived actor implementation requires touch).
+    if ( actorImpl.GetTouchRequired() )
+    {
+      consumed = actorImpl.EmitTouchEventSignal( event );
+    }
+
+    if ( consumed )
+    {
+      // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+      consumedActor = Dali::Actor( &actorImpl );
+    }
+    else
+    {
+      // The actor may have been removed/reparented during the signal callbacks.
+      Dali::Actor parent = actor.GetParent();
+
+      if ( parent &&
+           (parent == oldParent) )
+      {
+        // One of the actor's parents may consumed the event and they should be set as the consumed actor.
+        consumedActor = EmitTouchSignals( parent, event );
+      }
+    }
+  }
+
+  return consumedActor;
+}
+
+/**
+ * Changes the state of the primary point to leave and emits the touch signals
+ */
+Dali::Actor EmitTouchSignals( Actor* actor, RenderTask& renderTask, const TouchEvent& originalEvent, TouchPoint::State state )
+{
+  TouchEvent touchEvent( originalEvent );
+
+  DALI_ASSERT_DEBUG( NULL != actor && "NULL actor pointer" );
+  if( actor )
+  {
+    TouchPoint& primaryPoint = touchEvent.points[0];
+
+    actor->ScreenToLocal( renderTask, primaryPoint.local.x, primaryPoint.local.y, primaryPoint.screen.x, primaryPoint.screen.y );
+
+    primaryPoint.hitActor = Dali::Actor(actor);
+    primaryPoint.state = state;
+  }
+
+  return EmitTouchSignals( Dali::Actor(actor), touchEvent );
+}
+
+} // unnamed namespace
+
+TouchEventProcessor::TouchEventProcessor( Stage& stage )
+: mStage( stage ),
+  mLastPrimaryHitActor( MakeCallback( this, &TouchEventProcessor::OnObservedActorDisconnected ) ),
+  mLastConsumedActor(),
+  mTouchDownConsumedActor(),
+  mLastRenderTask()
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+TouchEventProcessor::~TouchEventProcessor()
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+}
+
+void TouchEventProcessor::ProcessTouchEvent( const Integration::TouchEvent& event )
+{
+  DALI_LOG_TRACE_METHOD( gLogFilter );
+
+  DALI_ASSERT_ALWAYS( !event.points.empty() && "Empty TouchEvent sent from Integration\n" );
+
+  Stage& stage = mStage;
+
+  PRINT_HIERARCHY(gLogFilter);
+
+  // Copy so we can add the results of a hit-test.
+  TouchEvent touchEvent( event.time );
+
+  // 1) Check if it is an interrupted event - we should inform our last primary hit actor about this
+  //    and emit the stage signal as well.
+
+  if ( event.points[0].state == TouchPoint::Interrupted )
+  {
+    Dali::Actor consumingActor;
+    touchEvent.points.push_back(event.points[0]);
+
+    Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+    if ( lastPrimaryHitActor )
+    {
+      Dali::Actor lastPrimaryHitActorHandle( lastPrimaryHitActor );
+      touchEvent.points[0].hitActor = lastPrimaryHitActorHandle;
+      consumingActor = EmitTouchSignals( lastPrimaryHitActorHandle, touchEvent );
+    }
+
+    // If the last consumed actor was different to the primary hit actor then inform it as well (if it has not already been informed).
+    Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+    if ( lastConsumedActor &&
+         lastConsumedActor != lastPrimaryHitActor &&
+         lastConsumedActor != consumingActor )
+    {
+      Dali::Actor lastConsumedActorHandle( lastConsumedActor );
+      touchEvent.points[0].hitActor = lastConsumedActorHandle;
+      EmitTouchSignals( lastConsumedActorHandle, touchEvent );
+    }
+
+    // Tell the touch-down consuming actor as well, if required
+    Actor* touchDownConsumedActor( mTouchDownConsumedActor.GetActor() );
+    if ( touchDownConsumedActor &&
+         touchDownConsumedActor != lastPrimaryHitActor &&
+         touchDownConsumedActor != lastConsumedActor &&
+         touchDownConsumedActor != consumingActor )
+    {
+      Dali::Actor touchDownConsumedActorHandle( touchDownConsumedActor );
+      touchEvent.points[0].hitActor = touchDownConsumedActorHandle;
+      EmitTouchSignals( touchDownConsumedActorHandle, touchEvent );
+    }
+
+    mLastPrimaryHitActor.SetActor( NULL );
+    mLastConsumedActor.SetActor( NULL );
+    mTouchDownConsumedActor.SetActor( NULL );
+    mLastRenderTask.Reset();
+
+    touchEvent.points[0].hitActor.Reset();
+    mStage.EmitTouchedSignal( touchEvent );
+
+    return; // No need for hit testing
+  }
+
+  // 2) Hit Testing.
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "\n" );
+  DALI_LOG_INFO( gLogFilter, Debug::General, "Point(s): %d\n", event.GetPointCount() );
+
+  Dali::RenderTask currentRenderTask;
+
+  for ( TouchPointContainerConstIterator iter = event.points.begin(), beginIter = event.points.begin(), endIter = event.points.end(); iter != endIter; ++iter )
+  {
+    HitTestAlgorithm::Results hitTestResults;
+    HitTestAlgorithm::HitTest( stage, iter->screen, hitTestResults );
+
+    TouchPoint newPoint( iter->deviceId, iter->state, iter->screen.x, iter->screen.y );
+    newPoint.hitActor = hitTestResults.actor;
+    newPoint.local = hitTestResults.actorCoordinates;
+
+    touchEvent.points.push_back( newPoint );
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  State(%s), Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n",
+                   TOUCH_POINT_STATE[iter->state], iter->screen.x, iter->screen.y,
+                   ( hitTestResults.actor ? (void*)&hitTestResults.actor.GetBaseObject() : NULL ),
+                   ( hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" ),
+                   hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y );
+
+    // Only set the currentRenderTask for the primary hit actor.
+    if ( iter == beginIter && hitTestResults.renderTask )
+    {
+      currentRenderTask = hitTestResults.renderTask;
+    }
+  }
+
+  // 3) Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+
+  // Emit the touch signal
+  Dali::Actor consumedActor;
+  if ( currentRenderTask )
+  {
+    consumedActor = EmitTouchSignals( touchEvent.points[0].hitActor, touchEvent );
+  }
+
+  TouchPoint& primaryPoint = touchEvent.points[0];
+  Dali::Actor primaryHitActor = primaryPoint.hitActor;
+  TouchPoint::State primaryPointState = primaryPoint.state;
+
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "PrimaryHitActor:     (%p) %s\n", primaryPoint.hitActor ? (void*)&primaryPoint.hitActor.GetBaseObject() : NULL, primaryPoint.hitActor ? primaryPoint.hitActor.GetName().c_str() : "" );
+  DALI_LOG_INFO( gLogFilter, Debug::Concise, "ConsumedActor:       (%p) %s\n", consumedActor ? (void*)&consumedActor.GetBaseObject() : NULL, consumedActor ? consumedActor.GetName().c_str() : "" );
+
+  if ( ( primaryPointState == TouchPoint::Down ) &&
+       ( touchEvent.GetPointCount() == 1 ) &&
+       ( consumedActor && consumedActor.OnStage() ) )
+  {
+    mTouchDownConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+  }
+
+  // 4) Check if the last primary hit actor requires a leave event and if it was different to the current primary
+  //    hit actor.  Also process the last consumed actor in the same manner.
+
+  Actor* lastPrimaryHitActor( mLastPrimaryHitActor.GetActor() );
+  Actor* lastConsumedActor( mLastConsumedActor.GetActor() );
+  if( (primaryPointState == TouchPoint::Motion) || (primaryPointState == TouchPoint::Up) || (primaryPointState == TouchPoint::Stationary) )
+  {
+    if ( mLastRenderTask )
+    {
+      Dali::Actor leaveEventConsumer;
+      RenderTask& lastRenderTaskImpl( GetImplementation( mLastRenderTask ) );
+
+      if( lastPrimaryHitActor &&
+          lastPrimaryHitActor != primaryHitActor &&
+          lastPrimaryHitActor != consumedActor )
+      {
+        if( lastPrimaryHitActor->IsHittable() && IsActuallySensitive( lastPrimaryHitActor ) )
+        {
+          if ( lastPrimaryHitActor->GetLeaveRequired() )
+          {
+            DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Hit):     (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+            leaveEventConsumer = EmitTouchSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEvent, TouchPoint::Leave );
+          }
+        }
+        else
+        {
+          // At this point mLastPrimaryHitActor was touchable and sensitive in the previous touch event process but is not in the current one.
+          // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+          DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Hit):     (%p) %s\n", (void*)lastPrimaryHitActor, lastPrimaryHitActor->GetName().c_str() );
+          leaveEventConsumer = EmitTouchSignals( mLastPrimaryHitActor.GetActor(), lastRenderTaskImpl, touchEvent, TouchPoint::Interrupted );
+        }
+      }
+
+      // Check if the motion event has been consumed by another actor's listener.  In this case, the previously
+      // consumed actor's listeners may need to be informed (through a leave event).
+      // Further checks here to ensure we do not signal the same actor twice for the same event.
+      if ( lastConsumedActor &&
+           lastConsumedActor != consumedActor &&
+           lastConsumedActor != lastPrimaryHitActor &&
+           lastConsumedActor != primaryHitActor &&
+           lastConsumedActor != leaveEventConsumer )
+      {
+        if( lastConsumedActor->IsHittable() && IsActuallySensitive( lastConsumedActor ) )
+        {
+          if( lastConsumedActor->GetLeaveRequired() )
+          {
+            DALI_LOG_INFO( gLogFilter, Debug::Concise, "LeaveActor(Consume): (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+            EmitTouchSignals( lastConsumedActor, lastRenderTaskImpl, touchEvent, TouchPoint::Leave );
+          }
+        }
+        else
+        {
+          // At this point mLastConsumedActor was touchable and sensitive in the previous touch event process but is not in the current one.
+          // An interrupted event is send to allow some actors to go back to their original state (i.e. Button controls)
+          DALI_LOG_INFO( gLogFilter, Debug::Concise, "InterruptedActor(Consume):     (%p) %s\n", (void*)lastConsumedActor, lastConsumedActor->GetName().c_str() );
+          EmitTouchSignals( mLastConsumedActor.GetActor(), lastRenderTaskImpl, touchEvent, TouchPoint::Interrupted );
+        }
+      }
+    }
+  }
+
+  // 5) If our primary point is an Up event, then the primary point (in multi-touch) will change next
+  //    time so set our last primary actor to NULL.  Do the same to the last consumed actor as well.
+
+  if ( primaryPointState == TouchPoint::Up )
+  {
+    mLastPrimaryHitActor.SetActor( NULL );
+    mLastConsumedActor.SetActor( NULL );
+    mLastRenderTask.Reset();
+  }
+  else
+  {
+    // The primaryHitActor may have been removed from the stage so ensure it is still on the stage before setting members.
+    if ( primaryHitActor && primaryHitActor.OnStage() )
+    {
+      mLastPrimaryHitActor.SetActor( &GetImplementation( primaryHitActor ) );
+
+      // Only observe the consumed actor if we have a primaryHitActor (check if it is still on stage).
+      if ( consumedActor && consumedActor.OnStage() )
+      {
+        mLastConsumedActor.SetActor( &GetImplementation( consumedActor ) );
+      }
+      else
+      {
+        mLastConsumedActor.SetActor( NULL );
+      }
+
+      mLastRenderTask = currentRenderTask;
+    }
+    else
+    {
+      mLastPrimaryHitActor.SetActor( NULL );
+      mLastConsumedActor.SetActor( NULL );
+      mLastRenderTask.Reset();
+    }
+  }
+
+  // 6) Emit an interrupted event to the touch-down actor if it hasn't consumed the up and
+  //    emit the stage touched event if required.
+
+  if ( touchEvent.GetPointCount() == 1 ) // Only want the first touch and the last release
+  {
+    switch ( primaryPointState )
+    {
+      case TouchPoint::Up:
+      {
+        Actor* touchDownConsumedActor( mTouchDownConsumedActor.GetActor() );
+        if ( touchDownConsumedActor &&
+             touchDownConsumedActor != consumedActor &&
+             touchDownConsumedActor != lastPrimaryHitActor &&
+             touchDownConsumedActor != lastConsumedActor )
+        {
+          Dali::Actor touchDownConsumedActorHandle( touchDownConsumedActor );
+          touchEvent.points[0].hitActor = touchDownConsumedActorHandle;
+          touchEvent.points[0].state = TouchPoint::Interrupted;
+          EmitTouchSignals( touchDownConsumedActorHandle, touchEvent );
+
+          // Restore touch-event to original state
+          touchEvent.points[0].hitActor = primaryHitActor;
+          touchEvent.points[0].state = primaryPointState;
+        }
+
+        mTouchDownConsumedActor.SetActor( NULL );
+      }
+      // No break, Fallthrough
+
+      case TouchPoint::Down:
+      {
+        mStage.EmitTouchedSignal( touchEvent );
+        break;
+      }
+
+      case TouchPoint::Motion:
+      case TouchPoint::Leave:
+      case TouchPoint::Stationary:
+      case TouchPoint::Interrupted:
+      case TouchPoint::Last:
+      {
+        // Ignore
+        break;
+      }
+    }
+  }
+}
+
+void TouchEventProcessor::OnObservedActorDisconnected( Actor* actor )
+{
+  if ( actor == mLastPrimaryHitActor.GetActor() )
+  {
+    Dali::Actor handle( actor );
+    TouchEvent touchEvent( 0 );
+    touchEvent.points.push_back( TouchPoint( 0, TouchPoint::Interrupted, 0.0f, 0.0f ) );
+    touchEvent.points[0].hitActor = handle;
+
+    Dali::Actor eventConsumer = EmitTouchSignals( handle, touchEvent );
+
+    if ( mLastConsumedActor.GetActor() != eventConsumer )
+    {
+      EmitTouchSignals( Dali::Actor( mLastConsumedActor.GetActor() ), touchEvent );
+    }
+
+    // Do not set mLastPrimaryHitActor to NULL we may be iterating through its observers
+
+    mLastConsumedActor.SetActor( NULL );
+    mLastRenderTask.Reset();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/touch-event-processor.h b/dali/internal/event/events/touch-event-processor.h
new file mode 100644 (file)
index 0000000..e0c38b7
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __DALI_INTERNAL_TOUCH_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_TOUCH_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/event/events/actor-observer.h>
+
+namespace Dali
+{
+
+class Actor;
+struct Vector2;
+struct Vector4;
+
+namespace Integration
+{
+struct TouchEvent;
+}
+
+namespace Internal
+{
+
+class Actor;
+class Stage;
+struct ActorObserver;
+
+/**
+ * <h3>Multi-Touch Event Processing:</h3>
+ *
+ * The TouchEventProcessor processes touch events and emits the Touched signal on the hit actor (and
+ * its parents).
+ *
+ * - Hit Testing & Touch Event Delivery are described in Dali::Actor.
+ */
+class TouchEventProcessor
+{
+public:
+
+  /**
+   * Create an event processor.
+   * @param[in] stage The stage.
+   */
+  TouchEventProcessor( Stage& stage );
+
+  /**
+   * Non-virtual destructor; TouchEventProcessor is not a base class
+   */
+  ~TouchEventProcessor();
+
+  /**
+   * This function is called by the event processor whenever a touch event occurs.
+   * @param[in] event The touch event that has occurred.
+   */
+  void ProcessTouchEvent( const Integration::TouchEvent& event );
+
+private:
+
+  // Undefined
+  TouchEventProcessor(const TouchEventProcessor&);
+
+  // Undefined
+  TouchEventProcessor& operator=(const TouchEventProcessor& rhs);
+
+  /**
+   * Called by some actor-observers when the observed actor is disconnected.
+   *
+   * @param[in]  actor  The actor that has been disconnected.
+   */
+  void OnObservedActorDisconnected( Actor* actor );
+
+private:
+
+  Stage& mStage; ///< Used to deliver touch events
+  ActorObserver mLastPrimaryHitActor; ///< Stores the last primary point hit actor
+  ActorObserver mLastConsumedActor; ///< Stores the last consumed actor
+  ActorObserver mTouchDownConsumedActor; ///< Stores the touch-down consumed actor
+  Dali::RenderTask mLastRenderTask; ///< The RenderTask used for the last hit actor
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TOUCH_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/events/wheel-event-processor.cpp b/dali/internal/event/events/wheel-event-processor.cpp
new file mode 100644 (file)
index 0000000..6d08325
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/events/wheel-event-processor.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/wheel-event.h>
+#include <dali/devel-api/events/hit-test-algorithm.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/integration-api/events/wheel-event-integ.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/actors/actor-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_WHEEL_PROCESSOR");
+#endif
+
+/**
+ *  Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+ */
+Dali::Actor EmitWheelSignals( Dali::Actor actor, const WheelEvent& event )
+{
+  Dali::Actor consumedActor;
+
+  if ( actor )
+  {
+    Dali::Actor oldParent( actor.GetParent() );
+
+    Actor& actorImpl( GetImplementation(actor) );
+
+    bool consumed( false );
+
+    // Only do the conversion and emit the signal if the actor's wheel signal has connections.
+    if ( actorImpl.GetWheelEventRequired() )
+    {
+      // Emit the signal to the parent
+      consumed = actorImpl.EmitWheelEventSignal( event );
+    }
+
+    if ( consumed )
+    {
+      // One of this actor's listeners has consumed the event so set this actor as the consumed actor.
+      consumedActor = Dali::Actor( &actorImpl );
+    }
+    else
+    {
+      // The actor may have been removed/reparented during the signal callbacks.
+      Dali::Actor parent = actor.GetParent();
+
+      if ( parent &&
+           (parent == oldParent) )
+      {
+        // One of the actor's parents may consumed the event and they should be set as the consumed actor.
+        consumedActor = EmitWheelSignals( parent, event );
+      }
+    }
+  }
+
+  return consumedActor;
+}
+
+/**
+ * The function to be used in the hit-test algorithm to check whether the actor is wheelable.
+ */
+bool IsActorWheelableFunction(Dali::Actor actor, Dali::HitTestAlgorithm::TraverseType type)
+{
+  bool hittable = false;
+
+  switch (type)
+  {
+    case Dali::HitTestAlgorithm::CHECK_ACTOR:
+    {
+      if( GetImplementation(actor).GetWheelEventRequired() && // Does the Application or derived actor type require a wheel event?
+          GetImplementation(actor).IsHittable() )
+      {
+        hittable = true;
+      }
+      break;
+    }
+    case Dali::HitTestAlgorithm::DESCEND_ACTOR_TREE:
+    {
+      if( actor.IsVisible() ) // Actor is visible, if not visible then none of its children are visible.
+      {
+        hittable = true;
+      }
+      break;
+    }
+    default:
+    {
+      break;
+    }
+  }
+
+  return hittable;
+};
+
+} // unnamed namespace
+
+
+WheelEventProcessor::WheelEventProcessor(Stage& stage)
+: mStage(stage)
+{
+}
+
+WheelEventProcessor::~WheelEventProcessor()
+{
+}
+
+void WheelEventProcessor::ProcessWheelEvent(const Integration::WheelEvent& event)
+{
+  Stage& stage = mStage;
+  WheelEvent wheelEvent( static_cast< WheelEvent::Type >(event.type), event.direction, event.modifiers, event.point, event.z, event.timeStamp );
+
+  if( wheelEvent.type == WheelEvent::MOUSE_WHEEL )
+  {
+    HitTestAlgorithm::Results hitTestResults;
+    HitTestAlgorithm::HitTest( Dali::Stage(&stage), event.point, hitTestResults, IsActorWheelableFunction );
+
+    DALI_LOG_INFO( gLogFilter, Debug::General, "  Screen(%.0f, %.0f), HitActor(%p, %s), Local(%.2f, %.2f)\n",
+                   event.point.x, event.point.y,
+                   ( hitTestResults.actor ? (void*)&hitTestResults.actor.GetBaseObject() : NULL ),
+                   ( hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" ),
+                   hitTestResults.actorCoordinates.x, hitTestResults.actorCoordinates.y );
+
+    // Recursively deliver events to the actor and its parents, until the event is consumed or the stage is reached.
+    Dali::Actor consumedActor = EmitWheelSignals( hitTestResults.actor, wheelEvent );
+
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "HitActor:      (%p) %s\n", hitTestResults.actor ? (void*)&hitTestResults.actor.GetBaseObject() : NULL, hitTestResults.actor ? hitTestResults.actor.GetName().c_str() : "" );
+    DALI_LOG_INFO( gLogFilter, Debug::Concise, "ConsumedActor: (%p) %s\n", consumedActor ? (void*)&consumedActor.GetBaseObject() : NULL, consumedActor ? consumedActor.GetName().c_str() : "" );
+  }
+  else
+  {
+    // if CUSTOM_WHEEL, emit the key event signal from stage.
+    mStage.EmitWheelEventSignal( wheelEvent );
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/events/wheel-event-processor.h b/dali/internal/event/events/wheel-event-processor.h
new file mode 100644 (file)
index 0000000..bc26322
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __DALI_INTERNAL_WHEEL_EVENT_PROCESSOR_H__
+#define __DALI_INTERNAL_WHEEL_EVENT_PROCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Integration
+{
+struct WheelEvent;
+}
+
+namespace Internal
+{
+
+class Stage;
+
+/**
+ *  WheelEventProcessor receives the wheel events from the Dali Event processor.
+ *
+ *  When a wheel event is received the WheelEvent Processor emits the Wheeled signal
+ *  on the hit actor (and its parents).
+ *
+ * - Hit Testing is described in Dali::Actor.
+ */
+class WheelEventProcessor
+{
+public:
+
+  /**
+   * Create a wheel event processor.
+   */
+  WheelEventProcessor(Stage& stage);
+
+  /**
+   * Non-virtual destructor; WheelEventProcessor is not a base class
+   */
+  ~WheelEventProcessor();
+
+  /**
+   * This function is called by the event processor whenever a nouse wheel event occurs.
+   * @param[in] event The wheel event that has occurred.
+   */
+  void ProcessWheelEvent(const Integration::WheelEvent& event);
+
+private:
+
+  // Undefined
+  WheelEventProcessor(const WheelEventProcessor&);
+
+  // Undefined
+  WheelEventProcessor& operator=(const WheelEventProcessor& rhs);
+
+private:
+
+  Stage& mStage;               ///< Used to deliver the wheel events
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_WHEEL_EVENT_PROCESSOR_H__
diff --git a/dali/internal/event/images/atlas-impl.cpp b/dali/internal/event/images/atlas-impl.cpp
new file mode 100644 (file)
index 0000000..e5231de
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/atlas-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for memset()
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/platform-abstraction.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::Atlas ), typeid( Dali::Image ), NULL );
+}
+
+Atlas* Atlas::New( SizeType width,
+                   SizeType height,
+                   Pixel::Format pixelFormat,
+                   bool recoverContext)
+{
+  return new Atlas( width, height, pixelFormat, recoverContext );
+}
+
+void Atlas::Clear(const Vector4& color)
+{
+  ClearCache();
+  ClearBackground( color );
+}
+
+bool Atlas::Upload( BufferImage& bufferImage,
+                    SizeType xOffset,
+                    SizeType yOffset )
+{
+  bool uploadSuccess( false );
+
+  if( Compatible(bufferImage.GetPixelFormat(),
+                 xOffset + bufferImage.GetWidth(),
+                 yOffset + bufferImage.GetHeight() ) )
+  {
+    AllocateAtlas();
+    ResourceId destId = GetResourceId();
+    ResourceId srcId = bufferImage.GetResourceId();
+
+    if( destId && srcId )
+    {
+      mResourceClient.UploadBitmap( destId, srcId, xOffset, yOffset );
+      uploadSuccess = true;
+    }
+  }
+
+  return uploadSuccess;
+}
+
+bool Atlas::Upload( const std::string& url,
+                    SizeType xOffset,
+                    SizeType yOffset)
+{
+  bool uploadSuccess( false );
+
+  Integration::BitmapPtr bitmap = LoadBitmap( url );
+
+  if( bitmap && Compatible(bitmap->GetPixelFormat(), xOffset + bitmap->GetImageWidth(), yOffset + bitmap->GetImageHeight()) )
+  {
+    AllocateAtlas();
+    ResourceId destId = GetResourceId();
+    if( destId )
+    {
+      mResourceClient.UploadBitmap( destId, bitmap, xOffset, yOffset  );
+      uploadSuccess = true;
+
+      if( mRecoverContext )
+      {
+        mTiles.PushBack( new Tile(xOffset, yOffset, url) );
+      }
+    }
+  }
+  return uploadSuccess;
+}
+
+void Atlas::RecoverFromContextLoss()
+{
+  ResourceId destId = GetResourceId();
+  if( destId )
+  {
+    if( mClear )
+    {
+      ClearBackground( mClearColor );
+    }
+
+    if( mRecoverContext )
+    {
+      // Restore the atlas by re-uploading the url resources
+      Vector< Tile* >::ConstIterator end = mTiles.End();
+      for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+      {
+        Integration::BitmapPtr bitmap = LoadBitmap( (*iter)->url );
+        mResourceClient.UploadBitmap( destId, bitmap, (*iter)->xOffset, (*iter)->yOffset  );
+      }
+    }
+  }
+}
+
+Atlas::~Atlas()
+{
+  ReleaseAtlas();
+}
+
+Atlas::Atlas( SizeType width,
+              SizeType height,
+              Pixel::Format pixelFormat,
+              bool recoverContext )
+: mResourceClient( ThreadLocalStorage::Get().GetResourceClient() ),
+  mImageFactory( ThreadLocalStorage::Get().GetImageFactory() ),
+  mClearColor( Vector4::ZERO ),
+  mPixelFormat( pixelFormat ),
+  mClear( false ),
+  mRecoverContext( recoverContext )
+{
+  mWidth  = width;
+  mHeight = height;
+}
+
+void Atlas::Connect()
+{
+  ++mConnectionCount;
+
+  if( mConnectionCount == 1 )
+  {
+    AllocateAtlas();
+  }
+}
+
+void Atlas::Disconnect()
+{
+  if( mConnectionCount )
+  {
+    --mConnectionCount;
+
+    if ( Dali::Image::UNUSED == mReleasePolicy &&
+         mConnectionCount == 0 )
+    {
+      ReleaseAtlas();
+    }
+  }
+}
+
+bool Atlas::Compatible( Pixel::Format pixelFormat,
+                        SizeType x,
+                        SizeType y )
+{
+  bool Compatible(false);
+
+  if( mPixelFormat != pixelFormat )
+  {
+    DALI_LOG_ERROR( "Pixel format %d does not match Atlas format %d\n", pixelFormat, mPixelFormat );
+  }
+  else
+  {
+    if( x <= mWidth  && y <= mHeight )
+    {
+      Compatible = true;
+    }
+    else
+    {
+      DALI_LOG_ERROR( "image does not fit within the atlas \n" );
+    }
+  }
+
+  return Compatible;
+}
+
+void Atlas::AllocateAtlas()
+{
+  if( !mTicket )
+  {
+    mTicket = mResourceClient.AllocateTexture( mWidth, mHeight, mPixelFormat );
+    mTicket->AddObserver( *this );
+    mImageFactory.RegisterForContextRecovery( this );
+  }
+}
+
+void Atlas::ReleaseAtlas()
+{
+  mTicket.Reset();
+  ClearCache();
+  mImageFactory.UnregisterFromContextRecovery( this );
+}
+
+void Atlas::ClearBackground(const Vector4& color )
+{
+  AllocateAtlas();
+  ResourceId destId = GetResourceId();
+  if( destId )
+  {
+    const unsigned int numPixels = mWidth * mHeight;
+    unsigned int bytesPerPixel = Pixel::GetBytesPerPixel(mPixelFormat);
+    BufferImagePtr imageData = BufferImage::New( mWidth, mHeight, mPixelFormat );
+    PixelBuffer* pixbuf = imageData->GetBuffer();
+
+    if( pixbuf )
+    {
+      // converting color value from float 0.f~1.f to byte 0~255
+      unsigned char r =  static_cast<unsigned char>( 255.f * Clamp( color.r, 0.f, 1.f ) );
+      unsigned char g =  static_cast<unsigned char>( 255.f * Clamp( color.g, 0.f, 1.f ) );
+      unsigned char b =  static_cast<unsigned char>( 255.f * Clamp( color.b, 0.f, 1.f ) );
+      unsigned char a =  static_cast<unsigned char>( 255.f * Clamp( color.a, 0.f, 1.f ) );
+      if( mPixelFormat == Pixel::RGBA8888 )
+      {
+        // For little-endian byte order, the RGBA channels needs to be reversed for bit shifting.
+        uint32_t clearColor = ( (uint32_t) a<<24 | (uint32_t)b << 16 | (uint32_t)g << 8 | (uint32_t)r );
+        uint32_t* buf = (uint32_t *) pixbuf;
+        for( unsigned int i = 0; i < numPixels; ++i )
+        {
+          buf[i] = clearColor;
+        }
+      }
+      else if( mPixelFormat == Pixel::RGB888 )
+      {
+        for( unsigned int i = 0; i < numPixels; ++i )
+        {
+          pixbuf[i*bytesPerPixel] = r;
+          pixbuf[i*bytesPerPixel+1] = g;
+          pixbuf[i*bytesPerPixel+2] = b;
+        }
+      }
+      else if( mPixelFormat == Pixel::A8 )
+      {
+        memset( pixbuf, a, numPixels );
+      }
+    }
+
+    RectArea area;
+    imageData->Update(area);
+
+    mClearColor = color;
+    mClear = true;
+    mResourceClient.UploadBitmap( destId, imageData->GetResourceId(), 0, 0 );
+  }
+}
+
+void Atlas::ClearCache()
+{
+  Vector< Tile* >::ConstIterator end = mTiles.End();
+  for( Vector<Tile*>::Iterator iter = mTiles.Begin(); iter != end; iter++ )
+  {
+    delete *iter;
+  }
+  mTiles.Clear();
+}
+
+Integration::BitmapPtr Atlas::LoadBitmap( const std::string& url )
+{
+  Integration::BitmapResourceType resourceType;
+  Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+
+  Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously(resourceType, url);
+  Integration::BitmapPtr bitmap = static_cast<Integration::Bitmap*>( resource.Get());
+
+  return bitmap;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/atlas-impl.h b/dali/internal/event/images/atlas-impl.h
new file mode 100644 (file)
index 0000000..ae767f3
--- /dev/null
@@ -0,0 +1,209 @@
+#ifndef __DALI_INTERNAL_ATLAS_H__
+#define __DALI_INTERNAL_ATLAS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/devel-api/images/atlas.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceClient;
+
+typedef Dali::Atlas::SizeType SizeType;
+
+/**
+ * Internal class for Dali::Atlas
+ */
+class Atlas : public Image, public ContextRecoveryInterface
+{
+public:
+
+  /**
+   * @brief Create a new Atlas.
+   *
+   * @pre width & height are greater than zero.
+   * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format.
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
+   * @return A pointer to a new Atlas.
+   */
+  static Atlas* New( SizeType width,
+                     SizeType height,
+                     Pixel::Format pixelFormat,
+                     bool recoverContext);
+
+  /**
+   * @copydoc Dali::Atlas::Clear
+   */
+  void Clear( const Vector4& color  );
+
+  /**
+   * @copydoc Dali::Atlas::Upload( const BufferImage&, unsigned int, unsigned int )
+   */
+  bool Upload( BufferImage& bufferImage,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
+   * @copydoc Dali::Atlas::Upload( const std::string&, unsigned int, unsigned int )
+   */
+  bool Upload( const std::string& url,
+               SizeType xOffset,
+               SizeType yOffset );
+
+  /**
+   * @copydoc ContextRecoveryInterface::RecoverFromContextLoss
+   */
+  virtual void RecoverFromContextLoss();
+
+protected:
+
+  /**
+   * @brief Protected constructor.
+   *
+   * @pre width & height are greater than zero.
+   * The maximum size of the atlas is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] width          The atlas width in pixels.
+   * @param [in] height         The atlas height in pixels.
+   * @param [in] pixelFormat    The pixel format.
+   * @param [in] recoverContext Whether re-uploading the resource images automatically when regaining the context
+   */
+  Atlas( SizeType width,
+         SizeType height,
+         Pixel::Format pixelFormat,
+         bool recoverContext);
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Atlas();
+
+  /**
+   * @copydoc Dali::Internal::Image::Connect
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Image::Disconnect
+   */
+  virtual void Disconnect();
+
+private:
+
+  /**
+   * Helper for Upload methods
+   * @return True if the bitmap has the same pixel format and its size fits within the atlas at the specified offset
+   */
+  bool Compatible( Pixel::Format pixelFormat,
+                   SizeType x,
+                   SizeType y );
+  /**
+   * Helper to create the Atlas resource
+   */
+  void AllocateAtlas();
+
+  /**
+   * Helper to release the Atlas resource
+   */
+  void ReleaseAtlas();
+
+  /**
+   * Upload a bitmap with the given color to clear the background.
+   */
+  void ClearBackground( const Vector4& color  );
+
+  /**
+   * Clear all the current tiles and resources of the atlas
+   */
+  void ClearCache();
+
+  /**
+   * Load the bitmap data from the url
+   */
+  Integration::BitmapPtr LoadBitmap( const std::string& url );
+
+private:
+
+  /**
+   * Record of the url resource in the Atlas.
+   */
+  struct Tile
+  {
+    Tile( SizeType xOffset, SizeType yOffset, const std::string& url )
+    : xOffset( xOffset ), yOffset( yOffset ), url(url)
+    {}
+
+    ~Tile(){};
+
+    SizeType xOffset;   ///< Offset in the x direction within the atlas
+    SizeType yOffset;   ///< Offset in the y direction within the atlas
+    std::string url;    ///< The URL of the resource image file to use
+
+  private:
+    Tile(const Tile& rhs); ///< not defined
+    Tile& operator=(const Tile& rhs); ///< not defined
+  };
+
+private:
+
+  ResourceClient&          mResourceClient;
+  ImageFactory&            mImageFactory;
+  Vector4                  mClearColor;       ///< The background clear color
+  Vector<Tile*>            mTiles;            ///< The url resources, which would recover automatically when regaining context
+  Pixel::Format            mPixelFormat;      ///< The pixel format (rgba 32 bit by default)
+  bool                     mClear:1;          ///< Clear the backgound or not
+  bool                     mRecoverContext:1; ///< Re-upload the url resources or not when regaining context
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::Atlas& GetImplementation(Dali::Atlas& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::Atlas&>(handle);
+}
+
+inline const Internal::Atlas& GetImplementation(const Dali::Atlas& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Atlas handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::Atlas&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ATLAS_H__
diff --git a/dali/internal/event/images/bitmap-compressed.cpp b/dali/internal/event/images/bitmap-compressed.cpp
new file mode 100644 (file)
index 0000000..65a01bc
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/bitmap-compressed.h>
+
+// EXTERNAL INCLUDES
+#include <cstdlib>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/core-impl.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+using namespace Dali::Pixel;
+
+BitmapCompressed::BitmapCompressed( const ResourcePolicy::Discardable discardable )
+: Bitmap( discardable ),
+  mBufferSize(0)
+{
+}
+
+BitmapCompressed::~BitmapCompressed()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+}
+
+void BitmapCompressed::Initialize( Pixel::Format pixelFormat,
+                          const unsigned int width,
+                          const unsigned int height,
+                          const size_t bufferSize )
+{
+  Dali::Integration::Bitmap::Initialize( pixelFormat, width, height );
+  mBufferSize  = bufferSize;
+  mAlphaChannelUsed = false; // Default to not using Alpha as we cannot scan the pixels to look for transparent pixels. A follow-up work-item and patch will add an "assume alpha present" flag to ImageAttributes.
+}
+
+Dali::Integration::PixelBuffer* BitmapCompressed::ReserveBufferOfSize( Pixel::Format pixelFormat,
+                                    const unsigned int  width,
+                                    const unsigned int  height,
+                                    const size_t        bufferSize )
+{
+  // Sanity check that a not-outrageous amount of data is being passed in (indicating a client error):
+  DALI_ASSERT_DEBUG(bufferSize < (1U << 27U) && "That is far too much compressed data."); // 128MB of compressed data == unreasonable.
+  // delete existing buffer
+  DeletePixelBuffer();
+
+  Initialize(pixelFormat, width, height, bufferSize);
+
+  mData = reinterpret_cast< Dali::Integration::PixelBuffer* >( malloc( bufferSize ) );
+
+  return mData;
+}
+
+} //namespace Integration
+
+} //namespace Dali
diff --git a/dali/internal/event/images/bitmap-compressed.h b/dali/internal/event/images/bitmap-compressed.h
new file mode 100644 (file)
index 0000000..85241e9
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef __DALI_INTERNAL_COMPRESSED_BITMAP_H__
+#define __DALI_INTERNAL_COMPRESSED_BITMAP_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+class BitmapCompressed;
+typedef IntrusivePtr<BitmapCompressed>        BitmapCompressedPtr;
+
+/**
+ * BitmapCompressed class.
+ * A container for image data that remains in compresssed form as an opaque blob
+ * in memory rather than being decompressed at load time.
+ * Used for formats that are supported as GLES texture data directly.
+ * \sa{Bitmap BitmapPackedPixel BitmapExternal}
+ */
+class BitmapCompressed : public Dali::Integration::Bitmap, Dali::Integration::Bitmap::CompressedProfile
+{
+public:
+  /**
+   * Constructor
+   * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
+   */
+  BitmapCompressed( ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_RETAIN );
+
+  virtual const Bitmap::CompressedProfile* GetCompressedProfile() const { return this; }
+  virtual Bitmap::CompressedProfile* GetCompressedProfile() { return this; }
+
+private:
+  /**
+   * Initializes internal class members
+   * @param[in] pixelFormat   pixel format
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferSize    Buffer cpacity in pixels
+   */
+  void Initialize(Pixel::Format pixelFormat,
+                           unsigned int width,
+                           unsigned int height,
+                           const std::size_t bufferSize);
+public:
+  /**
+   * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer
+   * is deleted.
+   * Dali has ownership of the buffer, and contents are opaque and immutable.
+   * Bitmap stores given size information about the image which the client is assumed
+   * to have retrieved from out-of-band image metadata.
+   * @param[in] pixelFormat   pixel format
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferSize    Buffer size in bytes
+   * @return pixel buffer pointer
+   */
+  virtual Dali::Integration::PixelBuffer* ReserveBufferOfSize( Pixel::Format pixelFormat,
+                                     const unsigned width,
+                                     const unsigned height,
+                                     const std::size_t numBytes );
+
+  /**
+   * Get the pixel buffer size in bytes
+   * @return The buffer size in bytes.
+   */
+  virtual std::size_t GetBufferSize() const
+  {
+    return mBufferSize;
+  }
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~BitmapCompressed();
+
+private:
+
+  std::size_t mBufferSize;
+
+  BitmapCompressed(const BitmapCompressed& other);  ///< defined private to prevent use
+  BitmapCompressed& operator = (const BitmapCompressed& other); ///< defined private to prevent use
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_COMPRESSED_BITMAP_H__
diff --git a/dali/internal/event/images/bitmap-external.cpp b/dali/internal/event/images/bitmap-external.cpp
new file mode 100644 (file)
index 0000000..d4a81dd
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/bitmap-external.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/core-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// use power of two bufferWidth and bufferHeight for better performance
+BitmapExternal::BitmapExternal(Dali::Integration::PixelBuffer* pixBuf,
+               unsigned int width,
+               unsigned int height,
+               Pixel::Format pixelFormat,
+               unsigned int bufferWidth,
+               unsigned int bufferHeight)
+: BitmapPackedPixel(ResourcePolicy::NOT_OWNED, NULL/*pixBuf is externally owned*/),
+  mExternalData(pixBuf)
+{
+  mImageWidth   = width;
+  mImageHeight  = height;
+  mBufferWidth  = (bufferWidth  != 0) ? bufferWidth  : width;
+  mBufferHeight = (bufferHeight != 0) ? bufferHeight : height;
+  mPixelFormat  = pixelFormat;
+
+  mBytesPerPixel = Pixel::GetBytesPerPixel(pixelFormat);
+  mHasAlphaChannel = Pixel::HasAlpha(pixelFormat);
+  mAlphaChannelUsed = mHasAlphaChannel;
+
+  DALI_ASSERT_DEBUG(mBufferWidth >= mImageWidth && mBufferHeight >= mImageHeight);
+}
+
+BitmapExternal::~BitmapExternal()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+}
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/event/images/bitmap-external.h b/dali/internal/event/images/bitmap-external.h
new file mode 100644 (file)
index 0000000..b822934
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_INTERNAL_BITMAP_EXTERNAL_H__
+#define __DALI_INTERNAL_BITMAP_EXTERNAL_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/bitmap-packed-pixel.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Bitmap class.
+ * A container for external image data
+ */
+class BitmapExternal : public BitmapPackedPixel
+{
+public:
+  /**
+   * Constructor
+   */
+
+  /**
+   * Creates new BitmapExternal instance with pixel buffer pointer and details.
+   * Application has ownership of the buffer, its contents can be modified.
+   * Bitmap stores given size information about the image.
+   * @pre bufferWidth, bufferHeight have to be power of two
+   * @param[in] pixBuf        pointer to external pixel buffer
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] pixelformat   pixel format
+   * @param[in] bufferWidth   Buffer width in pixels
+   * @param[in] bufferHeight  Buffer height in pixels
+   */
+  BitmapExternal(Dali::Integration::PixelBuffer* pixBuf,
+                 unsigned int width,
+                 unsigned int height,
+                 Pixel::Format pixelformat,
+                 unsigned int bufferWidth  = 0,
+                 unsigned int bufferHeight = 0);
+
+  /**
+   * This does nothing, data is owned by external application.
+   */
+  virtual Dali::Integration::PixelBuffer* ReserveBuffer(Pixel::Format pixelFormat,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int bufferWidth = 0,
+                                     unsigned int bufferHeight = 0)
+  {
+    return NULL;
+  }
+
+  /**
+   * Get the pixel buffer
+   * @return The buffer. You can modify its contents.
+   */
+  virtual Dali::Integration::PixelBuffer* GetBuffer()
+  {
+    return mExternalData;
+  }
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~BitmapExternal();
+
+private:
+
+  Dali::Integration::PixelBuffer* mExternalData; ///< Externally owned pixel data
+
+private:
+  BitmapExternal();  ///< defined private to prevent use
+  BitmapExternal(const BitmapExternal& other);  ///< defined private to prevent use
+  BitmapExternal& operator = (const BitmapExternal& other); ///< defined private to prevent use
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_BITMAP_EXTERNAL_H__
diff --git a/dali/internal/event/images/bitmap-packed-pixel.cpp b/dali/internal/event/images/bitmap-packed-pixel.cpp
new file mode 100644 (file)
index 0000000..232877f
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/bitmap-packed-pixel.h>
+
+// EXTERNAL INCLUDES
+#include <cstdlib>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/common/core-impl.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+using namespace Dali::Pixel;
+
+
+BitmapPackedPixel::BitmapPackedPixel( ResourcePolicy::Discardable discardable, Dali::Integration::PixelBuffer* pixBuf )
+: Bitmap( discardable, pixBuf ),
+  mBufferWidth(0),
+  mBufferHeight(0),
+  mBytesPerPixel(0)
+{
+}
+
+// use power of two bufferWidth and bufferHeight for better performance
+Dali::Integration::PixelBuffer* BitmapPackedPixel::ReserveBuffer(Pixel::Format pixelFormat,
+                                    unsigned int  width,
+                                    unsigned int  height,
+                                    unsigned int  bufferWidth,
+                                    unsigned int  bufferHeight)
+{
+  // delete existing buffer
+  DeletePixelBuffer();
+
+  Initialize(pixelFormat, width, height, bufferWidth, bufferHeight);
+
+  //allocate buffer
+  unsigned int bufSize = mBufferWidth * mBufferHeight * mBytesPerPixel;
+
+  mData = reinterpret_cast< Dali::Integration::PixelBuffer* >( malloc( bufSize) );
+
+  return mData;
+}
+
+void BitmapPackedPixel::AssignBuffer(Pixel::Format pixelFormat,
+                                     Dali::Integration::PixelBuffer* buffer,
+                                     std::size_t bufferSize,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int bufferWidth,
+                                     unsigned int bufferHeight)
+{
+  DALI_ASSERT_DEBUG( buffer );
+
+  // delete existing buffer
+  DeletePixelBuffer();
+
+  Initialize( pixelFormat, width, height, bufferWidth, bufferHeight );
+
+   // make sure the buffer size matches what is being passed in
+  DALI_ASSERT_DEBUG( bufferSize ==  (mBufferWidth * mBufferHeight * mBytesPerPixel))
+
+  mData = buffer;
+}
+
+void BitmapPackedPixel::TestForTransparency()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  mAlphaChannelUsed = false;
+
+  if(HasAlphaChannel())
+  {
+    unsigned char* pixelBuffer=GetBuffer();
+    if(pixelBuffer != NULL)
+    {
+      unsigned char* row = pixelBuffer;
+
+      int byte; int bits;
+      Pixel::GetAlphaOffsetAndMask(mPixelFormat, byte, bits);
+
+      int stride       = mBufferWidth * mBytesPerPixel;
+      int pixelsPerRow = mImageWidth;
+
+      for(size_t j=0; j<mImageHeight; j++)
+      {
+        unsigned char* pixels = row;
+        for(int i=0; i<pixelsPerRow; i++)
+        {
+          if((pixels[byte] & bits) != bits)
+          {
+            mAlphaChannelUsed = true;
+            j=mImageHeight; // break out of outer loop
+            break;
+          }
+          pixels+=mBytesPerPixel;
+        }
+        row += stride;
+      }
+    }
+  }
+}
+
+BitmapPackedPixel::~BitmapPackedPixel()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+}
+
+void BitmapPackedPixel::Initialize( Pixel::Format pixelFormat,
+                          unsigned int width,
+                          unsigned int height,
+                          unsigned int bufferWidth,
+                          unsigned int bufferHeight)
+{
+  Dali::Integration::Bitmap::Initialize(pixelFormat, width, height);
+  mBufferWidth  = (bufferWidth  != 0) ? bufferWidth  : width;
+  mBufferHeight = (bufferHeight != 0) ? bufferHeight : height;
+  mBytesPerPixel = Pixel::GetBytesPerPixel(pixelFormat);
+  DALI_ASSERT_DEBUG(mBufferWidth >= mImageWidth && mBufferHeight >= mImageHeight);
+}
+
+unsigned int BitmapPackedPixel::GetBufferStride() const
+{
+  return mBufferWidth*mBytesPerPixel;
+}
+
+
+
+} //namespace Integration
+
+} //namespace Dali
diff --git a/dali/internal/event/images/bitmap-packed-pixel.h b/dali/internal/event/images/bitmap-packed-pixel.h
new file mode 100644 (file)
index 0000000..4fc6967
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef __DALI_INTERNAL_BITMAP_H__
+#define __DALI_INTERNAL_BITMAP_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+class BitmapPackedPixel;
+typedef IntrusivePtr<BitmapPackedPixel>        BitmapPackedPixelPtr;
+
+/**
+ * BitmapPackedPixel class.
+ * A container for image data that is packed into individual struct-like
+ * pixels in an addressable 2D array, with each pixel occupying a whole
+ * number of bytes.
+ * This is a vanilla Bitmap class, typically used to hold data decompressed
+ * from PNG and JPEG file formats for example.
+ *
+ * \sa{Bitmap BitmapCompressed BitmapExternal}
+ */
+class BitmapPackedPixel : public Dali::Integration::Bitmap, Dali::Integration::Bitmap::PackedPixelsProfile
+{
+public:
+  /**
+   * Constructor
+   * @param[in] discardable Flag to tell the bitmap if it can delete the buffer with the pixel data.
+   */
+  BitmapPackedPixel( ResourcePolicy::Discardable discardable = ResourcePolicy::OWNED_RETAIN, Dali::Integration::PixelBuffer* pixBuf = 0 );
+
+public:
+  virtual const Bitmap::PackedPixelsProfile* GetPackedPixelsProfile() const { return this; }
+  virtual Bitmap::PackedPixelsProfile* GetPackedPixelsProfile() { return this; }
+
+  /**
+   * (Re-)Allocate pixel buffer for the Bitmap. Any previously allocated pixel buffer is deleted.
+   * Dali has ownership of the buffer, but its contents can be modified.
+   * Bitmap stores given size information about the image.
+   * @pre bufferWidth, bufferHeight have to be power of two
+   * @param[in] pixelFormat   pixel format
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferWidth   Buffer width (stride) in pixels
+   * @param[in] bufferHeight  Buffer height in pixels
+   * @return pixel buffer pointer
+   */
+  virtual Dali::Integration::PixelBuffer* ReserveBuffer(Pixel::Format pixelFormat,
+                                     unsigned int width,
+                                     unsigned int height,
+                                     unsigned int bufferWidth = 0,
+                                     unsigned int bufferHeight = 0);
+
+  /**
+   * Assign a pixel buffer. Any previously allocated pixel buffer is deleted.
+   * Dali has ownership of the buffer, but its contents can be modified.
+   * Bitmap stores given size information about the image.
+   * @pre bufferWidth, bufferHeight have to be power of two
+   * @param[in] pixelFormat   pixel format
+   * @param[in] buffer        the pixel buffer
+   * @param[in] bufferSize    size of the pixel buffer
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferWidth   Buffer width (stride) in pixels
+   * @param[in] bufferHeight  Buffer height in pixels
+   */
+  virtual void AssignBuffer(Pixel::Format pixelFormat,
+                            Dali::Integration::PixelBuffer* buffer,
+                            std::size_t bufferSize,
+                            unsigned int width,
+                            unsigned int height,
+                            unsigned int bufferWidth = 0,
+                            unsigned int bufferHeight = 0);
+
+  /**
+   * Get the width of the buffer (stride)
+   * @return The width of the buffer in pixels
+   */
+  virtual unsigned GetBufferWidth() const
+  {
+    return mBufferWidth;
+  }
+
+  /**
+   * Get the height of the buffer
+   * @return The height of the buffer in pixels
+   */
+  virtual unsigned GetBufferHeight() const
+  {
+    return mBufferHeight;
+  }
+
+  /**
+   * Get the pixel buffer size in bytes
+   * @return The buffer size in bytes.
+   */
+  // unsigned int GetBufferSize() const
+  virtual size_t GetBufferSize() const
+  {
+    return mBufferWidth*mBytesPerPixel*mBufferHeight;
+  }
+
+  /**
+   * Get the pixel buffer stride.
+   * @return The buffer stride (in bytes).
+   */
+  virtual unsigned int GetBufferStride() const;
+  //{
+  //  return mBufferWidth*mBytesPerPixel;
+  //}
+
+  /**
+   * Get the pixel format
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const
+  {
+    return mPixelFormat;
+  }
+
+  /**
+   * Check the bitmap data and test whether it has any transparent pixels.
+   * This property can then be tested for with IsFullyOpaque().
+   */
+  virtual void TestForTransparency();
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~BitmapPackedPixel();
+
+protected:
+
+  unsigned int  mBufferWidth;         ///< Buffer width (stride) in pixels
+  unsigned int  mBufferHeight;        ///< Buffer height in pixels
+  unsigned int  mBytesPerPixel;       ///< Bytes per pixel
+
+private:
+
+  /**
+   * Initializes internal class members
+   * @param[in] pixelFormat   pixel format
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferWidth   Buffer width (stride) in pixels
+   * @param[in] bufferHeight  Buffer height in pixels
+   */
+  void Initialize(Pixel::Format pixelFormat,
+                           unsigned int width,
+                           unsigned int height,
+                           unsigned int bufferWidth,
+                           unsigned int bufferHeight);
+
+
+  BitmapPackedPixel(const BitmapPackedPixel& other);  ///< defined private to prevent use
+  BitmapPackedPixel& operator = (const BitmapPackedPixel& other); ///< defined private to prevent use
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+} // namespace Integration
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_BITMAP_H__
diff --git a/dali/internal/event/images/buffer-image-impl.cpp b/dali/internal/event/images/buffer-image-impl.cpp
new file mode 100644 (file)
index 0000000..e87f0a1
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/buffer-image-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/internal/event/images/bitmap-external.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/event/images/image-factory.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::BufferImage ), typeid( Dali::Image ), NULL );
+} // unnamed namespace
+
+BufferImagePtr BufferImage::New( unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol )
+{
+  BufferImagePtr internal = new BufferImage( width, height, pixelformat, releasePol );
+  internal->Initialize();
+  return internal;
+}
+
+BufferImagePtr BufferImage::New( PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol )
+{
+  BufferImagePtr internal = new BufferImage( pixBuf, width, height, pixelformat, stride, releasePol );
+  internal->Initialize();
+  return internal;
+}
+
+BufferImage::BufferImage(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol)
+: Image(releasePol),
+  mIsDataExternal(false)
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  mResourceClient = &tls.GetResourceClient();
+  mWidth  = width;
+  mHeight = height;
+
+  const ImageTicketPtr& t = mResourceClient->AllocateBitmapImage(width, height, width, height, pixelformat);
+  mTicket = t.Get();
+
+  mTicket->AddObserver(*this);
+}
+
+BufferImage::BufferImage(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol)
+: Image(releasePol),
+  mIsDataExternal(true)
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  mResourceClient = &tls.GetResourceClient();
+  mWidth  = width;
+  mHeight = height;
+  Integration::Bitmap* bitmap = new BitmapExternal(pixBuf, width, height, pixelformat, stride);
+  const ImageTicketPtr& t = mResourceClient->AddBitmapImage(bitmap);
+  mTicket = t.Get();
+
+  mTicket->AddObserver(*this);
+}
+
+BufferImage::~BufferImage()
+{
+}
+
+void BufferImage::Update( RectArea& updateArea )
+{
+  if (mTicket)
+  {
+    // TODO:
+    // If updateArea is empty or same as image size, then pass on.
+    // If updateArea is larger than image size, throw exception
+    // Otherwise, copy updateArea window of pixelBuffer into newly
+    // allocated buffer and pass that to resource client. (it will
+    // tramp through to BitmapTexture eventually!)
+    mResourceClient->UpdateBitmapArea( mTicket, updateArea );
+  }
+  else if (mIsDataExternal && mBitmapCached)
+  {
+    // previously freed up resource memory, dali was informed about external BufferImage put back on screen
+    Integration::Bitmap* bitmap = mBitmapCached.Get();
+    mTicket.Reset((mResourceClient->AddBitmapImage(bitmap)).Get());
+
+    mTicket->AddObserver(*this);
+  }
+}
+
+bool BufferImage::IsDataExternal() const
+{
+  return mIsDataExternal;
+}
+
+PixelBuffer* BufferImage::GetBuffer()
+{
+  PixelBuffer* buffer = NULL;
+
+  Integration::Bitmap* const bitmap = GetBitmap();
+
+  if(bitmap)
+  {
+    buffer = bitmap->GetBuffer();
+  }
+  return buffer;
+}
+
+unsigned int BufferImage::GetBufferSize() const
+{
+  unsigned int bufferSize = 0;
+
+  Integration::Bitmap* const bitmap = GetBitmap();
+
+  if(bitmap)
+  {
+    bufferSize = bitmap->GetBufferSize();
+  }
+  return bufferSize;
+}
+
+unsigned int BufferImage::GetBufferStride() const
+{
+  unsigned int bufferStride = 0;
+
+  Integration::Bitmap* const bitmap = GetBitmap();
+
+  if(bitmap)
+  {
+    Integration::Bitmap::PackedPixelsProfile* packedBitmap = bitmap->GetPackedPixelsProfile();
+    DALI_ASSERT_DEBUG(packedBitmap);
+    bufferStride = packedBitmap->GetBufferStride();
+  }
+
+  return bufferStride;
+}
+
+Pixel::Format BufferImage::GetPixelFormat() const
+{
+  Pixel::Format format( Pixel::RGBA8888 );
+
+  Integration::Bitmap* const bitmap = GetBitmap();
+
+  if( bitmap )
+  {
+    format = bitmap->GetPixelFormat();
+  }
+
+  return format;
+}
+
+void BufferImage::Connect()
+{
+  ++mConnectionCount;
+
+  // application owns bitmap buffer, don't do anything. Update() has to be called manually.
+  if (mIsDataExternal)
+  {
+    return;
+  }
+
+  if (mConnectionCount == 1)
+  {
+    if (!mTicket && mBitmapCached)
+    {
+      const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmapCached.Get());
+      mTicket = t.Get();
+      mTicket->AddObserver(*this);
+    }
+  }
+}
+
+void BufferImage::Disconnect()
+{
+  if (!mTicket)
+  {
+    return;
+  }
+
+  --mConnectionCount;
+
+  if (mConnectionCount == 0 && mReleasePolicy == Dali::Image::UNUSED)
+  {
+    mBitmapCached = mResourceClient->GetBitmap(mTicket);
+    // release image memory when it's not visible anymore (decrease ref. count of texture)
+    mTicket->RemoveObserver(*this);
+    mTicket.Reset();
+  }
+}
+
+Integration::Bitmap * BufferImage::GetBitmap() const
+{
+  Integration::Bitmap* bitmap = NULL;
+
+  if (mTicket)
+  {
+    bitmap = mResourceClient->GetBitmap(mTicket);
+  }
+  else
+  {
+    // off screen and freeing memory was requested
+    bitmap = mBitmapCached.Get();
+  }
+
+  DALI_ASSERT_DEBUG(bitmap);
+
+  return bitmap;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/buffer-image-impl.h b/dali/internal/event/images/buffer-image-impl.h
new file mode 100644 (file)
index 0000000..618846f
--- /dev/null
@@ -0,0 +1,216 @@
+#ifndef __DALI_INTERNAL_BUFFER_IMAGE_H__
+#define __DALI_INTERNAL_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h> // For Integration::BitmapPtr
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/buffer-image.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class BufferImage;
+typedef IntrusivePtr<BufferImage> BufferImagePtr;
+
+class ResourceClient;
+class ResourceManager;
+
+/**
+ * BufferImage represents an image resource that can be added to actors etc.
+ * Its pixel buffer data is provided by the application developer.
+ * Pixel buffer memory allocation can be handled by dali or application.
+ */
+class BufferImage : public Image
+{
+public:
+  /**
+   * Create a new BufferImage.
+   * Also a pixel buffer for image data is allocated.
+   * Dali has ownership of the buffer.
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] width       image width in pixels
+   * @param [in] height      image height in pixels
+   * @param [in] pixelformat the pixel format (rgba 32 bit by default)
+   * @param [in] releasePol  optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  static BufferImagePtr New( unsigned int width,
+                             unsigned int height,
+                             Pixel::Format pixelformat,
+                             ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * Create a new BufferImage, which uses external data source.
+   * Pixel buffer has to be allocated by application.
+   * Application holds ownership of the buffer.
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @note  in case releasePol is "OffStage", application has to call Update() whenever image is re-added to the stage
+   * @param [in] pixBuf      pixel buffer. has to be allocated by application.
+   * @param [in] width       image width in pixels
+   * @param [in] height      image height in pixels
+   * @param [in] pixelformat the pixel format (rgba 32 bit by default)
+   * @param [in] stride      the internal stride of the pixelbuffer in pixels
+   * @param [in] releasePol  optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  static BufferImagePtr New( PixelBuffer* pixBuf,
+                             unsigned int width,
+                             unsigned int height,
+                             Pixel::Format pixelformat,
+                             unsigned int stride,
+                             ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * Create a new BufferImage.
+   * Also a pixel buffer for image data is allocated.
+   * Dali has ownership of the buffer.
+   * For better performance use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] width image width in pixels
+   * @param [in] height image height in pixels
+   * @param [in] pixelformat the pixel format (rgba 32 bit by default)
+   * @param [in] releasePol optionally release memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  BufferImage(unsigned int width,
+              unsigned int height,
+              Pixel::Format pixelformat,
+              ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT);
+
+  /**
+   * Create a new BufferImage, which uses external data source.
+   * Pixel buffer has to be allocated by application.
+   * Application holds ownership of the buffer.
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @note  in case releasePol is "OffStage", application has to call Update() whenever image is re-added to the stage
+   * @param [in] pixBuf      pixel buffer. has to be allocated by application.
+   * @param [in] width       image width in pixels
+   * @param [in] height      image height in pixels
+   * @param [in] pixelformat the pixel format (rgba 32 bit by default)
+   * @param [in] stride      the internal stride of the pixelbuffer in pixels
+   * @param [in] releasePol  optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  BufferImage(PixelBuffer* pixBuf,
+              unsigned int width,
+              unsigned int height,
+              Pixel::Format pixelformat,
+              unsigned int stride,
+              ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT);
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~BufferImage();
+
+public:
+  /**
+   * Notify Dali that the contents of the buffer have changed.
+   * @param [in] updateArea area that has changed in buffer. An empty rect means the whole buffer has changed.
+   */
+  void Update (RectArea& updateArea);
+
+  /**
+   * @copydoc Dali::BufferImage::IsDataExternal
+   */
+  bool IsDataExternal() const;
+
+  /**
+   * Returns the pixel buffer of the Image.
+   * The application developer can write to the buffer.
+   * Upload the modified contents with Update().
+   * @return the pixel buffer
+   */
+  PixelBuffer* GetBuffer();
+
+  /**
+   * Returns buffer size in bytes.
+   * @return the buffer size in bytes
+   */
+  unsigned int GetBufferSize() const;
+
+  /**
+   * Returns buffer stride (in bytes).
+   * @return the buffer stride
+   */
+  unsigned int GetBufferStride() const;
+
+  /**
+   * Get the pixel format
+   * @return The pixel format
+   */
+  Pixel::Format GetPixelFormat() const;
+
+protected: // From Resource
+  /**
+   * @copydoc Dali::Internal::Image::Connect
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Image::Disconnect
+   */
+  virtual void Disconnect();
+
+  /**
+   * Get the bitmap from local cache or ticket.
+   **/
+  Integration::Bitmap * GetBitmap() const;
+
+private:
+  bool mIsDataExternal; ///< whether application holds ownership of pixel buffer or not
+
+  ResourceClient*            mResourceClient;
+
+protected:
+  Integration::BitmapPtr     mBitmapCached;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::BufferImage& GetImplementation(Dali::BufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "BufferImage handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::BufferImage&>(handle);
+}
+
+inline const Internal::BufferImage& GetImplementation(const Dali::BufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "BufferImage handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::BufferImage&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_BUFFER_IMAGE_H__
diff --git a/dali/internal/event/images/context-recovery-interface.h b/dali/internal/event/images/context-recovery-interface.h
new file mode 100644 (file)
index 0000000..4ba86bc
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+#define __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Abstract interface for Context Recovery
+ *
+ */
+class ContextRecoveryInterface
+{
+
+public:
+
+  /**
+   * Restore the object after context loss
+   */
+  virtual void RecoverFromContextLoss() = 0;
+
+protected:
+
+  /**
+   * Constructor
+   */
+  ContextRecoveryInterface()
+  {
+  }
+  /**
+   * Destructor.
+   */
+  virtual ~ContextRecoveryInterface()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  ContextRecoveryInterface( const ContextRecoveryInterface& );
+
+  // Undefined assignment operator.
+  ContextRecoveryInterface& operator=( const ContextRecoveryInterface& );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONTEXT_RECOVERY_INTERFACE_H__
diff --git a/dali/internal/event/images/encoded-buffer-image-impl.cpp b/dali/internal/event/images/encoded-buffer-image-impl.cpp
new file mode 100644 (file)
index 0000000..01f379f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/encoded-buffer-image-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for memcpy
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/integration-api/platform-abstraction.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::EncodedBufferImage ), typeid( Dali::Image ), NULL );
+} // unnamed namespace
+
+EncodedBufferImagePtr EncodedBufferImage::New( const uint8_t * const encodedImage,
+                                               std::size_t encodedImageByteCount,
+                                               ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode,
+                                               bool orientationCorrection,
+                                               ReleasePolicy releasePol )
+{
+  DALI_ASSERT_DEBUG( encodedImage && "Null image pointer passed-in for decoding from memory." );
+  DALI_ASSERT_DEBUG( encodedImageByteCount > 0U && "Zero size passed for image resource in memory buffer." );
+  DALI_ASSERT_ALWAYS( encodedImage && (encodedImageByteCount != 0) );
+  // SEGV early before we allocate anything if the caller passed in an invalid
+  // input buffer by reading both ends of it:
+  DALI_ASSERT_ALWAYS( static_cast<int>( encodedImage[0] + encodedImage[encodedImageByteCount-1] ) != -1 );
+
+  EncodedBufferImagePtr image( new EncodedBufferImage( releasePol ) );
+  image->Initialize(); // Second stage initialization
+
+  // Replicate the functionality of ImageFactory::load() without the filesystem caching:
+  Dali::Integration::BitmapResourceType resourceType( size, fittingMode, samplingMode, orientationCorrection );
+  RequestBufferPtr buffer( new RequestBuffer );
+  buffer->GetVector().Resize( encodedImageByteCount );
+  // Resize() won't throw on failure, so avoid a SEGV if the allocation failed:
+  DALI_ASSERT_ALWAYS( buffer->GetVector().Size() >= encodedImageByteCount );
+
+  memcpy( &(buffer->GetVector()[0]), encodedImage, encodedImageByteCount );
+
+  // Get image size from buffer
+  Dali::Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+  const ImageDimensions expectedSize = platformAbstraction.GetClosestImageSize( buffer, size, fittingMode, samplingMode, orientationCorrection );
+  image->mWidth = (unsigned int) expectedSize.GetWidth();
+  image->mHeight = (unsigned int) expectedSize.GetHeight();
+
+  // Load the image synchronously
+  Integration::BitmapPtr bitmap = platformAbstraction.DecodeBuffer( resourceType, &(buffer->GetVector()[0]), encodedImageByteCount );
+
+  if( bitmap )
+  {
+    ResourceClient &resourceClient = ThreadLocalStorage::Get().GetResourceClient();
+    image->mTicket = resourceClient.AddBitmapImage( bitmap.Get() );
+    image->mTicket->AddObserver( *image );
+  }
+
+  return image;
+}
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/images/encoded-buffer-image-impl.h b/dali/internal/event/images/encoded-buffer-image-impl.h
new file mode 100644 (file)
index 0000000..c3b239c
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_INTERNAL_ENCODED_BUFFER_IMAGE_H__
+#define __DALI_INTERNAL_ENCODED_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/public-api/images/encoded-buffer-image.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class EncodedBufferImage;
+typedef IntrusivePtr<EncodedBufferImage> EncodedBufferImagePtr;
+
+class ResourceClient;
+class ResourceManager;
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+/**
+ * EncodedBufferImage represents an image resource that can be added to actors etc.
+ *
+ * A memory buffer of encoded image data is provided by the application and
+ * decoded asynchronously on a background thread to fill the image's
+ * pixel data.
+ */
+class EncodedBufferImage : public Image
+{
+private:
+  /**
+   * Construct using the supplied load policy.
+   */
+  EncodedBufferImage( ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT ) : Image( releasePol ) {}
+
+public:
+  /**
+   * Create an initialised image object from an encoded image buffer in memory.
+   * @param [in] encodedImage The encoded bytes of an image, in a supported
+   * image format such as PNG, JPEG, GIF, BMP, KTX, ICO, and WBMP, organised
+   * exactly as it would be as a file in the filesystem.
+   * The caller retains ownership of this buffer and is free to modify or
+   * discard it as soon as the function returns.
+   * @param [in] encodedImageByteCount The size in bytes of the buffer pointed to
+   * by encodedImage.
+   * @param [in] attributes Requested parameters for loading (size, scaling etc.).
+   * @param [in] releasePol The ReleasePolicy to apply to image. Since it cannot
+   * be recreated by dali, the default of Never will usually make sense.
+   * @return A pointer to a newly allocated object, or null on error.
+   */
+  static EncodedBufferImagePtr New(const uint8_t * const encodedImage,
+                                   const std::size_t encodedImageByteCount,
+                                   ImageDimensions size = ImageDimensions(0, 0),
+                                   FittingMode::Type scalingMode = FittingMode::SHRINK_TO_FIT,
+                                   SamplingMode::Type samplingMode = SamplingMode::BOX,
+                                   bool orientationCorrection = true,
+                                   const ReleasePolicy releasePol=Dali::Image::NEVER);
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::EncodedBufferImage& GetImplementation(Dali::EncodedBufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "EncodedBufferImage handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::EncodedBufferImage&>(handle);
+}
+
+inline const Internal::EncodedBufferImage& GetImplementation(const Dali::EncodedBufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "EncodedBufferImage handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::EncodedBufferImage&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_ENCODED_BUFFER_IMAGE_H__
diff --git a/dali/internal/event/images/frame-buffer-image-impl.cpp b/dali/internal/event/images/frame-buffer-image-impl.cpp
new file mode 100644 (file)
index 0000000..3090c92
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::FrameBufferImage ), typeid( Dali::Image ), NULL );
+} // unnamed namespace
+
+FrameBufferImage::~FrameBufferImage()
+{
+}
+
+FrameBufferImagePtr  FrameBufferImage::New(unsigned int width, 
+                                           unsigned int height, 
+                                           Pixel::Format pixelFormat, 
+                                           ReleasePolicy releasePolicy,
+                                           RenderBuffer::Format bufferformat)
+{
+  FrameBufferImagePtr image = new FrameBufferImage(width, height, pixelFormat, releasePolicy, bufferformat);
+  image->Initialize();
+  return image;
+}
+
+FrameBufferImagePtr  FrameBufferImage::New( NativeImageInterface& nativeImage )
+{
+  FrameBufferImagePtr image = new FrameBufferImage(nativeImage);
+  image->Initialize();
+  return image;
+}
+
+FrameBufferImagePtr  FrameBufferImage::New( NativeImageInterface& nativeImage, ReleasePolicy releasePolicy )
+{
+  FrameBufferImagePtr image = new FrameBufferImage(nativeImage, releasePolicy);
+  image->Initialize();
+  return image;
+}
+
+FrameBufferImage::FrameBufferImage(unsigned int width, unsigned int height, Pixel::Format pixelFormat, ReleasePolicy releasePolicy, RenderBuffer::Format bufferformat)
+: Image(releasePolicy),
+  mPixelFormat(pixelFormat),
+  mBufferFormat(bufferformat)
+{
+  mWidth  = width;
+  mHeight = height;
+}
+
+FrameBufferImage::FrameBufferImage( NativeImageInterface& nativeImage )
+: Image(),
+  mNativeImage(&nativeImage)
+{
+  mWidth = nativeImage.GetWidth();
+  mHeight = nativeImage.GetHeight();
+}
+
+FrameBufferImage::FrameBufferImage( NativeImageInterface& nativeImage, ReleasePolicy releasePolicy )
+: Image(releasePolicy),
+  mNativeImage(&nativeImage)
+{
+  mWidth = nativeImage.GetWidth();
+  mHeight = nativeImage.GetHeight();
+}
+
+void FrameBufferImage::Connect()
+{
+  ++mConnectionCount;
+
+  if (mConnectionCount == 1)
+  {
+    // ticket was thrown away when related actors went offstage
+    if (!mTicket)
+    {
+      ResourceClient& resourceClient = ThreadLocalStorage::Get().GetResourceClient();
+      if (mNativeImage)
+      {
+        mTicket = resourceClient.AddFrameBufferImage(*mNativeImage);
+        mTicket->AddObserver(*this);
+      }
+      else
+      {
+        mTicket = resourceClient.AddFrameBufferImage(mWidth, mHeight, mPixelFormat, mBufferFormat);
+        mTicket->AddObserver(*this);
+      }
+    }
+  }
+}
+
+void FrameBufferImage::Disconnect()
+{
+  if(!mTicket)
+  {
+    return;
+  }
+
+  DALI_ASSERT_DEBUG(mConnectionCount > 0);
+  --mConnectionCount;
+  if (mConnectionCount == 0 && mReleasePolicy == Dali::Image::UNUSED)
+  {
+    // release image memory when it's not visible anymore (decrease ref. count of texture)
+    mTicket->RemoveObserver(*this);
+    mTicket.Reset();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/frame-buffer-image-impl.h b/dali/internal/event/images/frame-buffer-image-impl.h
new file mode 100644 (file)
index 0000000..d9a7a17
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef __DALI_INTERNAL_FRAME_BUFFER_IMAGE_H__
+#define __DALI_INTERNAL_FRAME_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class FrameBufferImage;
+typedef IntrusivePtr<FrameBufferImage> FrameBufferImagePtr;
+
+/**
+ * @copydoc Dali::FrameBufferImage
+ */
+class FrameBufferImage : public Image
+{
+public:
+  /**
+   * @copydoc Dali::FrameBufferImage::New(unsigned int, unsigned int, Pixel::Format)
+   */
+  static FrameBufferImagePtr  New(unsigned int width, unsigned int height, Pixel::Format pixelFormat, ReleasePolicy releasePolicy, RenderBuffer::Format bufferformat);
+
+  /**
+   * @copydoc Dali::FrameBufferImage::New(NativeImageInterface&)
+   */
+  static FrameBufferImagePtr  New( NativeImageInterface& nativeImage );
+
+  /**
+   * @copydoc Dali::FrameBufferImage::New(NativeImageInterface&, ReleasePolicy)
+   */
+  static FrameBufferImagePtr  New( NativeImageInterface& nativeImage, ReleasePolicy releasePolicy );
+
+  /**
+   * @copydoc Dali::FrameBufferImage::FrameBufferImage
+   */
+  FrameBufferImage(unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferformat);
+
+  /**
+   * @copydoc Dali::FrameBufferImage::FrameBufferImage
+   */
+  FrameBufferImage(unsigned int width, unsigned int height, Pixel::Format pixelFormat, ReleasePolicy releasePolicy, RenderBuffer::Format bufferformat);
+
+  /**
+   * @copydoc Dali::FrameBufferImage::FrameBufferImage
+   */
+  FrameBufferImage(NativeImageInterface& image);
+
+  /**
+   * @copydoc Dali::FrameBufferImage::FrameBufferImage
+   */
+  FrameBufferImage(NativeImageInterface& image, ReleasePolicy releasePolicy);
+
+public: // From Image
+  /**
+   * @copydoc Dali::Internal::Image::Connect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Image::Disconnect()
+   */
+  virtual void Disconnect();
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~FrameBufferImage();
+
+private:
+  // cached values for the size / pixel format we were created with. Needed to recreate us when we Connect() to stage and mTicket was reset from a previous call to Disconnect().
+  NativeImageInterfacePtr mNativeImage;
+  Pixel::Format mPixelFormat;
+  RenderBuffer::Format mBufferFormat;
+}; // class FrameBufferImage
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::FrameBufferImage& GetImplementation(Dali::FrameBufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "FrameBufferImage handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::FrameBufferImage&>(handle);
+}
+
+inline const Internal::FrameBufferImage& GetImplementation(const Dali::FrameBufferImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "FrameBufferImage handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::FrameBufferImage&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_FRAME_BUFFER_IMAGE_H__
diff --git a/dali/internal/event/images/image-connector.cpp b/dali/internal/event/images/image-connector.cpp
new file mode 100644 (file)
index 0000000..265115c
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/image-connector.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ImageConnector::ImageConnector()
+: mImage(NULL)
+{
+}
+
+ImageConnector::~ImageConnector()
+{
+}
+
+ImagePtr ImageConnector::Get() const
+{
+  return mImage;
+}
+
+void ImageConnector::Set( ImagePtr image, bool onStage )
+{
+  if ( mImage != image )
+  {
+    // Disconnect from old image
+    if ( mImage && onStage )
+    {
+      mImage->Disconnect();
+    }
+
+    mImage = image;
+
+    // Connect to new image
+    if ( mImage && onStage )
+    {
+      mImage->Connect();
+    }
+  }
+}
+
+void ImageConnector::OnStageConnect()
+{
+  if ( mImage )
+  {
+    mImage->Connect();
+  }
+}
+
+void ImageConnector::OnStageDisconnect()
+{
+  if ( mImage )
+  {
+    mImage->Disconnect();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/image-connector.h b/dali/internal/event/images/image-connector.h
new file mode 100644 (file)
index 0000000..a778ed8
--- /dev/null
@@ -0,0 +1,88 @@
+#ifndef __DALI_INTERNAL_IMAGE_CONNECTOR_H__
+#define __DALI_INTERNAL_IMAGE_CONNECTOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Wrapper class which helps managing intrusive pointer assignments and Connect / Disconnect.
+ */
+class ImageConnector
+{
+
+public:
+  /**
+   * Constructor. Takes no parameters.
+   */
+  ImageConnector();
+
+  /**
+   * Destructor.
+   */
+  ~ImageConnector();
+
+  /**
+   * Returns a smart pointer to the image
+   * @return a smart pointer to the image
+   */
+  ImagePtr Get() const;
+
+  /**
+   * Assigns image, calling Connect and Disconnect methods accordingly, taking onStage into account.
+   * @param [in] image   smart pointer to new Image
+   * @param [in] onStage whether Image is used on stage or not
+   */
+  void Set( ImagePtr image, bool onStage );
+
+  /**
+   * Manages connection reference count.
+   * Must be called from owner when connected to stage.
+   */
+  void OnStageConnect();
+
+  /**
+   * Manages connection reference count.
+   * Must be called from owner when disconnecting from stage.
+   */
+  void OnStageDisconnect();
+
+private:
+
+  ImageConnector( const ImageConnector& ptr );                     ///< copy constructor, not defined
+  const ImageConnector& operator=( const ImageConnector& ptr );  ///< copy assignment operator, not defined
+
+  ImagePtr mImage;  ///< intrusive pointer to the Image. ImageConnector owns this.
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_CONNECTOR_H__
diff --git a/dali/internal/event/images/image-factory-cache.cpp b/dali/internal/event/images/image-factory-cache.cpp
new file mode 100644 (file)
index 0000000..1dee4c9
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/image-factory-cache.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/images/image-factory.h>
+
+// EXTERNAL INCLUDES
+
+
+using namespace Dali::Internal::ImageFactoryCache;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace ImageFactoryCache
+{
+  Request::Request( RequestLifetimeObserver& observer,
+                    RequestId reqId,
+                    ResourceId resId,
+                    const std::string& path,
+                    const ImageAttributes* attr )
+  : resourceId( resId ),
+    url( path ),
+    mId( reqId ),
+    mLifetimeObserver( &observer )
+  {
+    if( attr )
+    {
+      attributes = new ImageAttributes( *attr );
+    }
+    else
+    {
+      attributes = NULL;
+    }
+  }
+
+  Request::~Request()
+  {
+    if( Stage::IsInstalled() && mLifetimeObserver )
+    {
+      mLifetimeObserver->RequestDiscarded( *this );
+    }
+    delete attributes;
+  }
+
+  RequestId Request::GetId() const
+  {
+    return mId;
+  }
+
+  void Request::StopLifetimeObservation()
+  {
+    mLifetimeObserver = NULL;
+  }
+
+} // namespace ImageFactoryCache
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/image-factory-cache.h b/dali/internal/event/images/image-factory-cache.h
new file mode 100644 (file)
index 0000000..fea0406
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __DALI_INTERNAL_IMAGE_FACTORY_CACHE_H__
+#define __DALI_INTERNAL_IMAGE_FACTORY_CACHE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/common/image-attributes.h>
+
+// EXTERNAL INCLUDES
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace ImageFactoryCache
+{
+
+/**
+ * Request contains information about requests made when loading image resources.
+ */
+struct Request;
+
+/**
+ * @brief Unique ID for image resource requests.
+ *
+ * Images are loaded from a string locator (typically a file path) using a set
+ * of ImageAttributes. Each unique pair of string and attributes is mapped to a
+ * unique RequestId value. This ensures multiple Image objects loading the same
+ * image file with the same attributes only generate one resource request and
+ * Core only issues one IO operation to Adaptor to do the load.
+ *
+ * @sa Dali::Integration::ResourceId
+ */
+typedef unsigned int RequestId;
+
+typedef std::multimap<size_t, RequestId>           RequestPathHashMap;
+typedef std::pair<size_t, RequestId>               RequestPathHashPair;
+typedef std::map<RequestId, Request*>  RequestIdMap;
+typedef std::pair<RequestId, Request*> RequestIdPair;
+
+typedef IntrusivePtr<Request> RequestPtr;
+
+/**
+ * The RequestLifetimeObserver observes the lifetime of image requests.
+ */
+class RequestLifetimeObserver
+{
+public:
+
+  /**
+   * Called when an image request is discarded.
+   * This occurs during the ImageFactoryCache::Request destructor.
+   * @param[in] request The discarded request.
+   */
+  virtual void RequestDiscarded( const Request& request ) = 0;
+};
+
+/**
+* Request is a reference counted object to control the lifetime of elements in ImageFactory's cache.
+* When no more Image objects reference a request, it gets removed from ImageFactory cache.
+*/
+struct Request : public RefObject
+{
+  /**
+   * Image request.
+   * These requests are stored in ImageFactory's cache.
+   * @param [in] observer The object which observes request lifetime.
+   * @param [in] reqId A unique ID for this request.
+   * @param [ib] resId A unique ticket ID.
+   * @param [in] path  Url of request.
+   * @param [in] attr  Requested ImageAttributes.
+   */
+  Request( RequestLifetimeObserver& observer, RequestId reqId, ResourceId resId, const std::string& path, const ImageAttributes *attr );
+
+  ResourceId resourceId;        ///< The Ticket ID. This can be used to acquire details of the loaded resource from ResourceClient.
+  const std::string url;        ///< Path to the image resource
+  ImageAttributes* attributes;  ///< ImageAttributes that were used
+
+public:
+  /**
+   * Retrieve the unique ID of this request.
+   * @return The unique ID for this request.
+   */
+  RequestId GetId() const;
+
+  /**
+   * Called when the RequestLifetimeObserver is being destroyed.
+   * This method should only be called during destruction of the Dali core.
+   */
+  void StopLifetimeObservation();
+
+protected:
+  virtual ~Request();
+
+private:
+  Request(); ///< not defined
+  Request(const Request& rhs); ///< not defined
+  Request& operator=(const Request& rhs); ///< not defined
+
+private:
+  RequestId mId; ///< Request id assigned by ImageFactory
+  RequestLifetimeObserver* mLifetimeObserver; ///< reference to the lifetime-observer; not owned
+};
+
+typedef std::pair<RequestPathHashMap::iterator, RequestPathHashMap::iterator> RequestPathHashRange;
+
+} // namespace ImageFactoryCache
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_FACTORY_CACHE_H__
+
diff --git a/dali/internal/event/images/image-factory.cpp b/dali/internal/event/images/image-factory.cpp
new file mode 100644 (file)
index 0000000..c3ee746
--- /dev/null
@@ -0,0 +1,519 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/image-factory.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/devel-api/common/hash.h>
+#include <dali/public-api/images/resource-image.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/common/notification-manager.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/common/image-attributes.h>
+
+// EXTERNAL INCLUDES
+#include <float.h>
+
+using namespace Dali::Integration;
+using namespace Dali::Internal::ImageFactoryCache;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ImageFactory::ImageFactory( ResourceClient& resourceClient )
+: mResourceClient(resourceClient),
+  mMaxScale( 4 / 1024.0f ), ///< Only allow a very tiny fudge factor in matching new requests to existing resource transactions: 4 pixels at a dimension of 1024, 2 at 512, ...
+  mReqIdCurrent(0)
+{
+}
+
+ImageFactory::~ImageFactory()
+{
+  // Request memory is freed up by intrusive_ptr
+
+  mRequestCache.clear();
+}
+
+Request* ImageFactory::RegisterRequest( const std::string &filename, const ImageAttributes *attr )
+{
+  // check url cache
+  // check if same request exists
+  std::size_t urlHash = CalculateHash( filename );
+
+  Request* foundReq( NULL );
+  foundReq = FindRequest( filename, urlHash, attr );
+
+  if( !foundReq )
+  {
+    // the same request hasn't been made before
+    foundReq = InsertNewRequest( 0, filename, urlHash, attr );
+  }
+
+  return foundReq;
+}
+
+ResourceTicketPtr ImageFactory::Load( Request& request )
+{
+  ResourceTicketPtr ticket;
+
+  // See if any resource transaction has already been associated with this request:
+  const ResourceId resId = request.resourceId;
+  if( resId != 0 )
+  {
+    // An IO operation has been started at some time for the request so recover the
+    // ticket that was created for that:
+    ticket = mResourceClient.RequestResourceTicket( resId );  ///@note Always succeeds in normal use.
+  }
+  else
+  {
+    // Request not yet associated with a ticketed async resource transaction, so
+    // attempt to find a compatible cached one:
+    const std::size_t urlHash = GetHashForCachedRequest( request );
+    ticket = FindCompatibleResource( request.url, urlHash, request.attributes );
+  }
+
+  // Start a new resource IO transaction for the request if none is already happening:
+  if( !ticket )
+  {
+    ticket = IssueLoadRequest( request.url, request.attributes );
+  }
+  request.resourceId = ticket->GetId();
+
+  DALI_ASSERT_DEBUG( ticket->GetTypePath().type->id == ResourceBitmap      ||
+                     ticket->GetTypePath().type->id == ResourceNativeImage ||
+                     ticket->GetTypePath().type->id == ResourceTargetImage );
+  return ticket;
+}
+
+// File can change on fs, but still requesting same attributes.
+// Returning the ticket is important, because if two different requests mapped to the same resource
+// before, it is not guaranteed that they will still map to the same resource after reloading.
+// Example:
+// Image size (40, 40), Req1(img, 40, 40), Req2(img, 256, 256)
+// In this case both requests will be associated with the resource of size (40, 40)
+// If image changes on filesystem to size (96, 96) -> now after reloading Req2 would load a
+// new resource of size (96, 96), but reloading Req1 would load a scaled down version
+ResourceTicketPtr ImageFactory::Reload( Request& request )
+{
+  DALI_ASSERT_ALWAYS( &request );
+
+  // go through requests, check real size and attributes again. If different, update related ticket.
+  ResourceTicketPtr ticket;
+
+  if( !request.resourceId )
+  {
+    // in case of OnDemand loading, just return
+    return NULL;
+  }
+
+  ticket = mResourceClient.RequestResourceTicket( request.resourceId );
+
+  // ticket might have been deleted, eg. Image::Disconnect
+  if( !ticket )
+  {
+    ticket = IssueLoadRequest( request.url, request.attributes );
+    request.resourceId = ticket->GetId();
+  }
+  else // ticket still alive
+  {
+    DALI_ASSERT_DEBUG( ticket->GetTypePath().type->id == ResourceBitmap      ||
+                       ticket->GetTypePath().type->id == ResourceNativeImage ||
+                       ticket->GetTypePath().type->id == ResourceTargetImage );
+
+    // do not reload if still loading
+    if ( ticket->GetLoadingState() == ResourceLoading )
+    {
+      return ticket;
+    }
+
+    ImageDimensions closestSize;
+    if( request.attributes )
+    {
+      closestSize = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction().
+          GetClosestImageSize( request.url, ImageDimensions( request.attributes->GetSize().width, request.attributes->GetSize().width ),
+                               request.attributes->GetScalingMode(), request.attributes->GetFilterMode(), request.attributes->GetOrientationCorrection() );
+    }
+    else
+    {
+      closestSize = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction().GetClosestImageSize( request.url );
+    }
+    Vector2 size( closestSize.GetX(), closestSize.GetY() );
+
+    const ImageAttributes& attrib = static_cast<ImageTicket*>(ticket.Get())->GetAttributes();
+
+    if( size == attrib.GetSize() )
+    {
+      mResourceClient.ReloadResource( ticket->GetId(), false );
+    }
+    else
+    {
+      // if not, return a different ticket
+      ticket = IssueLoadRequest( request.url, request.attributes );
+      request.resourceId = ticket->GetId();
+    }
+  }
+  return ticket;
+}
+
+void ImageFactory::RecoverFromContextLoss()
+{
+  for( RequestIdMap::iterator it = mRequestCache.begin(); it != mRequestCache.end(); ++it )
+  {
+    // go through requests, reload with resource ticket's attributes.
+    Request* request = (*it).second;
+    if( request->resourceId )
+    {
+      ResourceTicketPtr ticket = mResourceClient.RequestResourceTicket( request->resourceId );
+
+      // do not reload if still loading
+      // check ticket is not NULL as the resource could have already been destroyed
+      if ( ticket && ticket->GetLoadingState() != ResourceLoading )
+      {
+        // Ensure the finished status is reset
+        mResourceClient.ReloadResource( ticket->GetId(), true );
+      }
+    }
+  }
+
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+      iter != end; iter++)
+  {
+    (*iter)->RecoverFromContextLoss();
+  }
+}
+
+
+void ImageFactory::RegisterForContextRecovery( ContextRecoveryInterface* object  )
+{
+  bool exist( false );
+  // To avoid registering the same object again
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+          iter != end; iter++)
+  {
+    if( object == *(iter) )
+    {
+      exist = true;
+      break;
+    }
+  }
+  if( !exist )
+  {
+    mContextRecoveryList.PushBack( object );
+  }
+}
+void ImageFactory::UnregisterFromContextRecovery( ContextRecoveryInterface* object  )
+{
+  Vector< ContextRecoveryInterface* >::ConstIterator end = mContextRecoveryList.End();
+  for( Vector< ContextRecoveryInterface* >::Iterator iter = mContextRecoveryList.Begin();
+        iter != end; iter++ )
+  {
+    if( object == *(iter) )
+    {
+      iter = mContextRecoveryList.Erase( iter );
+      break;
+    }
+  }
+}
+
+const std::string& ImageFactory::GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const
+{
+  if( request )
+  {
+    return request->url;
+  }
+
+  // Only create empty string if required
+  static std::string empty;
+  return empty;
+}
+
+const ImageAttributes& ImageFactory::GetActualAttributes( const ResourceTicketPtr& ticket ) const
+{
+  if( ticket )
+  {
+    DALI_ASSERT_DEBUG( ticket->GetTypePath().type->id == ResourceBitmap      ||
+                       ticket->GetTypePath().type->id == ResourceNativeImage ||
+                       ticket->GetTypePath().type->id == ResourceTargetImage );
+    const ImageAttributes& attrib = static_cast<ImageTicket*>(ticket.Get())->GetAttributes();
+    return attrib;
+  }
+  return ImageAttributes::DEFAULT_ATTRIBUTES;
+}
+
+const ImageAttributes& ImageFactory::GetRequestAttributes( const ImageFactoryCache::RequestPtr& request ) const
+{
+  if( request && request->attributes )
+  {
+    return *(request->attributes);
+  }
+
+  return ImageAttributes::DEFAULT_ATTRIBUTES;
+}
+
+void ImageFactory::GetImageSize( const ImageFactoryCache::RequestPtr& request, const ResourceTicketPtr& ticket, Size& size )
+{
+  if( ticket && ticket->GetLoadingState() != ResourceLoading )
+  {
+    // it is loaded so get the size from actual attributes
+    size = GetActualAttributes( ticket ).GetSize();
+  }
+  else
+  {
+    // not loaded so either loading or not yet loaded, ask platform abstraction
+    Integration::PlatformAbstraction& platformAbstraction = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction();
+
+    const ImageAttributes& attributes = GetRequestAttributes( request );
+    const ImageDimensions closestSize = platformAbstraction.GetClosestImageSize( GetRequestPath( request ),
+                                                                                   ImageDimensions( attributes.GetSize().width, attributes.GetSize().width ),
+                                                                                   attributes.GetScalingMode(), attributes.GetFilterMode(), attributes.GetOrientationCorrection() );
+    size[0] = closestSize.GetX();
+    size[1] = closestSize.GetY();
+  }
+}
+
+void ImageFactory::ReleaseTicket( ResourceTicket* ticket )
+{
+  ResourceTicketPtr ticketPtr(ticket);
+  mTicketsToRelease.push_back(ticketPtr);
+}
+
+void ImageFactory::FlushReleaseQueue()
+{
+  mTicketsToRelease.clear();
+}
+
+bool ImageFactory::CompareAttributes( const ImageAttributes& requested,
+                                      const ImageAttributes& actual ) const
+{
+  // do not load image resource again if there is a similar resource loaded:
+  // see explanation in image.h of what is deemed compatible
+  return (requested.GetScalingMode() ==  actual.GetScalingMode()) &&
+          (
+            (requested.GetFilterMode() == actual.GetFilterMode()) ||
+            (requested.GetFilterMode() == SamplingMode::DONT_CARE)
+          ) &&
+          (fabsf(requested.GetWidth()  -  actual.GetWidth())  <= actual.GetWidth()  * mMaxScale) &&
+          (fabsf(requested.GetHeight() -  actual.GetHeight()) <= actual.GetHeight() * mMaxScale);
+}
+
+Request* ImageFactory::InsertNewRequest( ResourceId resourceId, const std::string& filename, std::size_t urlHash, const ImageAttributes* attr )
+{
+  ++mReqIdCurrent;
+  Request* request = new Request( *this, mReqIdCurrent, resourceId, filename, attr );
+  mRequestCache.insert( RequestIdPair( mReqIdCurrent, request ) );
+  mUrlCache.insert( RequestPathHashPair( urlHash, mReqIdCurrent ) );
+  return request;
+}
+
+Request* ImageFactory::FindRequest( const std::string& filename, size_t hash, const ImageAttributes* attributes )
+{
+  // Search for a matching resource
+
+  // check whether the url has been used before
+  RequestPathHashRange foundRequests = mUrlCache.equal_range( hash );
+
+  // look for exact matches first
+  for( RequestPathHashMap::iterator it = foundRequests.first; it != foundRequests.second; ++it )
+  {
+    RequestId cachedReqId = it->second;
+
+    // get cached request
+    RequestIdMap::iterator foundRequestIter = mRequestCache.find( cachedReqId );
+    DALI_ASSERT_DEBUG( foundRequestIter != mRequestCache.end() && "Only requests that are live in mRequestCache should appear in mUrlCache which is an index to speed-up lookups into it.");
+    if( foundRequestIter != mRequestCache.end() )
+    {
+      const Request& cachedRequest = *(foundRequestIter->second);
+      const ImageAttributes* storedAttributes = cachedRequest.attributes;
+
+      // compare attributes: NULL means default attributes
+      if( !attributes )
+      {
+        attributes = &ImageAttributes::DEFAULT_ATTRIBUTES;
+      }
+      if( !storedAttributes )
+      {
+        storedAttributes = &ImageAttributes::DEFAULT_ATTRIBUTES;
+      }
+
+      if( *attributes != *storedAttributes )
+      {
+        continue;
+      }
+
+      if( filename.compare( cachedRequest.url ) )
+      {
+        // hash collision, filenames don't match
+        continue;
+      }
+
+      // we've found an exact match
+      return foundRequestIter->second;
+    }
+  }
+
+  return NULL;
+}
+
+ResourceTicketPtr ImageFactory::FindCompatibleResource( const std::string& filename, size_t hash, const ImageAttributes* attr )
+{
+  ResourceTicketPtr ticket;
+  // check whether the url has been used before
+  RequestPathHashRange foundRequests = mUrlCache.equal_range( hash );
+
+  bool foundCompatible = false;
+  if( foundRequests.first != mUrlCache.end() )
+  {
+    // check if we have a compatible resource already loaded
+    for( RequestPathHashMap::iterator it = foundRequests.first; it != foundRequests.second; ++it )
+    {
+      RequestId cachedReqId = it->second;
+
+      // get cached request
+      RequestIdMap::iterator foundRequestIter = mRequestCache.find( cachedReqId );
+      DALI_ASSERT_DEBUG( foundRequestIter != mRequestCache.end() );
+      if( foundRequestIter != mRequestCache.end() )
+      {
+        Request& cachedRequest = *(foundRequestIter->second);
+        if( filename.compare( cachedRequest.url ) )
+        {
+          // hash collision, filenames don't match
+          continue;
+        }
+
+        if( !cachedRequest.resourceId )
+        {
+          continue;
+        }
+
+        ticket = mResourceClient.RequestResourceTicket( cachedRequest.resourceId );
+        if( !ticket )
+        {
+          cachedRequest.resourceId = 0;
+          continue;
+        }
+
+        DALI_ASSERT_DEBUG( ticket->GetTypePath().type->id == ResourceBitmap      ||
+                           ticket->GetTypePath().type->id == ResourceNativeImage ||
+                           ticket->GetTypePath().type->id == ResourceTargetImage );
+
+        // check for compatible ImageAttributes
+        const ImageAttributes& storedAttributes = static_cast<ImageTicket*>(ticket.Get())->GetAttributes();
+        if( !attr )
+        {
+          attr = &ImageAttributes::DEFAULT_ATTRIBUTES;
+        }
+
+        // in case both attributes are default or they are matching custom ones
+        if( CompareAttributes( *attr, storedAttributes ) )
+        {
+          // found compatible resource
+          foundCompatible = true;
+          break;
+        }
+      }
+    } // for( it ...
+  } // foundRequests.first
+
+  if( !foundCompatible )
+  {
+    ticket.Reset();
+  }
+
+  return ticket;
+}
+
+ResourceTicketPtr ImageFactory::IssueLoadRequest( const std::string& filename, const ImageAttributes* attr )
+{
+  ImageDimensions dimensions;
+  FittingMode::Type fittingMode = FittingMode::DEFAULT;
+  SamplingMode::Type samplingMode = SamplingMode::DEFAULT;
+  bool orientation = true;
+
+  if( attr )
+  {
+    dimensions = ImageDimensions::FromFloatVec2( attr->GetSize() );
+    fittingMode = attr->GetScalingMode();
+    samplingMode = attr->GetFilterMode();
+    orientation = attr->GetOrientationCorrection();
+  }
+  else
+  {
+    // query image size from file if NULL was provided
+    dimensions = Dali::ResourceImage::GetImageSize( filename );
+    ///@ToDo: This is weird and pointless: we introduce a synchronous load of the image header on the event thread here to learn the image's on-disk dimensions to pass on to the resource system,
+    ///       but the default behaviour of the resource system when no dimensions are provided is to use exactly these on-disk dimensions when it eventually does the full load and decode.
+  }
+
+  BitmapResourceType resourceType( dimensions, fittingMode, samplingMode, orientation );
+  ResourceTicketPtr ticket = mResourceClient.RequestResource( resourceType, filename );
+  return ticket;
+}
+
+void ImageFactory::RequestDiscarded( const Request& req )
+{
+  RequestId id( req.GetId() );
+  // find in mRequestCache
+  RequestIdMap::iterator foundRequestIter = mRequestCache.find( id );
+  DALI_ASSERT_DEBUG( foundRequestIter != mRequestCache.end() );
+
+  // memory is freed up by intrusive_ptr
+
+  mRequestCache.erase( foundRequestIter );
+
+  // find in mUrlCache
+  for( RequestPathHashMap::iterator it = mUrlCache.begin(); it != mUrlCache.end(); ++it )
+  {
+    if( id == it->second )
+    {
+      mUrlCache.erase( it );
+      break;
+    }
+  }
+}
+
+std::size_t ImageFactory::GetHashForCachedRequest( const Request& request )
+{
+  const RequestId requestId = request.GetId();
+  std::size_t locatorHash(0);
+  RequestPathHashMap::const_iterator it;
+
+  for( it = mUrlCache.begin(); it != mUrlCache.end(); ++it )
+  {
+    if( it->second == requestId )
+    {
+      locatorHash = it->first;
+      break;
+    }
+  }
+  DALI_ASSERT_DEBUG( it!=mUrlCache.end() && "Only already-cached requests can have their locator hashes looked-up." );
+  return locatorHash;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/image-factory.h b/dali/internal/event/images/image-factory.h
new file mode 100644 (file)
index 0000000..4f235ed
--- /dev/null
@@ -0,0 +1,245 @@
+#ifndef __DALI_INTERNAL_IMAGE_FACTORY_H__
+#define __DALI_INTERNAL_IMAGE_FACTORY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/images/context-recovery-interface.h>
+#include <dali/internal/event/images/image-factory-cache.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class ResourceType;
+
+namespace ImageFactoryCache
+{
+struct Request;
+}
+
+/**
+ * ImageFactory is an object that manages Image resource load requests.
+ * It utilises an internal caching system where previous requests and associated
+ * resources are stored to avoid accessing the file system when not necessary.
+ */
+class ImageFactory : public ImageFactoryCache::RequestLifetimeObserver
+{
+public:
+
+  /**
+   * default constructor
+   */
+  ImageFactory( ResourceClient& resourceClient );
+
+  /**
+   * Default destructor
+   */
+  virtual ~ImageFactory();
+
+  /**
+   * Registers a request for an image resource if not yet available, but does not start loading yet.
+   * Use Load( req ) to issue load request.
+   * If image was already requested, an existing request is returned.
+   * @param [in] filename   path of requested image resource
+   * @param [in] attributes pointer to the ImageAttributes of the request. If NULL, default attributes are used.
+   * @return     request pointer
+   */
+  ImageFactoryCache::Request* RegisterRequest( const std::string& filename, const ImageAttributes *attributes );
+
+  /**
+   * Issue a request which has already been registered with ImageFactory.
+   * If the associated Ticket is no longer alive ImageFactory issues a resource load request.
+   * @param [in] request Request to be loaded.
+   * @return     intrusive pointer to image ticket. If Load fails, returned pointer is invalid. (!ret)
+   */
+  ResourceTicketPtr Load( ImageFactoryCache::Request& request );
+
+  /**
+   * Tells ResourceManager to reload image from filesystem.
+   * Also sends message to render thread.
+   * This operation uses the originally requested attributes when reloading the image.
+   * @pre req must be registered with ImageFactory
+   * @note if image is still loading, no new load request will be issued
+   * @param[in]  request Request to be reloaded.
+   * @return the ResourceTicket mapped to the request
+   */
+  ResourceTicketPtr Reload( ImageFactoryCache::Request& request );
+
+  /**
+   * Ensures all filesystem images are reloaded into textures.
+   * This operation uses the originally requested attributes when reloading the image.
+   *
+   * Recovering from context loss does not change the number of tickets if the
+   * image size has changed on the file system since the last load/reload.
+   *
+   * If two different requests mapped to the same resource before, they will still
+   * map to the same resource after context regain even if there would be a better
+   * fitting texture.
+   * @pre requests must be registered with ImageFactory
+   * @note If an image is still loading, no new load request will be issued.
+   */
+  void RecoverFromContextLoss();
+
+  /**
+   * Register an object into the context recovery list of  the image factory.
+   * Thus its RecoverFromContextLoss() function would be called when the Stage regaining context.
+   * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+   */
+  void RegisterForContextRecovery( ContextRecoveryInterface* object  );
+
+  /**
+   * Unregister an object from the context recovery list of the image factory
+   * @param[in] object The object whose RecoverFromContextLoss() function needs to be called to regain the context.
+   */
+  void UnregisterFromContextRecovery( ContextRecoveryInterface* object  );
+
+  /**
+   * Get resource path used in request.
+   * @param [in] request of the image
+   * @return     resource path
+   */
+  const std::string& GetRequestPath( const ImageFactoryCache::RequestPtr& request ) const;
+
+  /**
+   * Get ImageAttributes for an already requested image resource.
+   * @pre id should mark an existing Resource (Ticket is alive)
+   * @param [in] ticket of the image
+   * @return     ImageAttributes used for request.
+   * @throws     Throws exception if id is not valid.
+   */
+  const ImageAttributes& GetActualAttributes( const ResourceTicketPtr& ticket ) const;
+
+  /**
+   * Get ImageAttributes used for request.
+   * @pre req must point to a Request registered with ImageFactory
+   * @param [in] request of the image
+   * @return     ImageAttributes used for request.
+   */
+  const ImageAttributes& GetRequestAttributes( const ImageFactoryCache::RequestPtr& request ) const;
+
+  /**
+   * Retrieve the size of an image. This is either the application requested size or
+   * the actual (full size) that is or will be loaded.
+   * @param[in] request of the image
+   * @param[in] ticket of the image
+   * @param[out] size of the image
+   */
+  void GetImageSize( const ImageFactoryCache::RequestPtr& request, const ResourceTicketPtr& ticket, Size& size );
+
+  /**
+   * Prevents releasing and reloading image resources in the same frame
+   * @param [in] ticket the resource ticket to queue for releasing
+   */
+  void ReleaseTicket( ResourceTicket* ticket );
+
+  /**
+   * Flush the queue of resource tickets that were about to be relased.
+   * This discards the kept ticket handles at the end of each frame, and this way prevents
+   * releasing and reloading image resources in the same frame.
+   */
+  void FlushReleaseQueue();
+
+public: // From RequestLifetimeObserver
+
+  /**
+   * Finds request by id in mRequestCache and mUrlCache and removes relevant entries.
+   * @param [in] id request id
+   */
+  virtual void RequestDiscarded( const ImageFactoryCache::Request& request );
+
+private:
+
+  // Undefined
+  ImageFactory( const ImageFactory& );
+
+  // Undefined
+  ImageFactory& operator=( const ImageFactory& rhs );
+
+  /**
+   * Checks if the previously loaded image's attributes are compatible with a new request
+   * @param [in] requested The requested attributes
+   * @param [in] actual    The actual attributes
+   * @return True if the attributes are compatible
+   */
+  bool CompareAttributes( const ImageAttributes& requested,
+                          const ImageAttributes& actual ) const;
+
+  /**
+   * Inserts a new request to the request cache and url cache.
+   * @note this method increases the current request Id counter (mReqIdCurrent)
+   * @param [in] resourceId Ticket id to insert.
+   * @param [in] url        The requested url to insert.
+   * @param [in] urlHash    Calculated hash value for the url.
+   * @param [in] attr       Pointer to the requested attributes, NULL if default values are used.
+   * @return pointer to Request
+   */
+  ImageFactoryCache::Request* InsertNewRequest( ResourceId resourceId, const std::string& url, std::size_t urlHash, const ImageAttributes* attr );
+
+  /**
+   * Searches request cache for exact match.
+   * @param [in] filename    The url of the image resource.
+   * @param [in] hash        Hash value for the filename.
+   * @param [in] attributes  Pointer to ImageAttributes used for the request or NULL if default attributes were used.
+   * @return pointer to the found request or NULL if no exact match is found.
+   */
+  ImageFactoryCache::Request* FindRequest( const std::string& filename, size_t hash, const ImageAttributes *attributes );
+
+  /**
+   * Searches through tickets to find a compatible resource.
+   * @param [in] filename   The url of the image resource.
+   * @param [in] hash       Hash value for the filename.
+   * @param [in] attributes Pointer to ImageAttributes used for the request or NULL if default attributes were used.
+   * @return A ticket pointer to the found resource or an unitialized pointer if no compatible one is found.
+   */
+  ResourceTicketPtr FindCompatibleResource( const std::string& filename, size_t hash, const ImageAttributes* attributes );
+
+  /**
+   * Helper function that requests the image resource from platform abstraction.
+   * @param [in] filename   The url of the image resource.
+   * @param [in] attributes Pointer to ImageAttributes to be used for the request or NULL if default attributes are used.
+   * @return intrusive pointer to Ticket
+   */
+  ResourceTicketPtr IssueLoadRequest( const std::string& filename, const ImageAttributes* attributes );
+
+  /**
+   * Looks-up the hash of the string locator of the already-registered Request
+   * passed in.
+   * @param[in] request The image load request to return a locator string hash for.
+   * @return The hash of the locator string used in the request.
+   */
+  std::size_t GetHashForCachedRequest( const ImageFactoryCache::Request& request );
+
+private:
+  ResourceClient&                          mResourceClient;
+  ImageFactoryCache::RequestPathHashMap    mUrlCache;         ///< A multimap of url hashes and request IDs
+  ImageFactoryCache::RequestIdMap          mRequestCache;     ///< A map of request IDs and request information.
+  ResourceTicketContainer                  mTicketsToRelease; ///< List of ticket handles
+  Vector<ContextRecoveryInterface*>        mContextRecoveryList; ///< List of the objects who needs context recovery
+  float                                    mMaxScale;         ///< Defines maximum size difference between compatible resources
+  ImageFactoryCache::RequestId             mReqIdCurrent;     ///< Internal counter for Request IDs
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_FACTORY_H__
diff --git a/dali/internal/event/images/image-impl.cpp b/dali/internal/event/images/image-impl.cpp
new file mode 100644 (file)
index 0000000..4e3fa1e
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/image-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+using namespace Dali::Integration;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_IMAGE_UPLOADED = "uploaded";
+
+TypeRegistration mType( typeid( Dali::Image ), typeid( Dali::BaseHandle ), NULL );
+
+Dali::SignalConnectorType signalConnector1( mType, SIGNAL_IMAGE_UPLOADED, &Image::DoConnectSignal );
+
+}
+
+bool Image::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  DALI_ASSERT_DEBUG( dynamic_cast<Image*>( object ) && "Resource ticket not ImageTicket subclass for image resource.\n" );
+  Image* image = static_cast<Image*>(object);
+
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_IMAGE_UPLOADED ) )
+  {
+    image->UploadedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+ResourceId Image::GetResourceId() const
+{
+  ResourceId ret = mTicket ? mTicket->GetId() : 0;
+
+  return ret;
+}
+
+void Image::ResourceLoadingFailed(const ResourceTicket& ticket)
+{
+  // do nothing
+}
+
+void Image::ResourceLoadingSucceeded(const ResourceTicket& ticket)
+{
+  // do nothing
+}
+
+void Image::ResourceUploaded(const ResourceTicket& ticket)
+{
+  mUploaded.Emit( Dali::Image( this ) );
+}
+
+unsigned int Image::GetWidth() const
+{
+  return mWidth;
+}
+
+unsigned int Image::GetHeight() const
+{
+  return mHeight;
+}
+
+Vector2 Image::GetNaturalSize() const
+{
+  return Vector2( mWidth, mHeight );
+}
+
+Image::Image( ReleasePolicy releasePol )
+: mWidth( 0 ),
+  mHeight( 0 ),
+  mConnectionCount( 0 ),
+  mReleasePolicy( releasePol )
+{
+}
+
+Image::~Image()
+{
+  if( mTicket )
+  {
+    mTicket->RemoveObserver( *this );
+    mTicket.Reset();
+  }
+
+  if( Stage::IsInstalled() )
+  {
+    UnregisterObject();
+  }
+}
+
+void Image::Initialize()
+{
+  RegisterObject();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/image-impl.h b/dali/internal/event/images/image-impl.h
new file mode 100644 (file)
index 0000000..540b63f
--- /dev/null
@@ -0,0 +1,191 @@
+#ifndef __DALI_INTERNAL_IMAGE_H__
+#define __DALI_INTERNAL_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/event/resources/resource-ticket-observer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Dali::Image::ReleasePolicy ReleasePolicy;
+
+class Image;
+class ImageFactory;
+typedef IntrusivePtr<Image> ImagePtr;
+
+const ReleasePolicy IMAGE_RELEASE_POLICY_DEFAULT = Dali::Image::NEVER;
+
+/**
+ * Image represents an image resource that can be added to actors etc.
+ * When the Image object is created, resource loading will be attempted.
+ * Provided this is successful, the resource will exist until the Image is destroyed.
+ */
+class Image : public BaseObject, public ResourceTicketObserver
+{
+public:
+
+  /**
+   * @copydoc Dali::Image::GetReleasePolicy()
+   */
+  ReleasePolicy GetReleasePolicy () const { return mReleasePolicy; }
+
+  /**
+   * @copydoc Dali::Image::UploadedSignal()
+   */
+  Dali::Image::ImageSignalType& UploadedSignal() { return mUploaded; }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+  /**
+   * returns the Id used for lookups
+   * @note if LoadPolicy::OnDemand is used and Image is off Stage, this will return 0.
+   * @return the unique ID of the image data resource. This is actually also the same as Dali Texture id.
+   */
+  ResourceId GetResourceId() const;
+
+  /**
+   * Get the width of the image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * The returned value will reflect the true image dimensions once the asynchronous loading has finished.
+   * @pre image should be loaded
+   */
+  virtual unsigned int GetWidth() const;
+
+  /**
+   * Get the height of the image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * The returned value will reflect the true image dimensions once the asynchronous loading has finished.
+   * @pre image should be loaded
+   */
+  virtual unsigned int GetHeight() const;
+
+  /**
+   * Return the natural size of the image.
+   * This is the size that the loaded image will take
+   */
+  virtual Vector2 GetNaturalSize() const;
+
+public: // From ResourceTicketObserver
+
+  /**
+   * @copydoc Dali::Internal::ResourceTicketObserver::ResourceLoadingFailed()
+   */
+  virtual void ResourceLoadingFailed(const ResourceTicket& ticket);
+
+  /**
+   * @copydoc Dali::Internal::ResourceTicketObserver::ResourceLoadingSucceeded()
+   */
+  virtual void ResourceLoadingSucceeded(const ResourceTicket& ticket);
+
+  /**
+   * @copydoc Dali::Internal::ResourceTicketObserver::ResourceUploaded()
+   */
+  virtual void ResourceUploaded(const ResourceTicket& ticket);
+
+public:
+
+  /**
+   * Indicates that the image is used.
+   */
+  virtual void Connect() {}
+
+  /**
+   * Indicates that the image is not used anymore.
+   */
+  virtual void Disconnect() {}
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Image();
+
+  /**
+   * Constructor, with default parameters
+   */
+  Image( ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize();
+
+protected:
+
+  ResourceTicketPtr mTicket;              ///< smart pointer to the ticket object that gets completed when load finishes
+
+  mutable unsigned int mWidth;     ///< natural width of the image, needs to be mutable for lazy resolving and as the API for GetWidth is const
+  mutable unsigned int mHeight;    ///< natural height of the image, needs to be mutable for lazy resolving and as the API for GetHeight is const
+
+  unsigned int mConnectionCount; ///< number of on-stage objects using this image
+
+  ReleasePolicy  mReleasePolicy : 2; ///< 2 bits is enough space
+
+private:
+
+  Dali::Image::ImageSignalType mUploaded;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::Image& GetImplementation(Dali::Image& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::Image&>(handle);
+}
+
+inline const Internal::Image& GetImplementation(const Dali::Image& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::Image&>(handle);
+}
+
+} // namespace Dali
+#endif // __DALI_INTERNAL_IMAGE_H__
diff --git a/dali/internal/event/images/native-image-impl.cpp b/dali/internal/event/images/native-image-impl.cpp
new file mode 100644 (file)
index 0000000..4043f91
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/native-image-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+using namespace Dali::Integration;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid(Dali::NativeImage), typeid(Dali::Image), NULL );
+}
+
+NativeImage::NativeImage()
+: Image()
+{
+}
+
+NativeImagePtr NativeImage::New( NativeImageInterface& resourceData )
+{
+  NativeImagePtr image = new NativeImage;
+  image->Initialize();
+
+  ResourceClient &resourceClient = ThreadLocalStorage::Get().GetResourceClient();
+
+  image->mWidth  = resourceData.GetWidth();
+  image->mHeight = resourceData.GetHeight();
+
+  const ResourceTicketPtr& ticket = resourceClient.AddNativeImage( resourceData );
+  DALI_ASSERT_DEBUG( dynamic_cast<ImageTicket*>( ticket.Get() ) && "Resource ticket not ImageTicket subclass for image resource.\n" );
+  image->mTicket = static_cast<ImageTicket*>(ticket.Get());
+  image->mTicket->AddObserver( *image );
+
+  return image;
+}
+
+NativeImage::~NativeImage()
+{
+}
+
+void NativeImage::CreateGlTexture()
+{
+  ResourceClient& resourceClient = ThreadLocalStorage::Get().GetResourceClient();
+  resourceClient.CreateGlTexture( GetResourceId() );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/native-image-impl.h b/dali/internal/event/images/native-image-impl.h
new file mode 100644 (file)
index 0000000..0f1dfe4
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_NATIVE_IMAGE_H__
+#define __DALI_INTERNAL_NATIVE_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/native-image.h>
+#include <dali/internal/event/images/image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class NativeImage;
+typedef IntrusivePtr<NativeImage> NativeImagePtr;
+
+/**
+ * @copydoc Dali::NativeImage
+ */
+class NativeImage : public Image
+{
+public:
+
+  /**
+   * Creates object by using native resources
+   * the maximum size of the image is limited by GL_MAX_TEXTURE_SIZE
+   * @param [in] nativeImageInterface An reference to the object of the interface implementation.
+   * @return a pointer to a newly created object.
+   */
+  static NativeImagePtr New( NativeImageInterface& nativeImageInterface );
+
+  /**
+   * @copydoc Dali::NativeImage::CreateGlTexture
+   */
+  void CreateGlTexture();
+
+protected:
+
+  /**
+   * Constructor
+   */
+  NativeImage();
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~NativeImage();
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::NativeImage& GetImplementation(Dali::NativeImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::NativeImage&>(handle);
+}
+
+inline const Internal::NativeImage& GetImplementation(const Dali::NativeImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::NativeImage&>(handle);
+}
+
+} // namespace Dali
+#endif // __DALI_INTERNAL_NATIVE_IMAGE_H__
diff --git a/dali/internal/event/images/nine-patch-image-impl.cpp b/dali/internal/event/images/nine-patch-image-impl.cpp
new file mode 100644 (file)
index 0000000..af3eb31
--- /dev/null
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for memcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/internal/event/images/bitmap-external.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/resource-types.h>
+#include <dali/integration-api/resource-cache.h>
+
+
+namespace
+{
+void GetRedOffsetAndMask(Dali::Pixel::Format pixelFormat, int& byteOffset, int& bitMask)
+{
+  switch (pixelFormat)
+  {
+    case Dali::Pixel::A8:
+    case Dali::Pixel::L8:
+    case Dali::Pixel::LA88:
+    {
+      byteOffset=0;
+      bitMask=0;
+      break;
+    }
+
+    case Dali::Pixel::RGB888:
+    case Dali::Pixel::RGB8888:
+    case Dali::Pixel::RGBA8888:
+    {
+      byteOffset=0;
+      bitMask=0xFF;
+      break;
+    }
+    case Dali::Pixel::BGR8888:
+    case Dali::Pixel::BGRA8888:
+    {
+      byteOffset=2;
+      bitMask=0xff;
+      break;
+    }
+    case Dali::Pixel::RGB565:
+    {
+      byteOffset=0;
+      bitMask=0xf8;
+      break;
+    }
+    case Dali::Pixel::BGR565:
+    {
+      byteOffset=1;
+      bitMask=0x1f;
+      break;
+    }
+
+    case Dali::Pixel::RGBA4444:
+    {
+      byteOffset=0;
+      bitMask=0xf0;
+      break;
+    }
+    case Dali::Pixel::BGRA4444:
+    {
+      byteOffset=1;
+      bitMask=0xf0;
+      break;
+    }
+
+    case Dali::Pixel::RGBA5551:
+    {
+      byteOffset=0;
+      bitMask=0xf8;
+      break;
+    }
+
+    case Dali::Pixel::BGRA5551:
+    {
+      byteOffset=1;
+      bitMask=0x1e;
+      break;
+    }
+
+    case Dali::Pixel::COMPRESSED_R11_EAC:
+    case Dali::Pixel::COMPRESSED_SIGNED_R11_EAC:
+    case Dali::Pixel::COMPRESSED_RG11_EAC:
+    case Dali::Pixel::COMPRESSED_SIGNED_RG11_EAC:
+    case Dali::Pixel::COMPRESSED_RGB8_ETC2:
+    case Dali::Pixel::COMPRESSED_SRGB8_ETC2:
+    case Dali::Pixel::COMPRESSED_RGB8_ETC1:
+    case Dali::Pixel::COMPRESSED_RGB_PVRTC_4BPPV1:
+    case Dali::Pixel::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case Dali::Pixel::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case Dali::Pixel::COMPRESSED_RGBA8_ETC2_EAC:
+    case Dali::Pixel::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    {
+      DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
+      byteOffset=0;
+      bitMask=0;
+      break;
+    }
+  }
+}
+
+} // anonymous namespace
+
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+TypeRegistration mType( typeid( Dali::NinePatchImage ), typeid( Dali::Image ), NULL );
+} // unnamed namespace
+
+NinePatchImagePtr NinePatchImage::New( const std::string& filename, ReleasePolicy releasePol )
+{
+  Internal::NinePatchImagePtr internal( new NinePatchImage( filename, releasePol ) );
+  internal->Initialize();
+  return internal;
+}
+
+NinePatchImage::NinePatchImage( const std::string& filename, ReleasePolicy releasePol )
+: ResourceImage( IMAGE_LOAD_POLICY_DEFAULT, releasePol ),
+  mParsedBorder(false)
+{
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  mResourceClient = &tls.GetResourceClient();
+
+  Integration::PlatformAbstraction& platformAbstraction = tls.GetPlatformAbstraction();
+  Integration::BitmapResourceType resourceType;
+
+  // Note, bitmap is only destroyed when the image is destroyed.
+  Integration::ResourcePointer resource = platformAbstraction.LoadResourceSynchronously( resourceType, filename );
+  if( resource )
+  {
+    mBitmap = static_cast<Integration::Bitmap*>( resource.Get());
+    mWidth = mBitmap->GetImageWidth();
+    mHeight = mBitmap->GetImageHeight();
+  }
+  else
+  {
+    mBitmap.Reset();
+    mWidth = 0;
+    mHeight = 0;
+  }
+}
+
+NinePatchImage* NinePatchImage::DownCast( Image* image)
+{
+  return dynamic_cast<NinePatchImage*>(image);
+}
+
+NinePatchImage::~NinePatchImage()
+{
+}
+
+Vector4 NinePatchImage::GetStretchBorders()
+{
+  if( ! mParsedBorder )
+  {
+    ParseBorders();
+  }
+  return mStretchBorders;
+}
+
+Rect<int> NinePatchImage::GetChildRectangle()
+{
+  if( ! mParsedBorder )
+  {
+    ParseBorders();
+  }
+  return mChildRectangle;
+}
+
+Internal::BufferImagePtr NinePatchImage::CreateCroppedBufferImage()
+{
+  BufferImagePtr cropped;
+
+  if( ! mBitmap )
+  {
+    DALI_LOG_ERROR( "NinePatchImage: Bitmap not loaded, cannot perform operation\n");
+  }
+  else
+  {
+    Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
+
+    cropped = BufferImage::New( mWidth-2, mHeight-2, pixelFormat, Dali::Image::NEVER );
+
+    Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
+    DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
+
+    if( srcProfile )
+    {
+      PixelBuffer* destPixels = cropped->GetBuffer();
+      unsigned int destStride = cropped->GetBufferStride();
+      unsigned int pixelWidth = GetBytesPerPixel(pixelFormat);
+
+      PixelBuffer* srcPixels = mBitmap->GetBuffer();
+      unsigned int srcStride = srcProfile->GetBufferStride();
+
+      for( unsigned int row=1; row < mHeight-1; ++row )
+      {
+        PixelBuffer* src  = srcPixels + row*srcStride + pixelWidth;
+        PixelBuffer* dest = destPixels + (row-1)*destStride;
+        memcpy(dest, src, destStride );
+      }
+    }
+
+    RectArea area;
+    cropped->Update(area); // default area has no width or height
+  }
+  return cropped;
+}
+
+void NinePatchImage::Connect()
+{
+  if( !mTicket )
+  {
+    if( mBitmap )
+    {
+      const ImageTicketPtr& t = mResourceClient->AddBitmapImage(mBitmap.Get());
+      mTicket = t.Get();
+      mTicket->AddObserver(*this);
+    }
+  }
+
+  ++mConnectionCount;
+}
+
+void NinePatchImage::Disconnect()
+{
+  if( mConnectionCount > 0 )
+  {
+    --mConnectionCount;
+  }
+}
+
+
+void NinePatchImage::ParseBorders()
+{
+  if( ! mBitmap )
+  {
+    DALI_LOG_ERROR( "NinePatchImage: Bitmap not loaded, cannot perform operation\n");
+    return;
+  }
+
+  Pixel::Format pixelFormat = mBitmap->GetPixelFormat();
+
+  Integration::Bitmap::PackedPixelsProfile* srcProfile = mBitmap->GetPackedPixelsProfile();
+  DALI_ASSERT_DEBUG( srcProfile && "Wrong profile for source bitmap");
+
+  if( srcProfile )
+  {
+    unsigned int pixelWidth = GetBytesPerPixel(pixelFormat);
+    PixelBuffer* srcPixels = mBitmap->GetBuffer();
+    unsigned int srcStride = srcProfile->GetBufferStride();
+
+    int alphaByte=0;
+    int alphaBits=0;
+    Pixel::GetAlphaOffsetAndMask(pixelFormat, alphaByte, alphaBits);
+    int redByte=0;
+    int redBits=0;
+    GetRedOffsetAndMask(pixelFormat, redByte, redBits);
+
+    int testByte = alphaByte;
+    int testBits = alphaBits;
+    int testValue = alphaBits; // Opaque == stretch
+    if( ! alphaBits )
+    {
+      testByte = redByte;
+      testBits = redBits;
+      testValue = 0;           // Black == stretch
+    }
+
+    int startX1=-1;
+    int endX1=-1;
+    int startY1=-1;
+    int endY1=-1;
+    int startX2=-1;
+    int endX2=-1;
+    int startY2=-1;
+    int endY2=-1;
+
+    PixelBuffer* top = srcPixels + pixelWidth;
+    PixelBuffer* bottom = srcPixels + (mHeight-1)*srcStride + pixelWidth;
+
+    // Read the top and bottom rows:
+    // (Also read the last column to ensure end value gets set)
+    for( unsigned int col=1; col < mWidth; ++col )
+    {
+      if( (top[testByte] & testBits) == testValue )
+      {
+        if(startX1 < 0)
+        {
+          startX1 = col;
+        }
+      }
+      else if(startX1 >= 0 && endX1 < 0)
+      {
+        endX1 = col;
+      }
+
+      if( (bottom[testByte] & testBits) == testValue )
+      {
+        if(startX2 < 0)
+        {
+          startX2 = col;
+        }
+      }
+      else if(startX2 >= 0 && endX2 < 0)
+      {
+        endX2 = col;
+      }
+
+      if ( ( endX2 > 0 ) && ( endX1 > 0 ) )
+      {
+        break;
+      }
+
+      top+=pixelWidth;
+      bottom+=pixelWidth;
+    }
+
+    // Read the left and right columns:
+    PixelBuffer* left  = srcPixels + srcStride;
+    PixelBuffer* right = left + (srcStride - pixelWidth);
+
+    // (Also read the last row to ensure end value gets set)
+    for( unsigned int row=1; row < mHeight; ++row )
+    {
+      if((left[testByte] & testBits) == testValue)
+      {
+        if(startY1 < 0)
+        {
+          startY1 = row;
+        }
+      }
+      else if(startY1 >= 0 && endY1 < 0)
+      {
+        endY1 = row;
+      }
+
+      if((right[testByte] & testBits) == testValue)
+      {
+        if(startY2 < 0)
+        {
+          startY2 = row;
+        }
+      }
+      else if(startY2 >= 0 && endY2 < 0)
+      {
+        endY2 = row;
+      }
+      left += srcStride;
+      right += srcStride;
+
+      if ( ( endY2 > 0 ) && ( endY1 > 0 ) )
+      {
+        break;
+      }
+    }
+
+    mStretchBorders.x = startX1;
+    mStretchBorders.y = startY1;
+    mStretchBorders.z = mWidth-endX1;
+    mStretchBorders.w = mHeight-endY1;
+
+    mChildRectangle.x = startX2;
+    mChildRectangle.y = startY2;
+    mChildRectangle.width = endX2-startX2;
+    mChildRectangle.height = endY2-startY2;
+
+    mParsedBorder = true;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/nine-patch-image-impl.h b/dali/internal/event/images/nine-patch-image-impl.h
new file mode 100644 (file)
index 0000000..27a3b2f
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
+#define __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/nine-patch-image.h>
+#include <dali/internal/event/images/resource-image-impl.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class NinePatchImage;
+typedef IntrusivePtr<NinePatchImage> NinePatchImagePtr;
+
+class ResourceClient;
+class ResourceManager;
+
+namespace SceneGraph
+{
+class UpdateManager;
+}
+
+/**
+ * NinePatchImage represents an image resource that can be added to actors etc.
+ * It's image data has a border which determines stretch and fill areas
+ * Its pixel buffer data is loaded synchronously from file.
+ */
+class NinePatchImage : public ResourceImage
+{
+public:
+
+  /**
+   * Create a new NinePatchImage.
+   * Also a pixel buffer for image data is allocated.
+   * Dali has ownership of the buffer.
+   * @param [in] filename    File to load synchronously into buffer
+   * @param [in] releasePol  optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  static NinePatchImagePtr New( const std::string& filename,
+                                ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * Create a new NinePatchImage
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @param [in] filename    File to load synchronously into buffer
+   * @param [in] releasePol  optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   */
+  NinePatchImage( const std::string& filename,
+                  ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * Convert Image object to a 9 patch image object if possible.
+   * @param[in] image The image to convert
+   * @return A pointer to the 9 patch image object, or NULL
+   * if the conversion is not possible.
+   */
+  static NinePatchImage* DownCast( Image* image);
+
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~NinePatchImage();
+
+public:
+  /**
+   * Get the stretch borders
+   * @return The border in pixels from the left, top, right, and bottom of the image respectively.
+   */
+  Vector4 GetStretchBorders();
+
+  /**
+   * Get the child rectangle
+   * @return the position and size of the child rectangle
+   */
+  Rect<int> GetChildRectangle();
+
+  /**
+   * @brief Create a cropped image from the bitmap with the 1 pixel border cropped off.
+   * This does not change the internal bitmap.
+   *
+   * @return the cropped bitmap.
+   */
+  BufferImagePtr CreateCroppedBufferImage();
+
+
+protected: // From Resource
+  /**
+   * @copydoc Dali::Internal::Image::Connect
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Image::Disconnect
+   */
+  virtual void Disconnect();
+
+private:
+  /**
+   * Read the borders of the bitmap and determine the child area
+   * and stretch borders
+   */
+  void ParseBorders();
+
+private:
+  ResourceClient*               mResourceClient;
+  Integration::BitmapPtr        mBitmap;
+  Vector4                       mStretchBorders;
+  Rect<int>                     mChildRectangle;
+  bool                          mParsedBorder;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::NinePatchImage& GetImplementation(Dali::NinePatchImage& handle)
+{
+  DALI_ASSERT_ALWAYS( handle && "NinePatchImage handle is empty" );
+
+  BaseObject& image = handle.GetBaseObject();
+
+  return static_cast<Internal::NinePatchImage&>(image);
+}
+
+inline const Internal::NinePatchImage& GetImplementation(const Dali::NinePatchImage& handle)
+{
+  DALI_ASSERT_ALWAYS( handle && "NinePatchImage handle is empty" );
+
+  const BaseObject& image = handle.GetBaseObject();
+
+  return static_cast<const Internal::NinePatchImage&>(image);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_NINE_PATCH_IMAGE_H__
diff --git a/dali/internal/event/images/resource-image-impl.cpp b/dali/internal/event/images/resource-image-impl.cpp
new file mode 100644 (file)
index 0000000..ff4a247
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/images/resource-image-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/images/image-factory.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+
+using namespace Dali::Integration;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// Signals
+
+const char* const SIGNAL_IMAGE_LOADING_FINISHED = "image-loading-finished";
+
+BaseHandle CreateImage()
+{
+  ImagePtr image = ResourceImage::New();
+  return Dali::Image(image.Get());
+}
+
+TypeRegistration mType( typeid( Dali::ResourceImage ), typeid( Dali::Image ), CreateImage );
+
+Dali::SignalConnectorType signalConnector1( mType, SIGNAL_IMAGE_LOADING_FINISHED, &ResourceImage::DoConnectSignal );
+
+}
+
+ResourceImage::ResourceImage( LoadPolicy loadPol, ReleasePolicy releasePol )
+: Image( releasePol ),
+  mImageFactory( ThreadLocalStorage::Get().GetImageFactory() ),
+  mLoadPolicy(loadPol)
+{
+}
+
+ResourceImagePtr ResourceImage::New()
+{
+  ResourceImagePtr image = new ResourceImage;
+  image->Initialize();
+  return image;
+}
+
+ResourceImagePtr ResourceImage::New( const std::string& url, const ImageAttributes& attributes, LoadPolicy loadPol, ReleasePolicy releasePol )
+{
+  ResourceImagePtr image;
+  if( IsNinePatch( url ) )
+  {
+    image = NinePatchImage::New( url, releasePol );
+  }
+  else
+  {
+    image = new ResourceImage( loadPol, releasePol );
+    image->Initialize();
+
+    // consider the requested size as natural size, 0 means we don't (yet) know it
+    image->mWidth = attributes.GetWidth();
+    image->mHeight = attributes.GetHeight();
+    image->mRequest = image->mImageFactory.RegisterRequest( url, &attributes );
+
+    if( Dali::ResourceImage::IMMEDIATE == loadPol )
+    {
+      // Trigger loading of the image on a as soon as it can be done
+      image->mTicket = image->mImageFactory.Load( *image->mRequest.Get() );
+      image->mTicket->AddObserver( *image );
+    }
+  }
+  DALI_LOG_SET_OBJECT_STRING( image, url );
+
+  return image;
+}
+
+ResourceImage::~ResourceImage()
+{
+  if( mTicket )
+  {
+    mTicket->RemoveObserver( *this );
+    if( Stage::IsInstalled() )
+    {
+      mImageFactory.ReleaseTicket( mTicket.Get() );
+    }
+    mTicket.Reset();
+  }
+}
+
+bool ResourceImage::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  DALI_ASSERT_DEBUG( dynamic_cast<ResourceImage*>( object ) && "Resource ticket not ImageTicket subclass for image resource.\n" );
+  ResourceImage* image = static_cast<ResourceImage*>(object);
+
+  if( 0 == strcmp( signalName.c_str(), SIGNAL_IMAGE_LOADING_FINISHED ) )
+  {
+    image->LoadingFinishedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+const ImageAttributes& ResourceImage::GetAttributes() const
+{
+  if( mTicket )
+  {
+    return mImageFactory.GetActualAttributes( mTicket );
+  }
+  else
+  {
+    return mImageFactory.GetRequestAttributes( mRequest );
+  }
+}
+
+const std::string& ResourceImage::GetUrl() const
+{
+  return mImageFactory.GetRequestPath( mRequest );
+}
+
+void ResourceImage::Reload()
+{
+  if ( mRequest )
+  {
+    ResourceTicketPtr ticket = mImageFactory.Reload( *mRequest.Get() );
+    SetTicket( ticket.Get() );
+  }
+}
+
+unsigned int ResourceImage::GetWidth() const
+{
+  // if width is 0, it means we've not yet loaded the image
+  if( 0u == mWidth )
+  {
+    Size size;
+    mImageFactory.GetImageSize( mRequest, mTicket, size );
+    mWidth = size.width;
+    if( 0 == mHeight )
+    {
+      mHeight = size.height;
+    }
+  }
+  return mWidth;
+}
+
+unsigned int ResourceImage::GetHeight() const
+{
+  if( 0u == mHeight )
+  {
+    Size size;
+    mImageFactory.GetImageSize( mRequest, mTicket, size );
+    mHeight = size.height;
+    if( 0 == mWidth )
+    {
+      mWidth = size.width;
+    }
+  }
+  return mHeight;
+}
+
+Vector2 ResourceImage::GetNaturalSize() const
+{
+  Vector2 naturalSize(mWidth, mHeight);
+  if( 0u == mWidth || 0u == mHeight )
+  {
+    mImageFactory.GetImageSize( mRequest, mTicket, naturalSize );
+    mWidth = naturalSize.width;
+    mHeight = naturalSize.height;
+  }
+  return naturalSize;
+}
+
+void ResourceImage::ResourceLoadingFailed(const ResourceTicket& ticket)
+{
+  mLoadingFinished.Emit( Dali::ResourceImage( this ) );
+}
+
+void ResourceImage::ResourceLoadingSucceeded(const ResourceTicket& ticket)
+{
+  mLoadingFinished.Emit( Dali::ResourceImage( this ) );
+}
+
+void ResourceImage::Connect()
+{
+  ++mConnectionCount;
+
+  if( mConnectionCount == 1 )
+  {
+    // ticket was thrown away when related actors went offstage or image loading on demand
+    if( !mTicket )
+    {
+      DALI_ASSERT_DEBUG( mRequest.Get() );
+      ResourceTicketPtr newTicket = mImageFactory.Load( *mRequest.Get() );
+      SetTicket( newTicket.Get() );
+    }
+  }
+}
+
+void ResourceImage::Disconnect()
+{
+  if( !mTicket )
+  {
+    return;
+  }
+
+  DALI_ASSERT_DEBUG( mConnectionCount > 0 );
+  --mConnectionCount;
+  if( mConnectionCount == 0 && mReleasePolicy == Dali::ResourceImage::UNUSED )
+  {
+    // release image memory when it's not visible anymore (decrease ref. count of texture)
+    SetTicket( NULL );
+  }
+}
+
+bool ResourceImage::IsNinePatch( const std::string& url )
+{
+  bool match = false;
+
+  std::string::const_reverse_iterator iter = url.rbegin();
+  enum { SUFFIX, HASH, HASH_DOT, DONE } state = SUFFIX;
+  while(iter < url.rend())
+  {
+    switch(state)
+    {
+      case SUFFIX:
+      {
+        if(*iter == '.')
+        {
+          state = HASH;
+        }
+        else if(!isalnum(*iter))
+        {
+          state = DONE;
+        }
+      }
+      break;
+      case HASH:
+      {
+        if( *iter == '#' || *iter == '9' )
+        {
+          state = HASH_DOT;
+        }
+        else
+        {
+          state = DONE;
+        }
+      }
+      break;
+      case HASH_DOT:
+      {
+        if(*iter == '.')
+        {
+          match = true;
+        }
+        state = DONE; // Stop testing characters
+      }
+      break;
+      case DONE:
+      {
+      }
+      break;
+    }
+
+    // Satisfy prevent
+    if( state == DONE )
+    {
+      break;
+    }
+
+    ++iter;
+  }
+  return match;
+}
+
+void ResourceImage::SetTicket( ResourceTicket* ticket )
+{
+  if( ticket == mTicket.Get() )
+  {
+    return;
+  }
+
+  if( mTicket )
+  {
+    mTicket->RemoveObserver( *this );
+    mImageFactory.ReleaseTicket( mTicket.Get() );
+  }
+
+  if( ticket )
+  {
+    mTicket.Reset( ticket );
+    mTicket->AddObserver( *this );
+  }
+  else
+  {
+    mTicket.Reset();
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/images/resource-image-impl.h b/dali/internal/event/images/resource-image-impl.h
new file mode 100644 (file)
index 0000000..a537d3e
--- /dev/null
@@ -0,0 +1,220 @@
+#ifndef __DALI_INTERNAL_RESOURCE_IMAGE_H__
+#define __DALI_INTERNAL_RESOURCE_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/resource-image.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/images/image-factory-cache.h>
+#include <dali/integration-api/debug.h> // For DALI_LOG_OBJECT_STRING_DECLARATION
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Dali::ResourceImage::LoadPolicy LoadPolicy;
+
+const LoadPolicy IMAGE_LOAD_POLICY_DEFAULT = Dali::ResourceImage::IMMEDIATE;
+
+class ResourceImage;
+typedef IntrusivePtr<ResourceImage> ResourceImagePtr;
+
+/**
+ * ResourceImage is an image loaded using a URL, it is an image resource that can be added to actors etc.
+ */
+class ResourceImage : public Image
+{
+public:
+
+  /**
+   * Creates a pointer to an uninitialized Image object.
+   * @return a pointer to a newly created object.
+   */
+  static ResourceImagePtr New();
+
+  /**
+   * Creates object and loads image from filesystem
+   * the maximum size of the image is limited by GL_MAX_TEXTURE_SIZE
+   * @param [in] url The URL of the image file.
+   * @param [in] attributes requested parameters for loading (size, scaling etc.)
+   *                        if width or height is specified as 0, the natural size will be used.
+   * @param [in] loadPol controls time of loading a resource from the filesystem (default: load when Image is created).
+   * @param [in] releasePol optionally relase memory when image is not visible on screen (default: keep image data until Image object is alive).
+   * @return a pointer to a newly created object.
+   */
+  static ResourceImagePtr New( const std::string& url,
+                          const ImageAttributes& attributes,
+                          LoadPolicy loadPol = IMAGE_LOAD_POLICY_DEFAULT,
+                          ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+  /**
+   * @copydoc Dali::ResourceImage::GetLoadingState()
+   */
+  Dali::LoadingState GetLoadingState() const { return mTicket ? mTicket->GetLoadingState() : ResourceLoading; }
+
+  /**
+   * @copydoc Dali::ResourceImage::GetLoadPolicy()
+   */
+  LoadPolicy GetLoadPolicy () const { return mLoadPolicy; }
+
+  /**
+   * @copydoc Dali::ResourceImage::LoadingFinishedSignal()
+   */
+  Dali::ResourceImage::ResourceImageSignal& LoadingFinishedSignal() { return mLoadingFinished; }
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+  /**
+   * Get the attributes of the image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * Reflects the last cached values after a LoadComplete.
+   * If requested width or height was 0, they are replaced by concrete dimensions.
+   * @return a copy of the attributes
+   */
+  const ImageAttributes& GetAttributes() const;
+
+  /**
+   * @copydoc Dali::ResourceImage::GetUrl()
+   */
+  const std::string& GetUrl() const;
+
+  /**
+   * @copydoc Dali::ResourceImage::Reload()
+   */
+  void Reload();
+
+  /**
+   * @copydoc Dali::Image::GetWidth()
+   */
+  virtual unsigned int GetWidth() const;
+
+  /**
+   * @copydoc Dali::Image::GetWidth()
+   */
+  virtual unsigned int GetHeight() const;
+
+  /**
+   * @copydoc Dali::Internal::Image::GetNaturalSize()
+   */
+  virtual Vector2 GetNaturalSize() const;
+
+  /**
+   * Indicates that the image is used.
+   */
+  virtual void Connect();
+
+  /**
+   * Indicates that the image is not used anymore.
+   */
+  virtual void Disconnect();
+
+public: // From ResourceTicketObserver
+
+  /**
+   * @copydoc Dali::Internal::ResourceTicketObserver::ResourceLoadingFailed()
+   */
+  virtual void ResourceLoadingFailed(const ResourceTicket& ticket);
+
+  /**
+   * @copydoc Dali::Internal::ResourceTicketObserver::ResourceLoadingSucceeded()
+   */
+  virtual void ResourceLoadingSucceeded(const ResourceTicket& ticket);
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ResourceImage();
+
+  /**
+   * Constructor, with default parameters
+   */
+  ResourceImage( LoadPolicy loadPol = IMAGE_LOAD_POLICY_DEFAULT, ReleasePolicy releasePol = IMAGE_RELEASE_POLICY_DEFAULT );
+
+private:
+
+  /**
+   * Helper method to determine if the filename indicates that the image has a 9 patch border.
+   * @param [in] url The URL of the image file.
+   * @return true if it is a 9 patch image
+   */
+  static bool IsNinePatch( const std::string& url );
+
+  /**
+   * Helper method to set new resource ticket. Stops observing current ticket if any, and starts observing
+   * the new one or just resets the intrusive pointer.
+   * @param[in] ticket pointer to new resource Ticket or NULL.
+   */
+  void SetTicket( ResourceTicket* ticket );
+
+private:
+
+  ImageFactory& mImageFactory;
+
+  ImageFactoryCache::RequestPtr mRequest; ///< contains the initially requested attributes for image. Request is reissued when memory was released.
+
+  Dali::ResourceImage::ResourceImageSignal mLoadingFinished;
+
+  LoadPolicy mLoadPolicy : 2;    ///< 2 bits is enough space
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+} // namespace Internal
+
+/**
+ * Helper methods for public API.
+ */
+inline Internal::ResourceImage& GetImplementation(Dali::ResourceImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<Internal::ResourceImage&>(handle);
+}
+
+inline const Internal::ResourceImage& GetImplementation(const Dali::ResourceImage& image)
+{
+  DALI_ASSERT_ALWAYS( image && "Image handle is empty" );
+
+  const BaseObject& handle = image.GetBaseObject();
+
+  return static_cast<const Internal::ResourceImage&>(handle);
+}
+
+} // namespace Dali
+#endif // __DALI_INTERNAL_RESOURCE_IMAGE_H__
diff --git a/dali/internal/event/object/custom-object-internal.cpp b/dali/internal/event/object/custom-object-internal.cpp
new file mode 100644 (file)
index 0000000..bc19b73
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/object/custom-object-internal.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+
+using Dali::Internal::SceneGraph::PropertyOwner;
+using Dali::Internal::SceneGraph::PropertyBase;
+using Dali::Internal::SceneGraph::UpdateManager;
+using Dali::Internal::SceneGraph::AnimatableProperty;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CustomObject* CustomObject::New()
+{
+  return new CustomObject();
+}
+
+const SceneGraph::PropertyOwner* CustomObject::GetSceneObject() const
+{
+  return mUpdateObject;
+}
+
+const PropertyBase* CustomObject::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  CustomPropertyMetadata* custom = FindCustomProperty( index );
+  DALI_ASSERT_ALWAYS( custom && "Property index is invalid" );
+  return custom->GetSceneGraphProperty();
+}
+
+const PropertyInputImpl* CustomObject::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  return GetSceneObjectAnimatableProperty( index );
+}
+
+unsigned int CustomObject::GetDefaultPropertyCount() const
+{
+  return 0u;
+}
+
+void CustomObject::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+}
+
+const char* CustomObject::GetDefaultPropertyName( Property::Index index ) const
+{
+  return NULL;
+}
+
+Property::Index CustomObject::GetDefaultPropertyIndex(const std::string& name) const
+{
+  return Property::INVALID_INDEX;
+}
+
+bool CustomObject::IsDefaultPropertyWritable(Property::Index index) const
+{
+  return false;
+}
+
+bool CustomObject::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  return false;
+}
+
+bool CustomObject::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return false;
+}
+
+Property::Type CustomObject::GetDefaultPropertyType(Property::Index index) const
+{
+  return Property::NONE;
+}
+
+void CustomObject::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  // do nothing
+}
+
+Property::Value CustomObject::GetDefaultProperty(Property::Index index) const
+{
+  return Property::Value();
+}
+
+CustomObject::~CustomObject()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if( Stage::IsInstalled() )
+  {
+    if( NULL != mUpdateObject )
+    {
+      RemoveObjectMessage( GetEventThreadServices().GetUpdateManager(), mUpdateObject );
+      mUpdateObject = NULL; // object is about to be destroyed
+    }
+  }
+}
+
+CustomObject::CustomObject()
+{
+  PropertyOwner* updateObject = PropertyOwner::New();
+
+  // Pass ownership to the update-thread
+  AddObjectMessage( GetEventThreadServices().GetUpdateManager(), updateObject );
+
+  // Keep as const since this should only be modified from update-thread
+  mUpdateObject = updateObject;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/object/custom-object-internal.h b/dali/internal/event/object/custom-object-internal.h
new file mode 100644 (file)
index 0000000..17b0986
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef __DALI_INTERNAL_CUSTOM_OBJECT_H__
+#define __DALI_INTERNAL_CUSTOM_OBJECT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class PropertyOwner;
+}
+
+class CustomObject : public Object
+{
+public:
+
+  /**
+   * Create a new custom object.
+   * @return A pointer to the newly allocated object.
+   */
+  static CustomObject* New();
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~CustomObject();
+
+  /**
+   * Private constructor; see also CustomObject::New()
+   */
+  CustomObject();
+
+  // Undefined
+  CustomObject(const CustomObject&);
+
+  // Undefined
+  CustomObject& operator=(const CustomObject& rhs);
+
+protected:
+
+  SceneGraph::PropertyOwner* mUpdateObject;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CUSTOM_OBJECT_H__
diff --git a/dali/internal/event/render-tasks/render-task-defaults.h b/dali/internal/event/render-tasks/render-task-defaults.h
new file mode 100644 (file)
index 0000000..392f870
--- /dev/null
@@ -0,0 +1,61 @@
+#ifndef __DALI_INTERNAL_RENDER_TASK_DEFAULTS_H__
+#define __DALI_INTERNAL_RENDER_TASK_DEFAULTS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Actor;
+class CameraActor;
+
+/**
+ * An interface for retrieving render-tasks defaults
+ */
+class RenderTaskDefaults
+{
+public:
+
+  /**
+   * Retrieve the default root actor.
+   * @return The default root actor.
+   */
+  virtual Actor& GetDefaultRootActor() = 0;
+
+  /**
+   * Retrieve the default camera actor.
+   * @return The default camera actor.
+   */
+  virtual CameraActor& GetDefaultCameraActor() = 0;
+
+protected:
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~RenderTaskDefaults(){}
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_RENDER_TASK_DEFAULTS_H__
diff --git a/dali/internal/event/render-tasks/render-task-impl.cpp b/dali/internal/event/render-tasks/render-task-impl.cpp
new file mode 100644 (file)
index 0000000..a64d4ea
--- /dev/null
@@ -0,0 +1,827 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for strcmp
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/common/property-helper.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+
+#if defined(DEBUG_ENABLED)
+namespace
+{
+Debug::Filter* gLogRender = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK");
+}
+#endif
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // For internal properties
+{
+
+// Properties
+
+//              Name                 Type     writable animatable constraint-input  enum for index-checking
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "viewport-position",  VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_POSITION )
+DALI_PROPERTY( "viewport-size",      VECTOR2,    true,    true,    true,    Dali::RenderTask::Property::VIEWPORT_SIZE     )
+DALI_PROPERTY( "clear-color",        VECTOR4,    true,    true,    true,    Dali::RenderTask::Property::CLEAR_COLOR       )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+// Signals
+
+const char* const SIGNAL_FINISHED = "finished";
+
+TypeRegistration mType( typeid( Dali::RenderTask ), typeid( Dali::BaseHandle ), NULL );
+
+SignalConnectorType signalConnector1( mType, SIGNAL_FINISHED, &RenderTask::DoConnectSignal );
+
+} // Unnamed namespace
+
+RenderTask* RenderTask::New( bool isSystemLevel )
+{
+  RenderTask* task( new RenderTask( isSystemLevel ) );
+
+  return task;
+}
+
+void RenderTask::SetSourceActor( Actor* actor )
+{
+  const Stage* stage = Stage::GetCurrent();
+  if ( stage )
+  {
+    stage->GetRenderTaskList().SetExclusive( this, mExclusive );
+  }
+  mSourceConnector.SetActor( actor );
+}
+
+Actor* RenderTask::GetSourceActor() const
+{
+  return mSourceConnector.mActor;
+}
+
+void RenderTask::SetExclusive( bool exclusive )
+{
+  if ( mExclusive != exclusive )
+  {
+    mExclusive = exclusive;
+
+    const Stage* stage = Stage::GetCurrent();
+    if ( stage )
+    {
+      stage->GetRenderTaskList().SetExclusive( this, exclusive );
+    }
+
+    if ( mSceneObject )
+    {
+      // mSceneObject is being used in a separate thread; queue a message to set the value
+      SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
+    }
+  }
+}
+
+bool RenderTask::IsExclusive() const
+{
+  return mExclusive;
+}
+
+void RenderTask::SetInputEnabled( bool enabled )
+{
+  mInputEnabled = enabled;
+}
+
+bool RenderTask::GetInputEnabled() const
+{
+  return mInputEnabled;
+}
+
+void RenderTask::SetCameraActor( CameraActor* cameraActor )
+{
+  mCameraConnector.SetActor( cameraActor );
+}
+
+CameraActor* RenderTask::GetCameraActor() const
+{
+  // camera connector can only point to camera actor
+  return static_cast< CameraActor* >( mCameraConnector.mActor );
+}
+
+void RenderTask::SetTargetFrameBuffer( Dali::FrameBufferImage image )
+{
+  if ( mFrameBufferImage != image )
+  {
+    // if we have a scene object we need to track connection status and set frame buffer id as well as updating target frame buffer
+    if ( mSceneObject )
+    {
+      if(mFrameBufferImage)
+      {
+        GetImplementation(mFrameBufferImage).Disconnect();
+      }
+
+      // update target frame buffer
+      mFrameBufferImage = image;
+
+      unsigned int resourceId = 0;
+      if(mFrameBufferImage)
+      {
+        GetImplementation(mFrameBufferImage).Connect();
+
+        resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
+      }
+
+      // mSceneObject is being used in a separate thread; queue a message to set the value
+      SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+    }
+    else
+    {
+      // update target frame buffer
+      mFrameBufferImage = image;
+    }
+  }
+}
+
+Dali::FrameBufferImage RenderTask::GetTargetFrameBuffer() const
+{
+  return mFrameBufferImage;
+}
+
+void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
+{
+  mScreenToFrameBufferFunction = conversionFunction;
+}
+
+RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
+{
+  return mScreenToFrameBufferFunction;
+}
+
+void RenderTask::SetScreenToFrameBufferMappingActor( Actor* mappingActor )
+{
+  mMappingConnector.SetActor( mappingActor );
+}
+
+Actor* RenderTask::GetScreenToFrameBufferMappingActor() const
+{
+  return mMappingConnector.mActor;
+}
+
+void RenderTask::SetViewportPosition(const Vector2& value)
+{
+  BakeViewportPositionMessage( GetEventThreadServices(), *mSceneObject, value );
+}
+
+Vector2 RenderTask::GetCurrentViewportPosition() const
+{
+  return mSceneObject->GetViewportPosition( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+void RenderTask::SetViewportSize(const Vector2& value)
+{
+  BakeViewportSizeMessage( GetEventThreadServices(), *mSceneObject, value );
+}
+
+Vector2 RenderTask::GetCurrentViewportSize() const
+{
+  return mSceneObject->GetViewportSize( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+void RenderTask::SetViewport( const Viewport& viewport )
+{
+  SetViewportPosition(Vector2(viewport.x, viewport.y));
+  SetViewportSize(Vector2(viewport.width, viewport.height));
+}
+
+void RenderTask::GetViewport( Viewport& viewPort ) const
+{
+  BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
+
+  if(!mSceneObject->GetViewportEnabled( bufferIndex ))
+  {
+    if ( mFrameBufferImage )
+    {
+      viewPort.x = viewPort.y = 0;
+      viewPort.width = mFrameBufferImage.GetWidth();
+      viewPort.height = mFrameBufferImage.GetHeight();
+    }
+    else
+    {
+      Internal::Stage* stage = Internal::Stage::GetCurrent();
+      if ( stage )
+      {
+        Vector2 size( stage->GetSize() );
+        viewPort.x = viewPort.y = 0;
+        viewPort.width = size.width;
+        viewPort.height = size.height;
+      }
+    }
+  }
+  else
+  {
+    const Vector2& position = mSceneObject->GetViewportPosition(bufferIndex);
+    const Vector2& size = mSceneObject->GetViewportSize(bufferIndex);
+    viewPort.x = position.x;
+    viewPort.y = position.y;
+    viewPort.width = size.width;
+    viewPort.height = size.height;
+  }
+}
+
+void RenderTask::SetClearColor( const Vector4& color )
+{
+  if ( mClearColor != color )
+  {
+    mClearColor = color;
+
+    if ( mSceneObject )
+    {
+      // mSceneObject is being used in a separate thread; queue a message to set the value
+      BakeClearColorMessage( GetEventThreadServices(), *mSceneObject, color );
+    }
+  }
+}
+
+const Vector4& RenderTask::GetClearColor() const
+{
+  return mSceneObject->GetClearColor( GetEventThreadServices().GetEventBufferIndex() );
+}
+
+void RenderTask::SetClearEnabled( bool enabled )
+{
+  if ( mClearEnabled != enabled )
+  {
+    mClearEnabled = enabled;
+
+    if ( mSceneObject )
+    {
+      // mSceneObject is being used in a separate thread; queue a message to set the value
+      SetClearEnabledMessage( GetEventThreadServices(), *mSceneObject, mClearEnabled );
+    }
+  }
+}
+
+bool RenderTask::GetClearEnabled() const
+{
+  return mClearEnabled;
+}
+
+void RenderTask::SetCullMode( bool mode )
+{
+  if ( mCullMode != mode )
+  {
+    mCullMode = mode;
+
+    if ( mSceneObject )
+    {
+      // mSceneObject is being used in a separate thread; queue a message to set the value
+      SetCullModeMessage( GetEventThreadServices(), *mSceneObject, mCullMode );
+    }
+  }
+}
+
+bool RenderTask::GetCullMode() const
+{
+  return mCullMode;
+}
+
+void RenderTask::SetRefreshRate( unsigned int refreshRate )
+{
+  DALI_LOG_TRACE_METHOD_FMT(gLogRender, "this:%p  rate:%d\n", this, refreshRate);
+  DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::SetRefreshRate(this:%p, %d)\n", this, refreshRate);
+
+  mRefreshRate = refreshRate; // cached for GetRefreshRate()
+
+  // Note - even when refreshRate is the same as mRefreshRate, a message should be sent
+
+  if ( mSceneObject )
+  {
+    // mSceneObject is being used in a separate thread; queue a message to set the value
+    SetRefreshRateMessage( GetEventThreadServices(), *mSceneObject, refreshRate );
+  }
+}
+
+unsigned int RenderTask::GetRefreshRate() const
+{
+  return mRefreshRate;
+}
+
+bool RenderTask::IsHittable( Vector2& screenCoords ) const
+{
+  // True when input is enabled, source & camera actor are valid
+  bool inputEnabled( false );
+
+  Actor* sourceActor = GetSourceActor();
+  CameraActor* cameraActor = GetCameraActor();
+
+  if ( mInputEnabled  &&
+       NULL != sourceActor    &&
+       sourceActor->OnStage() &&
+       NULL != cameraActor    &&
+       cameraActor->OnStage() )
+  {
+    // If the actors are rendered off-screen, then the screen coordinates must be converted
+    // and the conversion function will tell us if they are inside or outside
+    if ( TranslateCoordinates( screenCoords ) )
+    {
+      // This is a suitable render-task for input handling
+      inputEnabled = true;
+    }
+  }
+
+  return inputEnabled;
+}
+
+bool RenderTask::TranslateCoordinates( Vector2& screenCoords ) const
+{
+  // return true for on-screen tasks
+  bool inside( true );
+  // If the actors are rendered off-screen, then the screen coordinates must be converted
+  // the function should only be called for offscreen tasks
+  if( mFrameBufferImage && mMappingConnector.mActor )
+  {
+    CameraActor* localCamera = GetCameraActor();
+    StagePtr stage = Stage::GetCurrent();
+    if( stage )
+    {
+      CameraActor& defaultCamera = stage->GetDefaultCameraActor();
+      if( localCamera )
+      {
+        Viewport viewport;
+        Vector2 size( stage->GetSize() );
+        viewport.x = viewport.y = 0;
+        viewport.width = size.width;
+        viewport.height = size.height;
+
+        float localX, localY;
+        inside = mMappingConnector.mActor->ScreenToLocal(defaultCamera.GetViewMatrix(), defaultCamera.GetProjectionMatrix(), viewport, localX, localY, screenCoords.x, screenCoords.y);
+        Vector3 actorSize = mMappingConnector.mActor->GetCurrentSize();
+        if( inside && localX >= 0.f && localX <= actorSize.x && localY >= 0.f && localY <= actorSize.y)
+        {
+          screenCoords.x = localX;
+          screenCoords.y = localY;
+        }
+        else
+        {
+          inside = false;
+        }
+      }
+      else
+      {
+        inside = false;
+      }
+    }
+  }
+  else if ( mFrameBufferImage && mScreenToFrameBufferFunction )
+  {
+    inside = mScreenToFrameBufferFunction( screenCoords );
+  }
+  return inside;
+}
+
+bool RenderTask::IsSystemLevel() const
+{
+  return mIsSystemLevel;
+}
+
+SceneGraph::RenderTask* RenderTask::CreateSceneObject()
+{
+  // This should only be called once, with no existing scene-object
+  DALI_ASSERT_DEBUG( NULL == mSceneObject );
+
+  // Keep the raw-pointer until DiscardSceneObject is called
+  mSceneObject = SceneGraph::RenderTask::New();
+
+  // if we have a frame buffer we need to track connection status then send a message to set the frame buffer id in case it has changed since last time we were on stage
+  unsigned int resourceId = 0;
+  if(mFrameBufferImage)
+  {
+    GetImplementation(mFrameBufferImage).Connect();
+
+    resourceId = GetImplementation( mFrameBufferImage ).GetResourceId();
+  }
+
+  // mSceneObject is being used in a separate thread; queue a message to set the value
+  SetFrameBufferIdMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+
+  // Send messages to set other properties that may have changed since last time we were on stage
+  SetExclusiveMessage( GetEventThreadServices(), *mSceneObject, mExclusive );
+  SetClearColorMessage(  GetEventThreadServices(), *mSceneObject, mClearColor );
+  SetClearEnabledMessage(  GetEventThreadServices(), *mSceneObject, mClearEnabled );
+  SetCullModeMessage(  GetEventThreadServices(), *mSceneObject, mCullMode );
+  SetRefreshRateMessage(  GetEventThreadServices(), *mSceneObject, mRefreshRate );
+
+  // Caller takes ownership
+  return mSceneObject;
+}
+
+SceneGraph::RenderTask* RenderTask::GetRenderTaskSceneObject()
+{
+  return mSceneObject;
+}
+
+void RenderTask::DiscardSceneObject()
+{
+  // mSceneObject is not owned; throw away the raw-pointer
+  mSceneObject = NULL;
+
+  // if we have a frame buffer we need to track connection status
+  if(mFrameBufferImage)
+  {
+    GetImplementation(mFrameBufferImage).Disconnect();
+  }
+}
+
+/********************************************************************************
+ ********************************   PROPERTY METHODS   **************************
+ ********************************************************************************/
+
+unsigned int RenderTask::GetDefaultPropertyCount() const
+{
+  return DEFAULT_PROPERTY_COUNT;
+}
+
+void RenderTask::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Reserve( DEFAULT_PROPERTY_COUNT );
+
+  for ( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    indices.PushBack( i );
+  }
+}
+
+const char* RenderTask::GetDefaultPropertyName( Property::Index index ) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].name;
+  }
+  else
+  {
+    return NULL;
+  }
+}
+
+Property::Index RenderTask::GetDefaultPropertyIndex(const std::string& name) const
+{
+  Property::Index index = Property::INVALID_INDEX;
+
+  // Look for name in default properties
+  for( int i = 0; i < DEFAULT_PROPERTY_COUNT; ++i )
+  {
+    if( 0 == strcmp( name.c_str(), DEFAULT_PROPERTY_DETAILS[i].name ) ) // dont want to convert rhs to string
+    {
+      index = i;
+      break;
+    }
+  }
+
+  return index;
+}
+
+bool RenderTask::IsDefaultPropertyWritable(Property::Index index) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].writable;
+}
+
+bool RenderTask::IsDefaultPropertyAnimatable(Property::Index index) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].animatable;
+}
+
+bool RenderTask::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return DEFAULT_PROPERTY_DETAILS[ index ].constraintInput;
+}
+
+Property::Type RenderTask::GetDefaultPropertyType(Property::Index index) const
+{
+  if( index < DEFAULT_PROPERTY_COUNT )
+  {
+    return DEFAULT_PROPERTY_DETAILS[index].type;
+  }
+
+  // index out of range...return Property::NONE
+  return Property::NONE;
+}
+
+void RenderTask::SetDefaultProperty( Property::Index index, const Property::Value& property )
+{
+  switch ( index )
+  {
+    case Dali::RenderTask::Property::VIEWPORT_POSITION:
+    {
+      SetViewportPosition( property.Get<Vector2>() );
+      break;
+    }
+    case Dali::RenderTask::Property::VIEWPORT_SIZE:
+    {
+      SetViewportSize( property.Get<Vector2>() );
+      break;
+    }
+    case Dali::RenderTask::Property::CLEAR_COLOR:
+    {
+      SetClearColor( property.Get<Vector4>() );
+      break;
+    }
+    default:
+    {
+      // nothing to do
+      break;
+    }
+  }
+}
+
+Property::Value RenderTask::GetDefaultProperty(Property::Index index) const
+{
+  Property::Value value;
+
+  switch ( index )
+  {
+
+    case Dali::RenderTask::Property::VIEWPORT_POSITION:
+    {
+      value = GetCurrentViewportPosition();
+      break;
+    }
+    case Dali::RenderTask::Property::VIEWPORT_SIZE:
+    {
+      value = GetCurrentViewportSize();
+      break;
+    }
+    case Dali::RenderTask::Property::CLEAR_COLOR:
+    {
+      value = GetClearColor();
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS(false && "RenderTask property index out of range"); // should not come here
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* RenderTask::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* RenderTask::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
+
+  const SceneGraph::PropertyBase* property( NULL );
+
+  // This method should only return a property which is part of the scene-graph
+  if( mSceneObject != NULL )
+  {
+    switch ( index )
+    {
+      case Dali::RenderTask::Property::VIEWPORT_POSITION:
+        property = &mSceneObject->mViewportPosition;
+        break;
+
+      case Dali::RenderTask::Property::VIEWPORT_SIZE:
+        property = &mSceneObject->mViewportSize;
+        break;
+
+      case Dali::RenderTask::Property::CLEAR_COLOR:
+        property = &mSceneObject->mClearColor;
+        break;
+
+      default:
+        break;
+    }
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* RenderTask::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property( NULL );
+  if( mSceneObject != NULL )
+  {
+    switch ( index )
+    {
+      case Dali::RenderTask::Property::VIEWPORT_POSITION:
+        property = &mSceneObject->mViewportPosition;
+        break;
+
+      case Dali::RenderTask::Property::VIEWPORT_SIZE:
+        property = &mSceneObject->mViewportSize;
+        break;
+
+      case Dali::RenderTask::Property::CLEAR_COLOR:
+        property = &mSceneObject->mViewportSize;
+        break;
+
+      default:
+        break;
+    }
+  }
+
+  return property;
+}
+
+bool RenderTask::HasFinished()
+{
+  bool finished = false;
+  const unsigned int counter = mSceneObject->GetRenderedOnceCounter();
+
+  if( mRefreshOnceCounter < counter )
+  {
+    finished = true;
+    mRefreshOnceCounter = counter;
+  }
+
+  DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::HasFinished()=%s SCRT:%p  SC\n", finished?"T":"F", mSceneObject);
+
+  return finished;
+}
+
+void RenderTask::EmitSignalFinish()
+{
+  DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::EmitSignalFinish(this:%p)\n", this);
+
+  if( !mSignalFinished.Empty() )
+  {
+    Dali::RenderTask handle( this );
+    mSignalFinished.Emit(handle );
+  }
+}
+
+Dali::RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
+{
+  return mSignalFinished;
+}
+
+bool RenderTask::DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  bool connected( true );
+  RenderTask* renderTask = dynamic_cast<RenderTask*>(object);
+
+  if ( 0 == strcmp( signalName.c_str(), SIGNAL_FINISHED ) )
+  {
+    renderTask->FinishedSignal().Connect( tracker, functor );
+  }
+  else
+  {
+    // signalName does not match any signal
+    connected = false;
+  }
+
+  return connected;
+}
+
+RenderTask::RenderTask( bool isSystemLevel )
+: mSceneObject( NULL ),
+  mSourceConnector( Connector::SOURCE_CONNECTOR, *this ),
+  mCameraConnector( Connector::CAMERA_CONNECTOR, *this ),
+  mMappingConnector( Connector::MAPPING_CONNECTOR, *this  ),
+  mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
+  mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
+  mRefreshOnceCounter( 0u ),
+  mScreenToFrameBufferFunction( Dali::RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION ),
+  mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
+  mInputEnabled( Dali::RenderTask::DEFAULT_INPUT_ENABLED ),
+  mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
+  mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
+  mIsSystemLevel( isSystemLevel )
+{
+  DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::RenderTask(this:%p)\n", this);
+}
+
+RenderTask::~RenderTask()
+{
+  DALI_LOG_INFO(gLogRender, Debug::General, "RenderTask::~RenderTask(this:%p)\n", this);
+}
+
+// Helper class for connecting Nodes to the scene-graph RenderTask
+
+RenderTask::Connector::Connector( Type type, RenderTask& renderTask )
+: mType( type ),
+  mRenderTask( renderTask ),
+  mActor( NULL )
+{
+}
+
+RenderTask::Connector::~Connector()
+{
+  SetActor( NULL );
+}
+
+void RenderTask::Connector::SetActor( Actor* actor )
+{
+  if ( mActor != actor )
+  {
+    if ( mActor )
+    {
+      mActor->RemoveObserver( *this );
+    }
+
+    mActor = actor;
+
+    if ( mActor )
+    {
+      mActor->AddObserver( *this );
+    }
+
+    UpdateRenderTask();
+  }
+}
+
+void RenderTask::Connector::SceneObjectAdded( Object& object )
+{
+  UpdateRenderTask();
+}
+
+void RenderTask::Connector::SceneObjectRemoved( Object& object )
+{
+  UpdateRenderTask();
+}
+
+void RenderTask::Connector::ObjectDestroyed( Object& object )
+{
+  if ( SOURCE_CONNECTOR == mType )
+  {
+    const Stage* stage = Stage::GetCurrent();
+    if ( stage )
+    {
+      stage->GetRenderTaskList().SetExclusive( &mRenderTask, false );
+    }
+  }
+
+  mActor = NULL;
+
+  UpdateRenderTask();
+}
+
+void RenderTask::Connector::UpdateRenderTask()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if( Internal::Stage::IsInstalled() &&
+      mRenderTask.mSceneObject )
+  {
+    const SceneGraph::Node* node( NULL );
+
+    // Check whether a Node exists in the scene-graph
+    if ( NULL != mActor )
+    {
+      const SceneGraph::PropertyOwner* object = mActor->GetSceneObject();
+      if ( NULL != object )
+      {
+        // actors only point to nodes as their scene objects
+        node = static_cast< const SceneGraph::Node* >( object );
+      }
+    }
+
+    //the mapping node is not used in the scene graph
+    if ( SOURCE_CONNECTOR == mType )
+    {
+      SetSourceNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
+    }
+    else if( CAMERA_CONNECTOR == mType )
+    {
+      SetCameraNodeMessage( mRenderTask.GetEventThreadServices(), *(mRenderTask.mSceneObject), node );
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/render-tasks/render-task-impl.h b/dali/internal/event/render-tasks/render-task-impl.h
new file mode 100644 (file)
index 0000000..bc7c942
--- /dev/null
@@ -0,0 +1,467 @@
+#ifndef __DALI_INTERNAL_RENDER_TASK_H__
+#define __DALI_INTERNAL_RENDER_TASK_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/internal/event/common/object-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Actor;
+class CameraActor;
+class EventThreadServices;
+
+namespace SceneGraph
+{
+class RenderTask;
+}
+
+class RenderTask : public Object
+{
+public:
+
+  typedef Dali::RenderTask::ScreenToFrameBufferFunction ScreenToFrameBufferFunction;
+
+  /**
+   * Creates a new RenderTask.
+   * @param[in] isSystemLevel Whether the render-task is on the system level task list.
+   */
+  static RenderTask* New( bool isSystemLevel );
+
+  /**
+   * @copydoc Dali::RenderTask::SetSourceActor()
+   */
+  void SetSourceActor( Actor* actor );
+
+  /**
+   * @copydoc Dali::RenderTask::GetSourceActor()
+   */
+  Actor* GetSourceActor() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetExclusive()
+   */
+  void SetExclusive( bool exclusive );
+
+  /**
+   * @copydoc Dali::RenderTask::IsExclusive()
+   */
+  bool IsExclusive() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetInputEnabled()
+   */
+  void SetInputEnabled( bool enabled );
+
+  /**
+   * @copydoc Dali::RenderTask::GetInputEnabled()
+   */
+  bool GetInputEnabled() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetCameraActor()
+   */
+  void SetCameraActor( CameraActor* cameraActor );
+
+  /**
+   * @copydoc Dali::RenderTask::GetCameraActor()
+   */
+  CameraActor* GetCameraActor() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetTargetFrameBuffer()
+   */
+  void SetTargetFrameBuffer( Dali::FrameBufferImage frameBuffer );
+
+  /**
+   * @copydoc Dali::RenderTask::GetTargetFrameBuffer
+   */
+  Dali::FrameBufferImage GetTargetFrameBuffer() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetScreenToFrameBufferFunction
+   */
+  void SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction );
+
+  /**
+   * @copydoc Dali::RenderTask::GetScreenToFrameBufferFunction
+   */
+  ScreenToFrameBufferFunction GetScreenToFrameBufferFunction() const;
+
+  /**
+   * copydoc Dali::RenderTask::SetScreenToFrameBufferMappingActor
+   */
+  void SetScreenToFrameBufferMappingActor( Actor* mappingActor );
+
+  /**
+   * copydoc Dali::RenderTask::GetScreenToFrameBufferMAppingActor
+   */
+  Actor* GetScreenToFrameBufferMappingActor() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetViewportPosition
+   */
+  void SetViewportPosition(const Vector2& value);
+
+  /**
+   * @copydoc Dali::RenderTask::GetCurrentViewportPosition
+   */
+  Vector2 GetCurrentViewportPosition() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetViewportSize
+   */
+  void SetViewportSize(const Vector2& value);
+
+  /**
+   * @copydoc Dali::RenderTask::GetCurrentViewportSize
+   */
+  Vector2 GetCurrentViewportSize() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetViewport()
+   */
+  void SetViewport( const Viewport& viewport );
+
+  /**
+   * @param[out] viewPort instance to copy the values into
+   */
+  void GetViewport( Viewport& viewPort ) const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetClearColor()
+   */
+  void SetClearColor( const Vector4& color );
+
+  /**
+   * @copydoc Dali::RenderTask::GetClearColor()
+   */
+  const Vector4& GetClearColor() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetClearEnabled()
+   */
+  void SetClearEnabled( bool enabled );
+
+  /**
+   * @copydoc Dali::RenderTask::GetClearEnabled()
+   */
+  bool GetClearEnabled() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetCullMode()
+   */
+  void SetCullMode( bool mode );
+
+  /**
+   * @copydoc Dali::RenderTask::GetCullMode()
+   */
+  bool GetCullMode() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetRefreshRate()
+   */
+  void SetRefreshRate( unsigned int refreshRate );
+
+  /**
+   * @copydoc Dali::RenderTask::GetRefreshRate()
+   */
+  unsigned int GetRefreshRate() const;
+
+  /**
+   * Check if the render-task is hittable. If render task is offscreen, the screen coordinates may be translated.
+   * @param[in,out] screenCoords The screen coordinate, which may be converted (for hit-testing actors which are rendered off-screen).
+   * @return True the render-task can be used for input-handling; otherwise the output parameters are not valid.
+   */
+  bool IsHittable( Vector2& screenCoords ) const;
+
+  /**
+   * Translates screen coordinates to render task coordinates for offscreen render tasks
+   * @param[in,out] screenCoords The screen coordinates, which may be converted (for off-screen).
+   * @return false if the conversion function decides the coordinates are not inside. returns true if there is no conversion function
+   */
+  bool TranslateCoordinates( Vector2& screenCoords ) const;
+
+  /**
+   * Query whether the RenderTask is on the system level render-task list.
+   * @return true, if on the system level task list, false otherwise.
+   */
+  bool IsSystemLevel() const;
+
+public: // Used by RenderTaskList, which owns the SceneGraph::RenderTasks
+
+  /**
+   * Create the scene-graph RenderTask object.
+   * @pre CreateSceneObject has not already been called.
+   * @return A newly allocated scene-graph object; the caller takes ownership.
+   */
+  SceneGraph::RenderTask* CreateSceneObject();
+
+  /**
+   * Retrieve the scene-graph RenderTask object.
+   * @return The scene-graph object, or NULL if this has been discarded.
+   */
+  SceneGraph::RenderTask* GetRenderTaskSceneObject();
+
+  /**
+   * Discard the scene-graph RenderTask object.
+   */
+  void DiscardSceneObject();
+
+public: // Implementation of Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+public: //signals
+
+  /**
+   * Query whether a Finished signal should be emitted for this render-task.
+   * This should only be called by NotificationManager, before signals are emitted.
+   * @pre The refresh rate must be REFRESH_ONCE.
+   * @post HasFinished() will return false on subsequent calls, until the render-task is processed again.
+   * @return \e true if the refresh once render task has finished. Otherwise it returns \e false.
+   */
+  bool HasFinished();
+
+  /**
+   * Emit the Finished signal
+   */
+  void EmitSignalFinish();
+
+  /**
+   * @copydoc Dali::RenderTask::FinishedSignal()
+   */
+  Dali::RenderTask::RenderTaskSignalType& FinishedSignal();
+
+  /**
+   * Connects a callback function with the object's signals.
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  static bool DoConnectSignal( BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor );
+
+protected:
+
+  /**
+   * Construct a new RenderTask.
+   * @param[in] isSystemLevel Whether the RenderTask is on the system level task list.
+   */
+  RenderTask( bool isSystemLevel );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~RenderTask();
+
+  /**
+   * Helper class for connecting Nodes to the scene-graph RenderTask
+   */
+  class Connector : public Object::Observer
+  {
+  public:
+
+    enum Type
+    {
+      SOURCE_CONNECTOR,
+      CAMERA_CONNECTOR,
+      MAPPING_CONNECTOR
+    };
+
+    /**
+     * Create the helper class
+     */
+    Connector( Type type, RenderTask& renderTask );
+
+    /**
+     * Non-virtual destructor; not suitable as a base object.
+     */
+    ~Connector();
+
+    /**
+     * Set the actor to be observed.
+     * @param[in] actor The actor to be observed.
+     */
+    void SetActor( Actor* actor );
+
+    /**
+     * Update the scene-graph RenderTask with a new source/camera Node.
+     */
+    void UpdateRenderTask();
+
+  public: // From Object::Observer
+
+    /**
+     * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded
+     */
+    virtual void SceneObjectAdded( Object& object );
+
+    /**
+     * @copydoc Dali::Internal::Object::Observer::SceneObjectAdded
+     */
+    virtual void SceneObjectRemoved( Object& object );
+
+    /**
+     * @copydoc Dali::Internal::Object::Observer::ObjectDestroyed
+     */
+    virtual void ObjectDestroyed( Object& object );
+
+  private:
+
+    // Undefined
+    Connector(const Connector&);
+
+    // Undefined
+    Connector& operator=(const Connector& rhs);
+
+  public:
+
+    const Type mType;
+
+    RenderTask& mRenderTask;
+
+    Actor* mActor; ///< Raw-pointer to the actor; not owned.
+  };
+
+private:
+
+  SceneGraph::RenderTask* mSceneObject; ///< Raw-pointer to the scene-graph object; not owned.
+
+  Connector mSourceConnector; ///< Responsible for connecting/disconnecting source Nodes
+  Connector mCameraConnector; ///< Responsible for connecting/disconnecting camera Nodes
+  Connector mMappingConnector; /// Responsible for connecting/disconnection actor node, which used to mapping screen to frame buffer coordinate
+
+  Vector4 mClearColor;       ///< Optional clear color
+
+  unsigned int mRefreshRate; ///< Determines how often the task is processed.
+
+  unsigned int mRefreshOnceCounter;
+
+  Dali::FrameBufferImage mFrameBufferImage;  ///< Optional off-screen render target.
+
+  Dali::RenderTask::ScreenToFrameBufferFunction mScreenToFrameBufferFunction; ///< Used to convert screen to frame-buffer coordinates
+
+  bool mExclusive     : 1; ///< True if the render-task has exclusive access to the source Nodes.
+  bool mInputEnabled  : 1; ///< True if the render-task should be considered for input handling.
+  bool mClearEnabled  : 1; ///< True if the render-task should be clear the color buffer.
+  bool mCullMode      : 1; ///< True if the render-task's actors should be culled
+  bool mIsSystemLevel : 1; ///< True if the render-task is on the system level task list.
+
+  //Signals
+  Dali::RenderTask::RenderTaskSignalType  mSignalFinished; ///< Signal emmited when the render task has been processed.
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::RenderTask& GetImplementation(Dali::RenderTask& task)
+{
+  DALI_ASSERT_ALWAYS(task && "RenderTask handle is empty");
+
+  BaseObject& handle = task.GetBaseObject();
+
+  return static_cast<Internal::RenderTask&>(handle);
+}
+
+inline const Internal::RenderTask& GetImplementation(const Dali::RenderTask& task)
+{
+  DALI_ASSERT_ALWAYS(task && "RenderTask handle is empty");
+
+  const BaseObject& handle = task.GetBaseObject();
+
+  return static_cast<const Internal::RenderTask&>(handle);
+}
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_RENDER_TASK_H__
diff --git a/dali/internal/event/render-tasks/render-task-list-impl.cpp b/dali/internal/event/render-tasks/render-task-list-impl.cpp
new file mode 100644 (file)
index 0000000..e7da30b
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/render-tasks/render-task-defaults.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+using Dali::Internal::SceneGraph::UpdateManager;
+
+#if defined(DEBUG_ENABLED)
+namespace
+{
+Debug::Filter* gLogRenderList = Debug::Filter::New(Debug::Concise, false, "LOG_RENDER_TASK_LIST");
+}
+#endif
+
+namespace Dali
+{
+namespace Internal
+{
+
+RenderTaskList* RenderTaskList::New( EventThreadServices& eventServices, RenderTaskDefaults& defaults, bool systemLevel )
+{
+  RenderTaskList* taskList = new RenderTaskList( eventServices, defaults, systemLevel );
+
+  taskList->Initialize( eventServices.GetUpdateManager() );
+
+  return taskList;
+}
+
+Dali::RenderTask RenderTaskList::CreateTask()
+{
+  RenderTask* taskImpl = RenderTask::New( mIsSystemLevel );
+
+  Dali::RenderTask newTask( taskImpl );
+  mTasks.push_back( newTask );
+
+  if ( mSceneObject )
+  {
+    SceneGraph::RenderTask* sceneObject = taskImpl->CreateSceneObject();
+    DALI_ASSERT_DEBUG( NULL != sceneObject );
+
+    // Pass ownership to SceneGraph::RenderTaskList
+    AddTaskMessage( mEventThreadServices, *mSceneObject, *sceneObject );
+  }
+
+  // Set the default source & camera actors
+  taskImpl->SetSourceActor( &mDefaults.GetDefaultRootActor() );
+  taskImpl->SetCameraActor( &mDefaults.GetDefaultCameraActor() );
+
+  return newTask;
+}
+
+void RenderTaskList::RemoveTask( Dali::RenderTask task )
+{
+  for ( RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter )
+  {
+    if ( *iter == task )
+    {
+      RenderTask& taskImpl = GetImplementation( task );
+      if ( mSceneObject )
+      {
+        SceneGraph::RenderTask* sceneObject = taskImpl.GetRenderTaskSceneObject();
+        DALI_ASSERT_DEBUG( NULL != sceneObject );
+
+        // Send a message to remove the scene-graph RenderTask
+        RemoveTaskMessage( mEventThreadServices, *mSceneObject, *sceneObject );
+
+        // The scene-graph RenderTask will be destroyed soon; discard the raw-pointer
+        taskImpl.DiscardSceneObject();
+      }
+
+      mTasks.erase( iter );
+
+      for ( Vector< Exclusive >::Iterator exclusiveIt = mExclusives.Begin(); exclusiveIt != mExclusives.End(); ++exclusiveIt )
+      {
+        if ( exclusiveIt->renderTaskPtr == &taskImpl )
+        {
+          mExclusives.Erase( exclusiveIt );
+          break;
+        }
+      }
+      break; // we're finished
+    }
+  }
+}
+
+unsigned int RenderTaskList::GetTaskCount() const
+{
+  return mTasks.size();
+}
+
+Dali::RenderTask RenderTaskList::GetTask( unsigned int index ) const
+{
+  DALI_ASSERT_ALWAYS( ( index < mTasks.size() ) && "RenderTask index out-of-range" );
+
+  return mTasks[index];
+}
+
+void RenderTaskList::SetExclusive( RenderTask* task, bool exclusive )
+{
+  // Check to see if this rendertask has an entry?
+  for ( Vector< Exclusive >::Iterator exclusiveIt = mExclusives.Begin(); exclusiveIt != mExclusives.End(); ++exclusiveIt )
+  {
+    if ( exclusiveIt->renderTaskPtr == task )
+    {
+      if ( !exclusive )
+      {
+        mExclusives.Erase( exclusiveIt );
+        break;
+      }
+      else
+      {
+        exclusiveIt->actorPtr = task->GetSourceActor();
+        exclusive = false;
+        break;
+      }
+    }
+  }
+  if ( exclusive )
+  {
+    Exclusive exclusiveSlot;
+    exclusiveSlot.renderTaskPtr = task;
+    exclusiveSlot.actorPtr = task->GetSourceActor();
+    mExclusives.PushBack( exclusiveSlot );
+  }
+}
+
+RenderTaskList::RenderTaskList( EventThreadServices& eventThreadServices, RenderTaskDefaults& defaults, bool systemLevel )
+: mEventThreadServices( eventThreadServices ),
+  mDefaults( defaults ),
+  mIsSystemLevel( systemLevel ),
+  mSceneObject( NULL )
+{
+}
+
+RenderTaskList::~RenderTaskList()
+{
+}
+
+void RenderTaskList::Initialize( UpdateManager& updateManager )
+{
+  // This should only be called once, with no existing scene-object
+  DALI_ASSERT_DEBUG( NULL == mSceneObject );
+
+  // Get raw-pointer to render task list
+  mSceneObject = updateManager.GetRenderTaskList( mIsSystemLevel );
+  // set the callback to call us back when tasks are completed
+  mSceneObject->SetCompleteNotificationInterface( this );
+}
+
+void RenderTaskList::NotifyCompleted()
+{
+  DALI_LOG_TRACE_METHOD(gLogRenderList);
+
+  std::vector< Dali::RenderTask > finishedRenderTasks;
+
+  // Since render tasks can be unreferenced during the signal emissions, iterators into render tasks pointers may be invalidated.
+  // First copy the finished render tasks, then emit signals
+  for ( std::vector<Dali::RenderTask>::iterator it = mTasks.begin(), endIt = mTasks.end(); it != endIt; ++it )
+  {
+    Dali::RenderTask& renderTask( *it );
+
+    if( GetImplementation( renderTask ).HasFinished() )
+    {
+      finishedRenderTasks.push_back( Dali::RenderTask( renderTask ) );
+    }
+  }
+
+  // Now it's safe to emit the signals
+  for ( std::vector<Dali::RenderTask>::iterator it = finishedRenderTasks.begin(), endIt = finishedRenderTasks.end(); it != endIt; ++it )
+  {
+    Dali::RenderTask& handle( *it );
+
+    GetImplementation(handle).EmitSignalFinish();
+  }
+}
+
+void RenderTaskList::RecoverFromContextLoss()
+{
+  for ( RenderTaskContainer::iterator iter = mTasks.begin(); mTasks.end() != iter; ++iter )
+  {
+    Dali::RenderTask task = *iter;
+
+    // If the render target renders only once to an offscreen, re-render the render task
+    if( task.GetRefreshRate() == Dali::RenderTask::REFRESH_ONCE && task.GetTargetFrameBuffer() )
+    {
+      task.SetRefreshRate( Dali::RenderTask::REFRESH_ONCE );
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/render-tasks/render-task-list-impl.h b/dali/internal/event/render-tasks/render-task-list-impl.h
new file mode 100644 (file)
index 0000000..3216793
--- /dev/null
@@ -0,0 +1,194 @@
+#ifndef __DALI_INTERNAL_RENDER_TASK_LIST_H__
+#define __DALI_INTERNAL_RENDER_TASK_LIST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/internal/event/common/complete-notification-interface.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class EventThreadServices;
+class RenderTaskDefaults;
+class Actor;
+
+namespace SceneGraph
+{
+class RenderTaskList;
+class UpdateManager;
+}
+
+/**
+ * A proxy for the scene-graph RenderTaskList.
+ * A separate LayerList is maintained for actors added via the SystemLevel::Add().
+ */
+class RenderTaskList : public BaseObject, public CompleteNotificationInterface
+{
+public:
+
+  typedef std::vector< Dali::RenderTask > RenderTaskContainer;
+
+  struct Exclusive
+  {
+    RenderTask* renderTaskPtr;        ///< Pointer for comparison with current rendertask.
+    Actor* actorPtr;                  ///< Pointer for comparison with current actor.
+  };
+
+  /**
+   * Create a RenderTaskList.
+   * @param[in] eventServices Used for sending message to the scene graph.
+   * @param[in] defaults Provides the default source & camera actors.
+   * @param[in] systemLevel True if this is the LayerList for actors added via the SystemLevel::Add().
+   * @return A newly allocated RenderTaskList; the caller takes ownership.
+   */
+  static RenderTaskList* New( EventThreadServices& eventServices, RenderTaskDefaults& defaults, bool systemLevel );
+
+  /**
+   * @copydoc Dali::RenderTaskList::CreateTask()
+   */
+  Dali::RenderTask CreateTask();
+
+  /**
+   * @copydoc Dali::RenderTaskList::RemoveTask()
+   */
+  void RemoveTask( Dali::RenderTask task );
+
+  /**
+   * @copydoc Dali::RenderTaskList::GetTaskCount()
+   */
+  unsigned int GetTaskCount() const;
+
+  /**
+   * @copydoc Dali::RenderTaskList::GetTask()
+   */
+  Dali::RenderTask GetTask( unsigned int index ) const;
+
+  /**
+   * Retrieve the container of render-tasks.
+   * @return The container.
+   */
+  RenderTaskContainer& GetTasks()
+  {
+    return mTasks;
+  }
+
+  /**
+   * @brief Mark a rendertask as having exclusive access to its source actor.
+   *
+   * @param[in] task Pointer to the rendertask.
+   * @param[in] exclusive If a rendertask is to have exclusive acesss to its source actor.
+   */
+  void SetExclusive( RenderTask* task, bool exclusive );
+
+  /**
+   * @brief Return the list of rendertasks that exclusively own their source actor.
+   *
+   * @return [description]
+   */
+  const Vector< Exclusive >& GetExclusivesList() const
+  {
+    return mExclusives;
+  }
+
+  /**
+   * Provide notification signals for a "Finished" render task.
+   * This method should be called in the event-thread
+   * Queue NotifyFinishedMessage() from update-thread
+   * @param object pointer to this class instance
+   */
+  static void NotifyFinished( void* object );
+
+  /**
+   * This method refreshes all render tasks that have a frame buffer
+   * and a refresh rate of RefreshOnce.
+   */
+  void RecoverFromContextLoss();
+
+protected:
+
+  /**
+   * Construct a new RenderTaskList.
+   * @param[in] eventThreadServices Used for creating render-tasks in the scene graph.
+   * @param[in] defaults Provides the default source & camera actors.
+   * @param[in] systemLevel True if this is the system-level list.
+   */
+  RenderTaskList( EventThreadServices& eventThreadServices, RenderTaskDefaults& defaults, bool systemLevel );
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~RenderTaskList();
+
+  /**
+   * 2nd-phase construction
+   */
+  void Initialize( SceneGraph::UpdateManager& updateManager );
+
+private: // from CompleteNotificationInterface
+
+  /**
+   * @copydoc CompleteNotificationInterface::NotifyCompleted()
+   */
+  virtual void NotifyCompleted();
+
+private:
+
+  EventThreadServices& mEventThreadServices;
+  RenderTaskDefaults& mDefaults;
+
+  bool mIsSystemLevel; ///< True if the layers are added via the SystemLevel API
+
+  SceneGraph::RenderTaskList* mSceneObject; ///< Raw-pointer to the scene-graph object; not owned.
+
+  RenderTaskContainer mTasks;           ///< Reference counted render-tasks
+  Vector< Exclusive > mExclusives;      ///< List of rendertasks with exclusively owned source actors.
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::RenderTaskList& GetImplementation(Dali::RenderTaskList& taskList)
+{
+  DALI_ASSERT_ALWAYS(taskList && "RenderTaskList handle is empty");
+
+  BaseObject& handle = taskList.GetBaseObject();
+
+  return static_cast<Internal::RenderTaskList&>(handle);
+}
+
+inline const Internal::RenderTaskList& GetImplementation(const Dali::RenderTaskList& taskList)
+{
+  DALI_ASSERT_ALWAYS(taskList && "RenderTaskList handle is empty");
+
+  const BaseObject& handle = taskList.GetBaseObject();
+
+  return static_cast<const Internal::RenderTaskList&>(handle);
+}
+
+} // namespace Dali
+
+#endif //__DALI_INTERNAL_RENDER_TASK_LIST_H__
diff --git a/dali/internal/event/rendering/geometry-impl.cpp b/dali/internal/event/rendering/geometry-impl.cpp
new file mode 100644 (file)
index 0000000..60081f2
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/geometry-impl.h> // Dali::Internal::Geometry
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ *            |name                    |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "geometry-type",         STRING,   true, false,  true, Dali::Geometry::Property::GEOMETRY_TYPE )
+DALI_PROPERTY( "geometry-center",       VECTOR3,  true, true,   true, Dali::Geometry::Property::GEOMETRY_CENTER )
+DALI_PROPERTY( "geometry-half-extents", VECTOR3,  true, true,   true, Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS )
+DALI_PROPERTY( "requires-depth-test",   BOOLEAN,  true, false,  true, Dali::Geometry::Property::REQUIRES_DEPTH_TEST )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> GEOMETRY_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::Geometry::New();
+}
+
+TypeRegistration mType( typeid( Dali::Geometry ), typeid( Dali::Handle ), Create );
+
+} // unnamed namespace
+
+GeometryPtr Geometry::New()
+{
+  GeometryPtr geometry( new Geometry() );
+  geometry->Initialize();
+  return geometry;
+}
+
+std::size_t Geometry::AddVertexBuffer( PropertyBuffer& vertexBuffer )
+{
+  PropertyBufferConnector connector;
+  connector.Set( vertexBuffer, OnStage() );
+  mVertexBufferConnectors.push_back( connector );
+
+  const SceneGraph::PropertyBuffer& sceneGraphPropertyBuffer = static_cast<const SceneGraph::PropertyBuffer&>( *vertexBuffer.GetSceneObject() );
+
+  SceneGraph::AddVertexBufferMessage( GetEventThreadServices(), *mSceneObject, sceneGraphPropertyBuffer );
+
+  return mVertexBufferConnectors.size() - 1u;
+}
+
+std::size_t Geometry::GetNumberOfVertexBuffers() const
+{
+  return mVertexBufferConnectors.size();
+}
+
+void Geometry::RemoveVertexBuffer( std::size_t index )
+{
+  const SceneGraph::PropertyBuffer& sceneGraphPropertyBuffer = static_cast<const SceneGraph::PropertyBuffer&>( *(mVertexBufferConnectors[index].Get()->GetSceneObject()) );
+  SceneGraph::RemoveVertexBufferMessage( GetEventThreadServices(), *mSceneObject, sceneGraphPropertyBuffer );
+
+  mVertexBufferConnectors.erase( mVertexBufferConnectors.begin() + index );
+}
+
+void Geometry::SetIndexBuffer( PropertyBuffer& indexBuffer )
+{
+  mIndexBufferConnector.Set( indexBuffer, OnStage() );
+
+  const SceneGraph::PropertyBuffer& sceneGraphPropertyBuffer = dynamic_cast<const SceneGraph::PropertyBuffer&>( *indexBuffer.GetSceneObject() );
+
+  SceneGraph::SetIndexBufferMessage( GetEventThreadServices(), *mSceneObject, sceneGraphPropertyBuffer );
+}
+
+void Geometry::SetGeometryType( Dali::Geometry::GeometryType geometryType )
+{
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<int>::Send(
+      GetEventThreadServices(),
+      mSceneObject,
+      &mSceneObject->mGeometryType,
+      &SceneGraph::DoubleBufferedProperty<int>::Set,
+      static_cast<int>(geometryType) );
+  }
+}
+
+Dali::Geometry::GeometryType Geometry::GetGeometryType() const
+{
+  return mSceneObject->GetGeometryType(GetEventThreadServices().GetEventBufferIndex());
+}
+
+void Geometry::SetRequiresDepthTesting( bool requiresDepthTest )
+{
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mRequiresDepthTest, &SceneGraph::DoubleBufferedProperty<bool>::Set, static_cast<int>(requiresDepthTest) );
+  }
+}
+
+bool Geometry::GetRequiresDepthTesting() const
+{
+  if( mSceneObject )
+  {
+    // mSceneObject is being used in a separate thread; copy the value from the previous update
+    return mSceneObject->GetRequiresDepthTesting(GetEventThreadServices().GetEventBufferIndex());
+  }
+  return false;
+}
+
+const SceneGraph::Geometry* Geometry::GetGeometrySceneObject() const
+{
+  return mSceneObject;
+}
+
+unsigned int Geometry::GetDefaultPropertyCount() const
+{
+  return GEOMETRY_IMPL.GetDefaultPropertyCount();
+}
+
+void Geometry::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  GEOMETRY_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* Geometry::GetDefaultPropertyName(Property::Index index) const
+{
+  return GEOMETRY_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index Geometry::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return GEOMETRY_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool Geometry::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return GEOMETRY_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool Geometry::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return GEOMETRY_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool Geometry::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return GEOMETRY_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type Geometry::GetDefaultPropertyType( Property::Index index ) const
+{
+  return GEOMETRY_IMPL.GetDefaultPropertyType( index );
+}
+
+void Geometry::SetDefaultProperty( Property::Index index,
+                                   const Property::Value& propertyValue )
+{
+  switch( index )
+  {
+    case Dali::Geometry::Property::GEOMETRY_TYPE :
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mGeometryType, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Geometry::Property::GEOMETRY_CENTER :
+    {
+      SceneGraph::AnimatablePropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mCenter, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
+      break;
+    }
+
+    case Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS :
+    {
+      SceneGraph::AnimatablePropertyMessage<Vector3>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mHalfExtents, &SceneGraph::AnimatableProperty<Vector3>::Bake, propertyValue.Get<Vector3>() );
+      break;
+    }
+
+    case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mRequiresDepthTest, &SceneGraph::DoubleBufferedProperty<bool>::Set, propertyValue.Get<bool>() );
+      break;
+    }
+  }
+}
+
+void Geometry::SetSceneGraphProperty( Property::Index index,
+                                      const PropertyMetadata& entry,
+                                      const Property::Value& value )
+{
+  GEOMETRY_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+}
+
+Property::Value Geometry::GetDefaultProperty( Property::Index index ) const
+{
+  BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
+  Property::Value value;
+
+  switch( index )
+  {
+    case Dali::Geometry::Property::GEOMETRY_TYPE :
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mGeometryType[bufferIndex];
+      }
+      break;
+    }
+    case Dali::Geometry::Property::GEOMETRY_CENTER :
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mCenter[bufferIndex];
+      }
+      break;
+    }
+
+    case Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS :
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mHalfExtents[bufferIndex];
+      }
+      break;
+    }
+
+    case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mRequiresDepthTest[bufferIndex];
+      }
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Geometry::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* Geometry::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* Geometry::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  const SceneGraph::PropertyBase* property = NULL;
+
+  if( OnStage() )
+  {
+    property = GEOMETRY_IMPL.GetRegisteredSceneGraphProperty ( this,
+                                                               &Geometry::FindAnimatableProperty,
+                                                               &Geometry::FindCustomProperty,
+                                                               index );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      switch(index)
+      {
+        case Dali::Geometry::Property::GEOMETRY_CENTER :
+        {
+          property = &mSceneObject->mCenter;
+          break;
+        }
+        case Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS :
+        {
+          property = &mSceneObject->mHalfExtents;
+          break;
+        }
+        default:
+        {
+          DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
+          break;
+        }
+      }
+    }
+  }
+  return property;
+}
+
+const PropertyInputImpl* Geometry::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  if( OnStage() )
+  {
+    const SceneGraph::PropertyBase* baseProperty =
+      GEOMETRY_IMPL.GetRegisteredSceneGraphProperty ( this,
+                                                      &Geometry::FindAnimatableProperty,
+                                                      &Geometry::FindCustomProperty,
+                                                      index );
+
+    property = static_cast<const PropertyInputImpl*>( baseProperty );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      switch(index)
+      {
+        case Dali::Geometry::Property::GEOMETRY_TYPE :
+        {
+          property = &mSceneObject->mGeometryType;
+          break;
+        }
+        case Dali::Geometry::Property::GEOMETRY_CENTER :
+        {
+          property = &mSceneObject->mCenter;
+          break;
+        }
+        case Dali::Geometry::Property::GEOMETRY_HALF_EXTENTS :
+        {
+          property = &mSceneObject->mHalfExtents;
+          break;
+        }
+        case Dali::Geometry::Property::REQUIRES_DEPTH_TEST :
+        {
+          property = &mSceneObject->mRequiresDepthTest;
+          break;
+        }
+        default:
+        {
+          DALI_ASSERT_ALWAYS( 0 && "Property cannot be a constraint input");
+          break;
+        }
+      }
+    }
+  }
+
+  return property;
+}
+
+int Geometry::GetPropertyComponentIndex( Property::Index index ) const
+{
+  // @todo MESH_REWORK - Change this if component properties are added for center/half-extent
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+bool Geometry::OnStage() const
+{
+  return mOnStage;
+}
+
+void Geometry::Connect()
+{
+  mOnStage = true;
+
+  PropertyBufferConnectorContainer::const_iterator end = mVertexBufferConnectors.end();
+  for( PropertyBufferConnectorContainer::iterator it = mVertexBufferConnectors.begin();
+       it < end;
+       ++it )
+  {
+    it->OnStageConnect();
+  }
+  mIndexBufferConnector.OnStageConnect();
+}
+
+void Geometry::Disconnect()
+{
+  mOnStage = false;
+
+  PropertyBufferConnectorContainer::const_iterator end = mVertexBufferConnectors.end();
+  for( PropertyBufferConnectorContainer::iterator it = mVertexBufferConnectors.begin();
+       it < end;
+       ++it )
+  {
+    it->OnStageDisconnect();
+  }
+  mIndexBufferConnector.OnStageDisconnect();
+}
+
+Geometry::Geometry()
+: mSceneObject( NULL ),
+  mOnStage( false )
+{
+}
+
+void Geometry::Initialize()
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  mSceneObject = new SceneGraph::Geometry();
+  AddMessage( updateManager, updateManager.GetGeometryOwner(), *mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
+}
+
+Geometry::~Geometry()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveMessage( updateManager, updateManager.GetGeometryOwner(), *mSceneObject );
+
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/rendering/geometry-impl.h b/dali/internal/event/rendering/geometry-impl.h
new file mode 100644 (file)
index 0000000..1ec3832
--- /dev/null
@@ -0,0 +1,254 @@
+#ifndef DALI_INTERNAL_GEOMETRY_H
+#define DALI_INTERNAL_GEOMETRY_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h> // std::vector
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/devel-api/rendering/geometry.h> // Dali::Geometry
+#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+#include <dali/internal/event/common/property-buffer-impl.h> // Dali::Internal::PropertyBuffer
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Geometry;
+}
+
+class Geometry;
+typedef IntrusivePtr<Geometry> GeometryPtr;
+
+/**
+ * Geometry is an object that contains an array of structures of values that
+ * can be accessed as properties.
+ */
+class Geometry : public Object, public Connectable
+{
+public:
+
+  /**
+   * Create a new Geometry.
+   * @return A smart-pointer to the newly allocated Geometry.
+   */
+  static GeometryPtr New();
+
+  /**
+   * @copydoc Dali::Geometry::AddVertexBuffer()
+   */
+  std::size_t AddVertexBuffer( PropertyBuffer& vertexBuffer );
+
+  /**
+   * @copydoc Dali::Geometry::GetNumberOfVertexBuffers()
+   */
+  std::size_t GetNumberOfVertexBuffers() const;
+
+  /**
+   * @copydoc Dali::Geometry::RemoveVertexBuffer()
+   */
+  void RemoveVertexBuffer( std::size_t index );
+
+  /**
+   * @copydoc Dali::Geometry::SetIndexBuffer()
+   */
+  void SetIndexBuffer( PropertyBuffer& indexBuffer );
+
+  /**
+   * @copydoc Dali::Geometry::SetGeometryType()
+   */
+  void SetGeometryType( Dali::Geometry::GeometryType geometryType );
+
+  /**
+   * @copydoc Dali::Geometry::GetGeometryType()
+   */
+  Dali::Geometry::GeometryType GetGeometryType() const;
+
+  /**
+   * @copydoc Dali::Geometry::SetRequiresDepthTesting()
+   */
+  void SetRequiresDepthTesting( bool requiresDepthTest );
+
+  /**
+   * @copydoc Dali::Geometry::GetRequiresDepthTesting()
+   */
+  bool GetRequiresDepthTesting() const;
+
+  /**
+   * @brief Get the geometry scene object
+   *
+   * @return the geometry scene object
+   */
+  const SceneGraph::Geometry* GetGeometrySceneObject() const;
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+public: // Functions from Connectable
+  /**
+   * @copydoc Dali::Internal::Connectable::OnStage()
+   */
+  virtual bool OnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Connect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Disconnect()
+   */
+  virtual void Disconnect();
+
+private: // implementation
+  Geometry();
+
+  /**
+   * Second stage initialization of the Geometry
+   */
+  void Initialize();
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Geometry();
+
+private: // unimplemented methods
+  Geometry( const Geometry& );
+  Geometry& operator=( const Geometry& );
+
+private: // data
+  typedef ObjectConnector<PropertyBuffer> PropertyBufferConnector;
+  typedef std::vector< PropertyBufferConnector > PropertyBufferConnectorContainer;
+  PropertyBufferConnectorContainer mVertexBufferConnectors; ///< Vector of connectors that hold the property buffers used by this geometry
+  PropertyBufferConnector mIndexBufferConnector;            ///< Connector that holds the index buffer used by this geometry
+  SceneGraph::Geometry* mSceneObject;
+  bool mOnStage;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::Geometry& GetImplementation(Dali::Geometry& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "Geometry handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Geometry&>(object);
+}
+
+inline const Internal::Geometry& GetImplementation(const Dali::Geometry& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "Geometry handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Geometry&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_GEOMETRY_H
diff --git a/dali/internal/event/rendering/material-impl.cpp b/dali/internal/event/rendering/material-impl.cpp
new file mode 100644 (file)
index 0000000..c02df3d
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/material-impl.h> // Dali::Internal::Material
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/rendering/material.h> // Dali::Internal::Material
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/update/manager/update-manager.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ *            |name                              |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "color",                           VECTOR4,  true, true,   true, Dali::Material::Property::COLOR )
+DALI_PROPERTY( "face-culling-mode",               STRING,   true, false,  false, Dali::Material::Property::FACE_CULLING_MODE )
+DALI_PROPERTY( "blending-mode",                   STRING,   true, false,  false, Dali::Material::Property::BLENDING_MODE )
+DALI_PROPERTY( "blend-equation-rgb",              STRING,   true, false,  false, Dali::Material::Property::BLEND_EQUATION_RGB )
+DALI_PROPERTY( "blend-equation-alpha",            STRING,   true, false,  false, Dali::Material::Property::BLEND_EQUATION_ALPHA )
+DALI_PROPERTY( "source-blend-factor-rgb",         STRING,   true, false,  false, Dali::Material::Property::BLENDING_SRC_FACTOR_RGB )
+DALI_PROPERTY( "destination-blend-factor-rgb",    STRING,   true, false,  false, Dali::Material::Property::BLENDING_DEST_FACTOR_RGB )
+DALI_PROPERTY( "source-blend-factor-alpha",       STRING,   true, false,  false, Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA )
+DALI_PROPERTY( "destination-blend-factor-alpha",  STRING,   true, false,  false, Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA )
+DALI_PROPERTY( "blend-color",                     VECTOR4,  true, true,   true, Dali::Material::Property::BLEND_COLOR )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> MATERIAL_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::Material ), typeid( Dali::Handle ), Create );
+
+} // unnamed namespace
+
+MaterialPtr Material::New()
+{
+  MaterialPtr material( new Material() );
+  material->Initialize();
+  return material;
+}
+
+void Material::SetShader( Shader& shader )
+{
+  DALI_ASSERT_DEBUG( mSceneObject )
+  mShader = &shader;
+
+  const SceneGraph::Shader& sceneGraphShader = dynamic_cast<const SceneGraph::Shader&>( *shader.GetSceneObject() );
+  SceneGraph::SetShaderMessage( GetEventThreadServices(), *mSceneObject, sceneGraphShader );
+}
+
+Shader* Material::GetShader() const
+{
+  return mShader.Get();
+}
+
+void Material::AddSampler( Sampler& sampler )
+{
+  SamplerConnector connector;
+  connector.Set( sampler, OnStage() );
+  mSamplerConnectors.push_back( connector );
+
+  const SceneGraph::Sampler& sceneGraphSampler = dynamic_cast<const SceneGraph::Sampler&>( *sampler.GetSceneObject() );
+  SceneGraph::AddSamplerMessage( GetEventThreadServices(), *mSceneObject, sceneGraphSampler );
+}
+
+std::size_t Material::GetNumberOfSamplers() const
+{
+  return mSamplerConnectors.size();
+}
+
+void Material::RemoveSampler( std::size_t index )
+{
+  mSamplerConnectors.erase( mSamplerConnectors.begin() + index );
+}
+
+Sampler* Material::GetSamplerAt( unsigned int index ) const
+{
+  return mSamplerConnectors[index].Get().Get();
+}
+
+void Material::SetFaceCullingMode( Dali::Material::FaceCullingMode cullingMode )
+{
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(cullingMode) );
+  }
+}
+
+void Material::SetBlendMode( BlendingMode::Type mode )
+{
+  mBlendingMode = mode;
+
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, static_cast<int>(mode) );
+  }
+}
+
+BlendingMode::Type Material::GetBlendMode() const
+{
+  return mBlendingMode;
+}
+
+void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
+{
+  mBlendingOptions.SetBlendFunc( srcFactorRgba, destFactorRgba, srcFactorRgba, destFactorRgba );
+  SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
+}
+
+void Material::SetBlendFunc( BlendingFactor::Type srcFactorRgb,
+                             BlendingFactor::Type destFactorRgb,
+                             BlendingFactor::Type srcFactorAlpha,
+                             BlendingFactor::Type destFactorAlpha )
+{
+  mBlendingOptions.SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+  SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
+}
+
+void Material::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,
+                             BlendingFactor::Type& destFactorRgb,
+                             BlendingFactor::Type& srcFactorAlpha,
+                             BlendingFactor::Type& destFactorAlpha ) const
+{
+  srcFactorRgb    = mBlendingOptions.GetBlendSrcFactorRgb();
+  destFactorRgb   = mBlendingOptions.GetBlendDestFactorRgb();
+  srcFactorAlpha  = mBlendingOptions.GetBlendSrcFactorAlpha();
+  destFactorAlpha = mBlendingOptions.GetBlendDestFactorAlpha();
+}
+
+void Material::SetBlendEquation( BlendingEquation::Type equationRgba )
+{
+  mBlendingOptions.SetBlendEquation( equationRgba, equationRgba );
+  SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
+}
+
+void Material::SetBlendEquation( BlendingEquation::Type equationRgb,
+                                 BlendingEquation::Type equationAlpha )
+{
+  mBlendingOptions.SetBlendEquation( equationRgb, equationAlpha );
+  SetBlendingOptionsMessage( GetEventThreadServices(), *mSceneObject, mBlendingOptions.GetBitmask() );
+}
+
+void Material::GetBlendEquation( BlendingEquation::Type& equationRgb,
+                                 BlendingEquation::Type& equationAlpha ) const
+{
+  // These are not animatable, the cached values are up-to-date.
+  equationRgb   = mBlendingOptions.GetBlendEquationRgb();
+  equationAlpha = mBlendingOptions.GetBlendEquationAlpha();
+}
+
+void Material::SetBlendColor( const Vector4& color )
+{
+  if( mSceneObject )
+  {
+    SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, color );
+  }
+}
+
+const Vector4& Material::GetBlendColor() const
+{
+  return mSceneObject->mBlendColor[ GetEventThreadServices().GetEventBufferIndex() ];
+}
+
+const SceneGraph::Material* Material::GetMaterialSceneObject() const
+{
+  return mSceneObject;
+}
+
+unsigned int Material::GetDefaultPropertyCount() const
+{
+  return MATERIAL_IMPL.GetDefaultPropertyCount();
+}
+
+void Material::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  MATERIAL_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* Material::GetDefaultPropertyName(Property::Index index) const
+{
+  return MATERIAL_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index Material::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return MATERIAL_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool Material::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return MATERIAL_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool Material::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return MATERIAL_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool Material::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return MATERIAL_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type Material::GetDefaultPropertyType( Property::Index index ) const
+{
+  return MATERIAL_IMPL.GetDefaultPropertyType( index );
+}
+
+void Material::SetDefaultProperty( Property::Index index,
+                                   const Property::Value& propertyValue )
+{
+  switch( index )
+  {
+    case Dali::Material::Property::COLOR:
+    {
+      SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
+      break;
+    }
+    case Dali::Material::Property::FACE_CULLING_MODE:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mFaceCullingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_MODE:
+    {
+      if( mSceneObject )
+      {
+        SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendingMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      }
+      break;
+    }
+    case Dali::Material::Property::BLEND_EQUATION_RGB:
+    {
+      BlendingEquation::Type alphaEquation = mBlendingOptions.GetBlendEquationAlpha();
+      mBlendingOptions.SetBlendEquation( static_cast<BlendingEquation::Type>(propertyValue.Get<int>()), alphaEquation );
+      break;
+    }
+    case Dali::Material::Property::BLEND_EQUATION_ALPHA:
+    {
+      BlendingEquation::Type rgbEquation = mBlendingOptions.GetBlendEquationRgb();
+      mBlendingOptions.SetBlendEquation( rgbEquation, static_cast<BlendingEquation::Type>(propertyValue.Get<int>()) );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_SRC_FACTOR_RGB:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      SetBlendFunc( static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
+                    destFactorRgb,
+                    srcFactorAlpha,
+                    destFactorAlpha );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_DEST_FACTOR_RGB:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      SetBlendFunc( srcFactorRgb,
+                    static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
+                    srcFactorAlpha,
+                    destFactorAlpha );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      SetBlendFunc( srcFactorRgb,
+                    destFactorRgb,
+                    static_cast<BlendingFactor::Type>(propertyValue.Get<int>()),
+                    destFactorAlpha );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      SetBlendFunc( srcFactorRgb,
+                    destFactorRgb,
+                    srcFactorAlpha,
+                    static_cast<BlendingFactor::Type>(propertyValue.Get<int>()) );
+      break;
+    }
+    case Dali::Material::Property::BLEND_COLOR:
+    {
+      SceneGraph::AnimatablePropertyMessage<Vector4>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mBlendColor, &SceneGraph::AnimatableProperty<Vector4>::Bake, propertyValue.Get<Vector4>() );
+      break;
+    }
+  }
+}
+
+void Material::SetSceneGraphProperty( Property::Index index,
+                                      const PropertyMetadata& entry,
+                                      const Property::Value& value )
+{
+  MATERIAL_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+  OnPropertySet(index, value);
+}
+
+Property::Value Material::GetDefaultProperty( Property::Index index ) const
+{
+  BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
+  Property::Value value;
+
+  switch( index )
+  {
+    case Dali::Material::Property::COLOR:
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mColor[bufferIndex];
+      }
+      break;
+    }
+    case Dali::Material::Property::FACE_CULLING_MODE:
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mFaceCullingMode[bufferIndex];
+      }
+      break;
+    }
+    case Dali::Material::Property::BLENDING_MODE:
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mBlendingMode[bufferIndex];
+      }
+      break;
+    }
+    case Dali::Material::Property::BLEND_EQUATION_RGB:
+    {
+      value = static_cast<int>( mBlendingOptions.GetBlendEquationRgb() );
+      break;
+    }
+    case Dali::Material::Property::BLEND_EQUATION_ALPHA:
+    {
+      value = static_cast<int>( mBlendingOptions.GetBlendEquationAlpha() );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_SRC_FACTOR_RGB:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      value = static_cast<int>( srcFactorRgb );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_DEST_FACTOR_RGB:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      value = static_cast<int>( destFactorRgb );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_SRC_FACTOR_ALPHA:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      value = static_cast<int>( srcFactorAlpha );
+      break;
+    }
+    case Dali::Material::Property::BLENDING_DEST_FACTOR_ALPHA:
+    {
+      BlendingFactor::Type srcFactorRgb;
+      BlendingFactor::Type destFactorRgb;
+      BlendingFactor::Type srcFactorAlpha;
+      BlendingFactor::Type destFactorAlpha;
+      GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+      value = static_cast<int>( destFactorAlpha );
+      break;
+    }
+    case Dali::Material::Property::BLEND_COLOR:
+    {
+      if( mSceneObject )
+      {
+        value = mSceneObject->mBlendColor[bufferIndex];
+      }
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Material::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* Material::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* Material::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
+
+  const SceneGraph::PropertyBase* property = NULL;
+
+  if( OnStage() )
+  {
+    property = MATERIAL_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                              &Material::FindAnimatableProperty,
+                                                              &Material::FindCustomProperty,
+                                                              index );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      switch(index)
+      {
+        case Dali::Material::Property::COLOR:
+        {
+          property = &mSceneObject->mColor;
+          break;
+        }
+        case Dali::Material::Property::BLEND_COLOR:
+        {
+          property = &mSceneObject->mBlendColor;
+          break;
+        }
+        default:
+        {
+          DALI_ASSERT_ALWAYS( 0 && "Property is not animatable");
+          break;
+        }
+      }
+    }
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* Material::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  if( OnStage() )
+  {
+    const SceneGraph::PropertyBase* baseProperty =
+      MATERIAL_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                     &Material::FindAnimatableProperty,
+                                                     &Material::FindCustomProperty,
+                                                     index );
+    property = static_cast<const PropertyInputImpl*>( baseProperty );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      switch(index)
+      {
+        case Dali::Material::Property::COLOR:
+        {
+          property = &mSceneObject->mColor;
+          break;
+        }
+        case Dali::Material::Property::FACE_CULLING_MODE:
+        {
+          property = &mSceneObject->mFaceCullingMode;
+          break;
+        }
+        case Dali::Material::Property::BLEND_COLOR:
+        {
+          property = &mSceneObject->mBlendColor;
+          break;
+        }
+        default:
+        {
+          DALI_ASSERT_ALWAYS( 0 && "Property cannot be a constraint input");
+          break;
+        }
+      }
+    }
+  }
+
+  return property;
+}
+
+int Material::GetPropertyComponentIndex( Property::Index index ) const
+{
+  // @todo MESH_REWORK - Change this if component properties are added for color/blend-color
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+bool Material::OnStage() const
+{
+  return mOnStage;
+}
+
+void Material::Connect()
+{
+  mOnStage = true;
+
+  SamplerConnectorContainer::const_iterator end = mSamplerConnectors.end();
+  for( SamplerConnectorContainer::iterator it = mSamplerConnectors.begin();
+       it < end;
+       ++it )
+  {
+    it->OnStageConnect();
+  }
+}
+
+void Material::Disconnect()
+{
+  mOnStage = false;
+
+  SamplerConnectorContainer::const_iterator end = mSamplerConnectors.end();
+  for( SamplerConnectorContainer::iterator it = mSamplerConnectors.begin();
+       it < end;
+       ++it )
+  {
+    it->OnStageDisconnect();
+  }
+}
+
+Material::Material()
+: mSceneObject( NULL ),
+  mOnStage( false )
+{
+}
+
+void Material::Initialize()
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  mSceneObject = new SceneGraph::Material();
+  AddMessage( updateManager, updateManager.GetMaterialOwner(), *mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
+}
+
+Material::~Material()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveMessage( updateManager, updateManager.GetMaterialOwner(), *mSceneObject );
+
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/rendering/material-impl.h b/dali/internal/event/rendering/material-impl.h
new file mode 100644 (file)
index 0000000..9c4f54e
--- /dev/null
@@ -0,0 +1,309 @@
+#ifndef DALI_INTERNAL_MATERIAL_H
+#define DALI_INTERNAL_MATERIAL_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h> // std::vector
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/devel-api/rendering/material.h> // Dali::Material
+#include <dali/internal/common/blending-options.h>
+#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+#include <dali/internal/event/common/property-buffer-impl.h> // Dali::Internal::PropertyBuffer
+#include <dali/internal/event/rendering/sampler-impl.h> // Dali::Internal::Sampler
+#include <dali/internal/event/rendering/shader-impl.h> // Dali::Internal::Shader
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Material;
+}
+
+
+class Material;
+typedef IntrusivePtr<Material> MaterialPtr;
+
+/**
+ * Material is an object that connects a Shader with Samplers and can be used
+ * to shade a Geometry.
+ */
+class Material : public Object, public Connectable
+{
+public:
+
+  /**
+   * @copydoc Dali::Material::New()
+   */
+  static MaterialPtr New();
+
+  /**
+   * @copydoc Dali::Material::SetShader()
+   */
+  void SetShader( Shader& shader );
+
+  /**
+   * @copydoc Dali::Material::GetShader()
+   */
+  Shader* GetShader() const;
+
+  /**
+   * @copydoc Dali::Material::AddSampler()
+   */
+  void AddSampler( Sampler& sampler );
+
+  /**
+   * @copydoc Dali::Material::GetNumberOfSamplers()
+   */
+  std::size_t GetNumberOfSamplers() const;
+
+  /**
+   * @copydoc Dali::Material::RemoveSampler()
+   */
+  void RemoveSampler( std::size_t index );
+
+  /**
+   * @copydoc Dali::Material::GetSamplerAt()
+   */
+  Sampler* GetSamplerAt( unsigned int index ) const;
+
+  /**
+   * @copydoc Dali::Material::SetFaceCullingMode()
+   */
+  void SetFaceCullingMode( Dali::Material::FaceCullingMode cullingMode );
+
+  /**
+   * @copydoc Dali::Material::SetBlendMode()
+   */
+  void SetBlendMode( BlendingMode::Type mode );
+
+  /**
+   * @copydoc Dali::Material::GetBlendMode()
+   */
+  BlendingMode::Type GetBlendMode() const;
+
+  /**
+   * @copydoc Dali::Material::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba );
+
+  /**
+   * @copydoc Dali::Material::SetBlendFunc()
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @copydoc Dali::Material::GetBlendFunc()
+   */
+  void GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
+
+  /**
+   * @copydoc Dali::Material::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgba );
+
+  /**
+   * @copydoc Dali::Material::SetBlendEquation()
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @copydoc Dali::Material::GetBlendEquation()
+   */
+  void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
+
+  /**
+   * @copydoc Dali::Material::SetBlendColor()
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * @copydoc Dali::Material::GetBlendColor()
+   */
+  const Vector4& GetBlendColor() const;
+
+  /**
+   * @brief Get the material scene object
+   *
+   * @return the material scene object
+   */
+  const SceneGraph::Material* GetMaterialSceneObject() const;
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+public: // Functions from Connectable
+  /**
+   * @copydoc Dali::Internal::Connectable::OnStage()
+   */
+  virtual bool OnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Connect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Disconnect()
+   */
+  virtual void Disconnect();
+
+private: // implementation
+  Material();
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize();
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Material();
+
+private: // unimplemented methods
+  Material( const Material& );
+  Material& operator=( const Material& );
+
+private: //data
+  IntrusivePtr<Shader> mShader; ///< Connector that holds the shader used by this material
+
+  typedef ObjectConnector<Sampler> SamplerConnector;
+  typedef std::vector< SamplerConnector > SamplerConnectorContainer;
+  SamplerConnectorContainer mSamplerConnectors; ///< Vector of connectors that hold the samplers used by this material
+
+  SceneGraph::Material* mSceneObject;
+
+  BlendingMode::Type mBlendingMode; ///< Local store
+  BlendingOptions mBlendingOptions; ///< Local copy of blending options bitmask
+  bool mOnStage;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::Material& GetImplementation( Dali::Material& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Material handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Material&>(object);
+}
+
+inline const Internal::Material& GetImplementation( const Dali::Material& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Material handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Material&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_MATERIAL_H
diff --git a/dali/internal/event/rendering/renderer-impl.cpp b/dali/internal/event/rendering/renderer-impl.cpp
new file mode 100644 (file)
index 0000000..19e8d53
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/renderer-impl.h> // Dali::Internal::Renderer
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/rendering/renderer.h> // Dali::Renderer
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ *            |name          |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "depth-index", INTEGER, true, false, false, Dali::Renderer::Property::DEPTH_INDEX )
+DALI_PROPERTY_TABLE_END( DEFAULT_OBJECT_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> RENDERER_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::Renderer ), typeid( Dali::Handle ), Create );
+
+} // unnamed namespace
+
+RendererPtr Renderer::New()
+{
+  RendererPtr rendererPtr( new Renderer() );
+  rendererPtr->Initialize();
+  return rendererPtr;
+}
+
+void Renderer::SetGeometry( Geometry& geometry )
+{
+  mGeometryConnector.Set( geometry, OnStage() );
+  const SceneGraph::Geometry* geometrySceneObject = geometry.GetGeometrySceneObject();
+
+  SetGeometryMessage( GetEventThreadServices(), *mSceneObject, *geometrySceneObject );
+}
+
+Geometry* Renderer::GetGeometry() const
+{
+  return mGeometryConnector.Get().Get();
+}
+
+void Renderer::SetMaterial( Material& material )
+{
+  mMaterialConnector.Set( material, OnStage() );
+  const SceneGraph::Material* materialSceneObject = material.GetMaterialSceneObject();
+  SetMaterialMessage( GetEventThreadServices(), *mSceneObject, *materialSceneObject );
+}
+
+Material* Renderer::GetMaterial() const
+{
+  return mMaterialConnector.Get().Get();
+}
+
+void Renderer::SetDepthIndex( int depthIndex )
+{
+  if ( mDepthIndex != depthIndex )
+  {
+    mDepthIndex = depthIndex;
+    SetDepthIndexMessage( GetEventThreadServices(), *mSceneObject, depthIndex );
+  }
+}
+
+int Renderer::GetDepthIndex() const
+{
+  return mDepthIndex;
+}
+
+SceneGraph::RendererAttachment* Renderer::GetRendererSceneObject()
+{
+  return mSceneObject;
+}
+
+unsigned int Renderer::GetDefaultPropertyCount() const
+{
+  return RENDERER_IMPL.GetDefaultPropertyCount();
+}
+
+void Renderer::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  RENDERER_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* Renderer::GetDefaultPropertyName(Property::Index index) const
+{
+  return RENDERER_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index Renderer::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return RENDERER_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool Renderer::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return RENDERER_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool Renderer::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return RENDERER_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool Renderer::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return RENDERER_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type Renderer::GetDefaultPropertyType( Property::Index index ) const
+{
+  return RENDERER_IMPL.GetDefaultPropertyType( index );
+}
+
+void Renderer::SetDefaultProperty( Property::Index index,
+                                   const Property::Value& propertyValue )
+{
+  switch( index )
+  {
+    case Dali::Renderer::Property::DEPTH_INDEX:
+    {
+      SetDepthIndex( propertyValue.Get<int>() );
+    }
+    break;
+  }
+}
+
+void Renderer::SetSceneGraphProperty( Property::Index index,
+                                      const PropertyMetadata& entry,
+                                      const Property::Value& value )
+{
+  RENDERER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+  OnPropertySet(index, value);
+}
+
+Property::Value Renderer::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+  switch( index )
+  {
+    case Dali::Renderer::Property::DEPTH_INDEX:
+    {
+      value = GetDepthIndex();
+    }
+    break;
+  }
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Renderer::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* Renderer::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* Renderer::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable(index) && "Property is not animatable" );
+  const SceneGraph::PropertyBase* property = NULL;
+
+  if( OnStage() )
+  {
+    property = RENDERER_IMPL.GetRegisteredSceneGraphProperty(
+      this,
+      &Renderer::FindAnimatableProperty,
+      &Renderer::FindCustomProperty,
+      index );
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* Renderer::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  if( OnStage() )
+  {
+    const SceneGraph::PropertyBase* baseProperty =
+      RENDERER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                     &Renderer::FindAnimatableProperty,
+                                                     &Renderer::FindCustomProperty,
+                                                     index );
+    property = static_cast<const PropertyInputImpl*>( baseProperty );
+  }
+
+  return property;
+}
+
+int Renderer::GetPropertyComponentIndex( Property::Index index ) const
+{
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+bool Renderer::OnStage() const
+{
+  return mOnStage;
+}
+
+void Renderer::Connect()
+{
+  // @todo: MESH_REWORK : check this
+  mGeometryConnector.OnStageConnect();
+  mMaterialConnector.OnStageConnect();
+  mOnStage = true;
+}
+
+void Renderer::Disconnect()
+{
+  // @todo: MESH_REWORK : check this
+  mGeometryConnector.OnStageDisconnect();
+  mMaterialConnector.OnStageDisconnect();
+  mOnStage = false;
+}
+
+Renderer::Renderer()
+: mSceneObject(NULL),
+  mDepthIndex(0),
+  mOnStage(false)
+{
+}
+
+void Renderer::Initialize()
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  // Transfer object ownership of scene-object to message
+  mSceneObject = SceneGraph::RendererAttachment::New();
+
+  // Send message to update to connect to scene graph:
+  AttachToSceneGraphMessage( updateManager, mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
+}
+
+Renderer::~Renderer()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/rendering/renderer-impl.h b/dali/internal/event/rendering/renderer-impl.h
new file mode 100644 (file)
index 0000000..286069a
--- /dev/null
@@ -0,0 +1,237 @@
+#ifndef DALI_INTERNAL_RENDERER_H
+#define DALI_INTERNAL_RENDERER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/devel-api/rendering/renderer.h> // Dali::Renderer
+#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+#include <dali/internal/event/rendering/material-impl.h> // Dali::Internal::Material
+#include <dali/internal/event/rendering/geometry-impl.h> // Dali::Internal::Geometry
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class RendererAttachment;
+}
+
+class Renderer;
+typedef IntrusivePtr<Renderer> RendererPtr;
+
+/**
+ * Renderer is an object that can be used to show content by combining a Geometry with a material.
+ */
+class Renderer : public Object, public Connectable
+{
+public:
+
+  /**
+   * Create a new Renderer.
+   * @return A smart-pointer to the newly allocated Renderer.
+   */
+  static RendererPtr New();
+
+  /**
+   * @copydoc Dali::Renderer::SetGeometry()
+   */
+  void SetGeometry( Geometry& geometry );
+
+  /**
+   * @copydoc Dali::Renderer::GetGeometry()
+   */
+  Geometry* GetGeometry() const;
+
+  /**
+   * @copydoc Dali::Renderer::SetMaterial()
+   */
+  void SetMaterial( Material& material );
+
+  /**
+   * @copydoc Dali::Renderer::GetMaterial()
+   */
+  Material* GetMaterial() const;
+
+  /**
+   * @copydoc Dali::Renderer::SetDepthIndex()
+   */
+  void SetDepthIndex( int depthIndex );
+
+  /**
+   * @copydoc Dali::Renderer::GetDepthIndex()
+   */
+  int GetDepthIndex() const;
+
+  /**
+   * @brief Get the scene graph object ( the node attachment )
+   *
+   * @return the scene object
+   */
+  SceneGraph::RendererAttachment* GetRendererSceneObject();
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+public: // Functions from Connectable
+  /**
+   * @copydoc Dali::Internal::Connectable::OnStage()
+   */
+  virtual bool OnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Connect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Disconnect()
+   */
+  virtual void Disconnect();
+
+private: // implementation
+  Renderer();
+
+  void Initialize();
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Renderer();
+
+private: // unimplemented methods
+  Renderer( const Renderer& );
+  Renderer& operator=( const Renderer& );
+
+private: // data
+  SceneGraph::RendererAttachment* mSceneObject;
+  ObjectConnector<Geometry> mGeometryConnector; ///< Connector that holds the geometry used by this renderer
+  ObjectConnector<Material> mMaterialConnector; ///< Connector that holds the material used by this renderer
+  int mDepthIndex;
+  bool mOnStage;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::Renderer& GetImplementation( Dali::Renderer& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Renderer handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Renderer&>(object);
+}
+
+inline const Internal::Renderer& GetImplementation( const Dali::Renderer& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Renderer handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Renderer&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_RENDERER_H
diff --git a/dali/internal/event/rendering/sampler-impl.cpp b/dali/internal/event/rendering/sampler-impl.cpp
new file mode 100644 (file)
index 0000000..9c61904
--- /dev/null
@@ -0,0 +1,378 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/sampler-impl.h> // Dali::Internal::Sampler
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/devel-api/rendering/sampler.h> // Dali::Internal::Sampler
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/update/rendering/scene-graph-sampler.h> // Dali::Internal::SceneGraph::Sampler
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ *            |name                    |type     |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "minification-filter",   STRING,   true, false,  true, Dali::Sampler::Property::MINIFICATION_FILTER )
+DALI_PROPERTY( "magnification-filter",  STRING,   true, false,  true, Dali::Sampler::Property::MAGNIGICATION_FILTER )
+DALI_PROPERTY( "u-wrap",                STRING,   true, false,  true, Dali::Sampler::Property::U_WRAP )
+DALI_PROPERTY( "v-wrap",                STRING,   true, false,  true, Dali::Sampler::Property::V_WRAP )
+DALI_PROPERTY( "affects-transparency",  BOOLEAN,  true, false,  true, Dali::Sampler::Property::AFFECTS_TRANSPARENCY )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> SAMPLER_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::Sampler ), typeid( Dali::Handle ), Create );
+
+} // unnamed namespace
+
+SamplerPtr Sampler::New( const std::string& textureUnitUniformName )
+{
+  SamplerPtr sampler( new Sampler() );
+  sampler->Initialize( textureUnitUniformName );
+  return sampler;
+}
+
+void Sampler::SetTextureUnitUniformName( const std::string& name )
+{
+  SetTextureUnitUniformNameMessage( GetEventThreadServices(), *mSceneObject, name);
+}
+
+void Sampler::SetImage( ImagePtr& image )
+{
+  // Keep a reference to the image object
+  mImageConnector.Set( image, OnStage() );
+
+  // sceneObject is being used in a separate thread; queue a message to set
+  if( mOnStage )
+  {
+    unsigned int resourceId = image->GetResourceId();
+    if( resourceId != 0 )
+    {
+      SetTextureMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+    }
+  }
+}
+
+ImagePtr Sampler::GetImage() const
+{
+  return mImageConnector.Get();
+}
+
+void Sampler::SetFilterMode( Dali::Sampler::FilterMode minFilter, Dali::Sampler::FilterMode magFilter )
+{
+  if( NULL != mSceneObject )
+  {
+    SetFilterModeMessage( GetEventThreadServices(), *mSceneObject, minFilter, magFilter );
+  }
+}
+
+void Sampler::SetWrapMode( Dali::Sampler::WrapMode uWrap, Dali::Sampler::WrapMode vWrap )
+{
+  if( NULL != mSceneObject )
+  {
+    SetWrapModeMessage( GetEventThreadServices(), *mSceneObject, uWrap, vWrap );
+  }
+}
+
+void Sampler::SetAffectsTransparency( bool affectsTransparency )
+{
+  if( NULL != mSceneObject )
+  {
+    SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mAffectsTransparency, &SceneGraph::DoubleBufferedProperty<bool>::Set, affectsTransparency );
+  }
+}
+
+const SceneGraph::Sampler* Sampler::GetSamplerSceneObject() const
+{
+  return mSceneObject;
+}
+
+unsigned int Sampler::GetDefaultPropertyCount() const
+{
+  return SAMPLER_IMPL.GetDefaultPropertyCount();
+}
+
+void Sampler::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  SAMPLER_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* Sampler::GetDefaultPropertyName(Property::Index index) const
+{
+  return SAMPLER_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index Sampler::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return SAMPLER_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool Sampler::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return SAMPLER_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool Sampler::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return SAMPLER_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool Sampler::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return SAMPLER_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type Sampler::GetDefaultPropertyType( Property::Index index ) const
+{
+  return SAMPLER_IMPL.GetDefaultPropertyType( index );
+}
+
+void Sampler::SetDefaultProperty( Property::Index index,
+                                  const Property::Value& propertyValue )
+{
+  switch( index )
+  {
+    case Dali::Sampler::Property::MINIFICATION_FILTER:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mMinFilter, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Sampler::Property::MAGNIGICATION_FILTER:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mMagFilter, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Sampler::Property::U_WRAP:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mUWrapMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Sampler::Property::V_WRAP:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<int>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mVWrapMode, &SceneGraph::DoubleBufferedProperty<int>::Set, propertyValue.Get<int>() );
+      break;
+    }
+    case Dali::Sampler::Property::AFFECTS_TRANSPARENCY:
+    {
+      SceneGraph::DoubleBufferedPropertyMessage<bool>::Send( GetEventThreadServices(), mSceneObject, &mSceneObject->mAffectsTransparency, &SceneGraph::DoubleBufferedProperty<bool>::Set, propertyValue.Get<bool>() );
+      break;
+    }
+  }
+}
+
+void Sampler::SetSceneGraphProperty( Property::Index index,
+                                     const PropertyMetadata& entry,
+                                     const Property::Value& value )
+{
+  SAMPLER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+  OnPropertySet(index, value);
+}
+
+Property::Value Sampler::GetDefaultProperty( Property::Index index ) const
+{
+  BufferIndex bufferIndex = GetEventThreadServices().GetEventBufferIndex();
+  Property::Value value;
+
+  switch( index )
+  {
+    case Dali::Sampler::Property::MINIFICATION_FILTER:
+    {
+      value = mSceneObject->mMinFilter[bufferIndex];
+      break;
+    }
+    case Dali::Sampler::Property::MAGNIGICATION_FILTER:
+    {
+      value = mSceneObject->mMagFilter[bufferIndex];
+      break;
+    }
+    case Dali::Sampler::Property::U_WRAP:
+    {
+      value = mSceneObject->mUWrapMode[bufferIndex];
+      break;
+    }
+    case Dali::Sampler::Property::V_WRAP:
+    {
+      value = mSceneObject->mVWrapMode[bufferIndex];
+      break;
+    }
+    case Dali::Sampler::Property::AFFECTS_TRANSPARENCY:
+    {
+      value = mSceneObject->mAffectsTransparency[bufferIndex];
+      break;
+    }
+  }
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Sampler::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* Sampler::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* Sampler::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
+
+  const SceneGraph::PropertyBase* property = NULL;
+
+  if( OnStage() )
+  {
+    property = SAMPLER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                             &Sampler::FindAnimatableProperty,
+                                                             &Sampler::FindCustomProperty,
+                                                             index );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      // No animatable default props
+      DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
+    }
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* Sampler::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  if( OnStage() )
+  {
+    const SceneGraph::PropertyBase* baseProperty =
+      SAMPLER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                    &Sampler::FindAnimatableProperty,
+                                                    &Sampler::FindCustomProperty,
+                                                    index );
+    property = static_cast<const PropertyInputImpl*>( baseProperty );
+
+    if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+    {
+      switch( index )
+      {
+        case Dali::Sampler::Property::MINIFICATION_FILTER:
+        {
+          property = &mSceneObject->mMinFilter;
+          break;
+        }
+        case Dali::Sampler::Property::MAGNIGICATION_FILTER:
+        {
+          property = &mSceneObject->mMagFilter;
+          break;
+        }
+        case Dali::Sampler::Property::U_WRAP:
+        {
+          property = &mSceneObject->mUWrapMode;
+          break;
+        }
+        case Dali::Sampler::Property::V_WRAP:
+        {
+          property = &mSceneObject->mVWrapMode;
+          break;
+        }
+        case Dali::Sampler::Property::AFFECTS_TRANSPARENCY:
+        {
+          property = &mSceneObject->mAffectsTransparency;
+          break;
+        }
+      }
+    }
+  }
+
+  return property;
+}
+
+int Sampler::GetPropertyComponentIndex( Property::Index index ) const
+{
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+bool Sampler::OnStage() const
+{
+  return mOnStage;
+}
+
+void Sampler::Connect()
+{
+  mOnStage = true;
+
+  mImageConnector.OnStageConnect();
+
+  // sceneObject is being used in a separate thread; queue a message to set
+  unsigned int resourceId = mImageConnector.Get()->GetResourceId();
+  SetTextureMessage( GetEventThreadServices(), *mSceneObject, resourceId );
+}
+
+void Sampler::Disconnect()
+{
+  mOnStage = false;
+
+  mImageConnector.OnStageDisconnect();
+}
+
+Sampler::Sampler()
+: mSceneObject( NULL ),
+  mOnStage( false )
+{
+}
+
+void Sampler::Initialize( const std::string& textureUnitUniformName )
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  mSceneObject = new SceneGraph::Sampler( textureUnitUniformName );
+  AddMessage( updateManager, updateManager.GetSamplerOwner(), *mSceneObject );
+
+  eventThreadServices.RegisterObject( this );
+}
+
+Sampler::~Sampler()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveMessage( updateManager, updateManager.GetSamplerOwner(), *mSceneObject );
+
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/rendering/sampler-impl.h b/dali/internal/event/rendering/sampler-impl.h
new file mode 100644 (file)
index 0000000..340f140
--- /dev/null
@@ -0,0 +1,235 @@
+#ifndef DALI_INTERNAL_SAMPLER_H
+#define DALI_INTERNAL_SAMPLER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/devel-api/rendering/sampler.h> // Dali::Sampler
+#include <dali/internal/event/common/connectable.h> // Dali::Internal::Connectable
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+#include <dali/internal/event/images/image-connector.h> // Dali::Internal::ImageConnector
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Sampler;
+}
+
+class Sampler;
+typedef IntrusivePtr<Sampler> SamplerPtr;
+
+/**
+ * Sampler is an object that contains an array of structures of values that
+ * can be accessed as properties.
+ */
+class Sampler : public Object, public Connectable
+{
+public:
+
+  /**
+   * Create a new Sampler.
+   * @return A smart-pointer to the newly allocated Sampler.
+   */
+  static SamplerPtr New( const std::string& textureUnitUniformName );
+
+  /**
+   * @copydoc Dali::Sampler::SetUniformName()
+   */
+  void SetTextureUnitUniformName( const std::string& name );
+
+  /**
+   * @copydoc Dali::Sampler::SetImage()
+   */
+  void SetImage( ImagePtr& image );
+
+  /**
+   * @copydoc Dali::Sampler::GetImage()
+   */
+  ImagePtr GetImage() const;
+
+  /**
+   * @copydoc Dali::Sampler::SetFilterMode()
+   */
+  void SetFilterMode( Dali::Sampler::FilterMode minFilter, Dali::Sampler::FilterMode magFilter );
+
+  /**
+   * @copydoc Dali::Sampler::SetWrapMode()
+   */
+  void SetWrapMode( Dali::Sampler::WrapMode uWrap, Dali::Sampler::WrapMode vWrap );
+
+  /**
+   * @copydoc Dali::Sampler::SetAffectsTransparency()
+   */
+  void SetAffectsTransparency( bool affectsTransparency );
+
+  /**
+   * @brief Get the sampler scene object
+   *
+   * @return the sampler scene object
+   */
+  const SceneGraph::Sampler* GetSamplerSceneObject() const;
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+public: // Functions from Connectable
+  /**
+   * @copydoc Dali::Internal::Connectable::OnStage()
+   */
+  virtual bool OnStage() const;
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Connect()
+   */
+  virtual void Connect();
+
+  /**
+   * @copydoc Dali::Internal::Connectable::Disconnect()
+   */
+  virtual void Disconnect();
+
+private:
+  Sampler();
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize( const std::string& textureUnitUniformName );
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Sampler();
+
+private: // data
+  //TODO: MESH_REWORK : change to ObjectConnector
+  ImageConnector mImageConnector;
+  SceneGraph::Sampler* mSceneObject;
+  bool mOnStage;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::Sampler& GetImplementation(Dali::Sampler& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "Sampler handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Sampler&>(object);
+}
+
+inline const Internal::Sampler& GetImplementation(const Dali::Sampler& handle)
+{
+  DALI_ASSERT_ALWAYS(handle && "Sampler handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Sampler&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SAMPLER_H
diff --git a/dali/internal/event/rendering/shader-impl.cpp b/dali/internal/event/rendering/shader-impl.cpp
new file mode 100644 (file)
index 0000000..ecf64cb
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/rendering/shader-impl.h> // Dali::Internal::Shader
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/shader-effects/shader-effect.h> // Dali::ShaderEffect::GeometryHints // TODO: MESH_REWORK REMOVE
+#include <dali/devel-api/rendering/shader.h> // Dali::Shader
+
+#include <dali/internal/event/common/object-impl-helper.h> // Dali::Internal::ObjectHelper
+#include <dali/internal/event/common/property-helper.h> // DALI_PROPERTY_TABLE_BEGIN, DALI_PROPERTY, DALI_PROPERTY_TABLE_END
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/effects/shader-factory.h>
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ *            |name             |type    |writable|animatable|constraint-input|enum for index-checking|
+ */
+DALI_PROPERTY_TABLE_BEGIN
+DALI_PROPERTY( "program",       MAP,     true,     false,     false,  Dali::Shader::Property::PROGRAM )
+DALI_PROPERTY( "shader-hints",  INTEGER, true,     false,     true,   Dali::Shader::Property::SHADER_HINTS )
+DALI_PROPERTY_TABLE_END( DEFAULT_ACTOR_PROPERTY_START_INDEX )
+
+const ObjectImplHelper<DEFAULT_PROPERTY_COUNT> SHADER_IMPL = { DEFAULT_PROPERTY_DETAILS };
+
+BaseHandle Create()
+{
+  return Dali::BaseHandle();
+}
+
+TypeRegistration mType( typeid( Dali::Shader ), typeid( Dali::Handle ), Create );
+
+} // unnamed namespace
+
+ShaderPtr Shader::New( const std::string& vertexShader,
+                       const std::string& fragmentShader,
+                       Dali::Shader::ShaderHints hints )
+{
+  //TODO: MESH_REWORK
+  ShaderPtr shader( new Shader() );
+  shader->Initialize( vertexShader, fragmentShader, hints );
+  return shader;
+}
+
+const SceneGraph::Shader* Shader::GetShaderSceneObject() const
+{
+  return mSceneObject;
+}
+
+unsigned int Shader::GetDefaultPropertyCount() const
+{
+  return SHADER_IMPL.GetDefaultPropertyCount();
+}
+
+void Shader::GetDefaultPropertyIndices( Property::IndexContainer& indices ) const
+{
+  SHADER_IMPL.GetDefaultPropertyIndices( indices );
+}
+
+const char* Shader::GetDefaultPropertyName(Property::Index index) const
+{
+  return SHADER_IMPL.GetDefaultPropertyName( index );
+}
+
+Property::Index Shader::GetDefaultPropertyIndex( const std::string& name ) const
+{
+  return SHADER_IMPL.GetDefaultPropertyIndex( name );
+}
+
+bool Shader::IsDefaultPropertyWritable( Property::Index index ) const
+{
+  return SHADER_IMPL.IsDefaultPropertyWritable( index );
+}
+
+bool Shader::IsDefaultPropertyAnimatable( Property::Index index ) const
+{
+  return SHADER_IMPL.IsDefaultPropertyAnimatable( index );
+}
+
+bool Shader::IsDefaultPropertyAConstraintInput( Property::Index index ) const
+{
+  return SHADER_IMPL.IsDefaultPropertyAConstraintInput( index );
+}
+
+Property::Type Shader::GetDefaultPropertyType( Property::Index index ) const
+{
+  return SHADER_IMPL.GetDefaultPropertyType( index );
+}
+
+void Shader::SetDefaultProperty( Property::Index index,
+                                 const Property::Value& propertyValue )
+{
+  switch(index)
+  {
+    case Dali::Shader::Property::PROGRAM:
+    {
+      // @todo MESH_REWORK Set program again?
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+    case Dali::Shader::Property::SHADER_HINTS:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+  }
+}
+
+void Shader::SetSceneGraphProperty( Property::Index index,
+                                    const PropertyMetadata& entry,
+                                    const Property::Value& value )
+{
+  SHADER_IMPL.SetSceneGraphProperty( GetEventThreadServices(), this, index, entry, value );
+  OnPropertySet(index, value);
+}
+
+Property::Value Shader::GetDefaultProperty( Property::Index index ) const
+{
+  Property::Value value;
+
+  switch(index)
+  {
+    case Dali::Shader::Property::PROGRAM:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+    case Dali::Shader::Property::SHADER_HINTS:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "MESH_REWORK" );
+      break;
+    }
+  }
+
+  return value;
+}
+
+const SceneGraph::PropertyOwner* Shader::GetPropertyOwner() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyOwner* Shader::GetSceneObject() const
+{
+  return mSceneObject;
+}
+
+const SceneGraph::PropertyBase* Shader::GetSceneObjectAnimatableProperty( Property::Index index ) const
+{
+  DALI_ASSERT_ALWAYS( IsPropertyAnimatable( index ) && "Property is not animatable" );
+  const SceneGraph::PropertyBase* property = NULL;
+
+  property = SHADER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                          &Shader::FindAnimatableProperty,
+                                                          &Shader::FindCustomProperty,
+                                                          index );
+
+  if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    DALI_ASSERT_ALWAYS( 0 && "Property is not animatable" );
+  }
+
+  return property;
+}
+
+const PropertyInputImpl* Shader::GetSceneObjectInputProperty( Property::Index index ) const
+{
+  const PropertyInputImpl* property = NULL;
+
+  const SceneGraph::PropertyBase* baseProperty =
+    SHADER_IMPL.GetRegisteredSceneGraphProperty( this,
+                                                 &Shader::FindAnimatableProperty,
+                                                 &Shader::FindCustomProperty,
+                                                 index );
+  property = static_cast<const PropertyInputImpl*>( baseProperty );
+
+  if( property == NULL && index < DEFAULT_PROPERTY_MAX_COUNT )
+  {
+    if( index == Dali::Shader::Property::SHADER_HINTS )
+    {
+      // @todo MESH_REWORK - return the property
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( 0 && "Property is not a valid constraint input" );
+    }
+  }
+
+  return property;
+}
+
+int Shader::GetPropertyComponentIndex( Property::Index index ) const
+{
+  return Property::INVALID_COMPONENT_INDEX;
+}
+
+Shader::Shader()
+: mSceneObject( NULL )
+{
+}
+
+void Shader::Initialize(
+  const std::string& vertexSource,
+  const std::string& fragmentSource,
+  Dali::Shader::ShaderHints hints )
+{
+  EventThreadServices& eventThreadServices = GetEventThreadServices();
+  SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+
+  // @todo MESH_REWORK - Pass hints directly to a new scene graph shader
+  int effectHint = Dali::ShaderEffect::HINT_NONE;
+  if( hints & Dali::Shader::HINT_OUTPUT_IS_TRANSPARENT )
+  {
+    effectHint |= Dali::ShaderEffect::HINT_BLENDING;
+  }
+
+  if( hints & Dali::Shader::HINT_REQUIRES_SELF_DEPTH_TEST )
+  {
+    effectHint |= Dali::ShaderEffect::HINT_DEPTH_BUFFER;
+  }
+
+  if( (hints & Dali::Shader::HINT_MODIFIES_GEOMETRY) == 0x0 )
+  {
+    effectHint |= Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY;
+  }
+  Dali::ShaderEffect::GeometryHints shaderEffectHint = static_cast<Dali::ShaderEffect::GeometryHints>( effectHint );
+
+  mSceneObject = new SceneGraph::Shader( shaderEffectHint );
+
+  // Add to update manager
+  AddShaderMessage( updateManager, *mSceneObject );
+
+  // Try to load a precompiled shader binary for the source pair:
+  ThreadLocalStorage& tls = ThreadLocalStorage::Get();
+  ShaderFactory& shaderFactory = tls.GetShaderFactory();
+  size_t shaderHash;
+  Internal::ShaderDataPtr shaderData = shaderFactory.Load( vertexSource, fragmentSource, shaderHash );
+
+  // Add shader program to scene-object using a message to the UpdateManager
+  SetShaderProgramMessage( updateManager, *mSceneObject, shaderData, (hints & Dali::Shader::HINT_MODIFIES_GEOMETRY) != 0x0 );
+  eventThreadServices.RegisterObject( this );
+}
+
+Shader::~Shader()
+{
+  if( EventThreadServices::IsCoreRunning() )
+  {
+    EventThreadServices& eventThreadServices = GetEventThreadServices();
+    SceneGraph::UpdateManager& updateManager = eventThreadServices.GetUpdateManager();
+    RemoveShaderMessage( updateManager, *mSceneObject);
+
+    eventThreadServices.UnregisterObject( this );
+  }
+}
+
+
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/event/rendering/shader-impl.h b/dali/internal/event/rendering/shader-impl.h
new file mode 100644 (file)
index 0000000..a1b25cf
--- /dev/null
@@ -0,0 +1,190 @@
+#ifndef DALI_INTERNAL_SHADER_H
+#define DALI_INTERNAL_SHADER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h> // DALI_ASSERT_ALWAYS
+#include <dali/public-api/common/intrusive-ptr.h> // Dali::IntrusivePtr
+#include <dali/devel-api/rendering/shader.h> // Dali::Shader
+#include <dali/internal/event/common/object-connector.h> // Dali::Internal::ObjectConnector
+#include <dali/internal/event/common/object-impl.h> // Dali::Internal::Object
+#include <dali/internal/event/resources/resource-ticket.h> // Dali::Internal::ResourceTicketPtr
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Shader;
+}
+
+class Shader;
+typedef IntrusivePtr<Shader> ShaderPtr;
+
+/**
+ * Shader is an object that contains an array of structures of values that
+ * can be accessed as properties.
+ */
+class Shader : public Object
+{
+public:
+
+  /**
+   * @copydoc Dali::Shader::New()
+   */
+  static ShaderPtr New( const std::string& vertexShader,
+                        const std::string& fragmentShader,
+                        Dali::Shader::ShaderHints hints );
+
+  /**
+   * @brief Get the shader scene object
+   *
+   * @return the shader scene object
+   */
+  const SceneGraph::Shader* GetShaderSceneObject() const;
+
+public: // Default property extensions from Object
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyCount()
+   */
+  virtual unsigned int GetDefaultPropertyCount() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndices()
+   */
+  virtual void GetDefaultPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyName()
+   */
+  virtual const char* GetDefaultPropertyName(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyIndex()
+   */
+  virtual Property::Index GetDefaultPropertyIndex(const std::string& name) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyWritable()
+   */
+  virtual bool IsDefaultPropertyWritable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAnimatable()
+   */
+  virtual bool IsDefaultPropertyAnimatable(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::IsDefaultPropertyAConstraintInput()
+   */
+  virtual bool IsDefaultPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultPropertyType()
+   */
+  virtual Property::Type GetDefaultPropertyType(Property::Index index) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::SetDefaultProperty()
+   */
+  virtual void SetDefaultProperty(Property::Index index, const Property::Value& propertyValue);
+
+  /**
+   * @copydoc Dali::Internal::Object::SetSceneGraphProperty()
+   */
+  virtual void SetSceneGraphProperty( Property::Index index, const PropertyMetadata& entry, const Property::Value& value );
+
+  /**
+   * @copydoc Dali::Internal::Object::GetDefaultProperty()
+   */
+  virtual Property::Value GetDefaultProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyOwner()
+   */
+  virtual const SceneGraph::PropertyOwner* GetPropertyOwner() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObject()
+   */
+  virtual const SceneGraph::PropertyOwner* GetSceneObject() const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectAnimatableProperty()
+   */
+  virtual const SceneGraph::PropertyBase* GetSceneObjectAnimatableProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetSceneObjectInputProperty()
+   */
+  virtual const PropertyInputImpl* GetSceneObjectInputProperty( Property::Index index ) const;
+
+  /**
+   * @copydoc Dali::Internal::Object::GetPropertyComponentIndex()
+   */
+  virtual int GetPropertyComponentIndex( Property::Index index ) const;
+
+private: // implementation
+  Shader();
+
+  /**
+   * Second stage initialization
+   */
+  void Initialize( const std::string& vertexShader, const std::string& fragmentShader, Dali::Shader::ShaderHints hints );
+
+protected:
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~Shader();
+
+private: // unimplemented methods
+  Shader( const Shader& );
+  Shader& operator=( const Shader& );
+
+private:
+  SceneGraph::Shader* mSceneObject;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+inline Internal::Shader& GetImplementation( Dali::Shader& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Shader handle is empty");
+
+  BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<Internal::Shader&>(object);
+}
+
+inline const Internal::Shader& GetImplementation( const Dali::Shader& handle )
+{
+  DALI_ASSERT_ALWAYS(handle && "Shader handle is empty");
+
+  const BaseObject& object = handle.GetBaseObject();
+
+  return static_cast<const Internal::Shader&>(object);
+}
+
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SHADER_H
diff --git a/dali/internal/event/resources/archive.cpp b/dali/internal/event/resources/archive.cpp
new file mode 100644 (file)
index 0000000..a2400e3
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/resources/archive.h>
+
+// EXTERNAL INCLUDES
+#include <fstream>
+#include <ios>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/quaternion.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/*--------- Archive ---------*/
+
+Archive::Archive(std::streambuf& buf)
+: mVersion(0),
+  mStream(&buf),
+  mResult(true)
+{
+}
+
+Archive::~Archive()
+{
+  if(!mChunkStack.empty())
+  {
+    DALI_LOG_ERROR("mChunkStack should be empty!");
+  }
+}
+
+
+/*--------- OutputArchive ---------*/
+
+OutputArchive::OutputArchive(std::streambuf& buf, const unsigned int version)
+: Archive(buf)
+{
+  SetVersion(version);
+}
+
+OutputArchive::~OutputArchive()
+{
+}
+
+bool OutputArchive::Write(const char* data, const unsigned int length)
+{
+  if( mResult )
+  {
+    mStream.write(data, length);
+    if( mStream.bad() )
+    {
+      mResult = false;
+    }
+  }
+  return mResult;
+}
+
+bool OutputArchive::OpenChunk(const unsigned int fourCC)
+{
+  const unsigned int zero = 0;
+
+  // Get current position in stream
+  std::streampos currentPos = mStream.tellp();
+
+  // Ensure chunk will start at an even byte
+  // (necessary for nested chunks)
+  if( currentPos & 1 )
+  {
+    const char padding = 0;
+    Write(&padding, sizeof(char));
+  }
+
+  // Write chunk header to stream
+  Write(reinterpret_cast<const char*>(&fourCC), sizeof(unsigned int));
+
+  // Push chunkHeader information to chunk LIFO stack
+  mChunkStack.push(std::make_pair(fourCC, mStream.tellp()));
+
+  // Write zero for chunk length temporarily. This will be overwritten in CloseChunk
+  Write(reinterpret_cast<const char*>(&zero), sizeof(unsigned int));
+
+  return mResult;
+}
+
+void OutputArchive::CloseChunk()
+{
+  // Get current position in stream
+  std::streampos currentPos = mStream.tellp();
+
+  // retrieve chunk header
+  ChunkHeader chunkHeader = mChunkStack.top();
+  mChunkStack.pop();
+
+  // seek to chunk header in stream
+  mStream.seekp(chunkHeader.second);
+
+  // calculate and write chunk size
+  unsigned int chunkLength = static_cast<unsigned int>(currentPos - chunkHeader.second) - sizeof(unsigned int);
+  Write(reinterpret_cast<const char*>(&chunkLength), sizeof(unsigned int));
+
+  // return to current position in stream
+  mStream.seekp(currentPos);
+
+  // Ensure next chunk will start at on even byte
+  if( currentPos & 1 )
+  {
+    const char padding = 0;
+    Write(&padding, 1);
+  }
+}
+
+
+/*--------- InputArchive ---------*/
+
+InputArchive::InputArchive(std::streambuf& buf, const unsigned int version)
+: Archive(buf),
+  mFileVersion(0)
+{
+  SetVersion(version);
+}
+
+InputArchive::~InputArchive()
+{
+}
+
+bool InputArchive::Read(char* data, const unsigned int length)
+{
+  if( mResult )
+  {
+    mStream.read(data, length);
+    if( mStream.bad() )
+    {
+      mResult = false;
+    }
+  }
+  return mResult;
+}
+
+bool InputArchive::OpenChunk(const unsigned int fourCC)
+{
+  if( PeekChunk() != fourCC )
+  {
+    // trying to open incorrect chunk, mark archive error
+    mResult = false;
+    return mResult;
+  }
+
+  union
+  {
+    unsigned int fourCC_int;
+    char fourCC_char[4];
+  };
+  fourCC_int = 0;
+
+  if( mStream.tellg() & 1 )
+  {
+    mStream.seekg(1, std::ios_base::cur);
+  }
+
+  Read(fourCC_char, sizeof(unsigned int));
+
+  // Push chunkHeader information to chunk LIFO stack
+  mChunkStack.push(std::make_pair(fourCC_int, mStream.tellg()));
+
+# if defined(DEBUG_ENABLED)
+
+  unsigned int chunkLength;
+  Read(reinterpret_cast<char*>(&chunkLength), sizeof(unsigned int));
+
+  DALI_LOG_INFO(Debug::Filter::gModel, Debug::Verbose, "Enter: %c%c%c%c(%d)\n",
+                fourCC_char[0], fourCC_char[1], fourCC_char[2], fourCC_char[3], chunkLength);
+
+# else  // defined(DEBUG_ENABLED)
+
+  // skip chunk length
+  mStream.seekg(sizeof(unsigned int), std::ios_base::cur);
+
+# endif // defined(DEBUG_ENABLED)
+
+  return mResult;
+}
+
+void InputArchive::SkipChunk(const unsigned int fourCC)
+{
+  // Ensure the next chunk is the correct one
+  if( PeekChunk() != fourCC )
+  {
+    return;
+  }
+
+  union
+  {
+    unsigned int fourCC_int;
+    char fourCC_char[4];
+  };
+  unsigned int chunkLength;
+
+  if( mStream.tellg() & 1 )
+  {
+    mStream.seekg(1, std::ios_base::cur);
+  }
+
+  Read(fourCC_char, sizeof(unsigned int));
+  Read(reinterpret_cast<char*>(&chunkLength), sizeof(unsigned int));
+
+  DALI_LOG_INFO(Debug::Filter::gModel, Debug::Verbose, "Enter: %c%c%c%c(%d)\n",
+                fourCC_char[0], fourCC_char[1], fourCC_char[2], fourCC_char[3], chunkLength);
+
+  if( chunkLength & 1 )
+  {
+    ++chunkLength;
+  }
+
+  mStream.seekg(chunkLength, std::ios_base::cur);
+}
+
+void InputArchive::CloseChunk()
+{
+  ChunkHeader chunkHeader = mChunkStack.top();
+  mChunkStack.pop();
+
+  mStream.seekg(chunkHeader.second);
+
+  unsigned int chunkLength;
+  Read(reinterpret_cast<char*>(&chunkLength), sizeof(unsigned int));
+
+  if( chunkLength & 1)
+  {
+    ++chunkLength;
+  }
+  mStream.seekg(chunkLength, std::ios_base::cur);
+}
+
+unsigned int InputArchive::PeekChunk()
+{
+  union
+  {
+    unsigned int fourCC_int;
+    char fourCC_char[4];
+  };
+  fourCC_int = 0;
+
+  // Get current position in stream
+  std::streampos currentPos = mStream.tellg();
+
+  // Ensure next read will be from an even byte
+  if( currentPos & 1 )
+  {
+    mStream.seekg(1, std::ios_base::cur);
+  }
+
+  // Read tag
+  Read(fourCC_char, sizeof(unsigned int));
+
+# if defined(DEBUG_ENABLED)
+  unsigned int chunkLength;
+  Read(reinterpret_cast<char*>(&chunkLength), sizeof(unsigned int));
+
+  DALI_LOG_INFO(Debug::Filter::gModel, Debug::Verbose, "Peek: %c%c%c%c(%d)\n",
+                fourCC_char[0], fourCC_char[1], fourCC_char[2], fourCC_char[3], chunkLength);
+# endif // defined(DEBUG_ENABLED)
+
+  // return to original position in stream
+  mStream.seekg(currentPos);
+
+  return fourCC_int;
+}
+
+namespace Serialize
+{
+/*------ serialization overrides of operator<< () and operator>> () ------*/
+
+Archive& operator<< (Archive& ar, const char& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, char& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const unsigned char& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, unsigned char& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const bool& t)
+{
+  char value = t ? 1 : 0;
+  ar.Write(&value, sizeof(value));
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, bool& t)
+{
+  char value;
+  ar.Read(&value, sizeof(value));
+  t = value != 0;
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const short& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, short& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const unsigned short& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, unsigned short& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const int& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, int& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator<< (Archive& ar, const unsigned int& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, unsigned int& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+// float
+Archive& operator<< (Archive& ar, const float& t)
+{
+  ar.Write((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, float& t)
+{
+  ar.Read((char*)&t, sizeof(t));
+
+  return ar;
+}
+
+// Vector2
+Archive& operator<< (Archive& ar, const Vector2& t)
+{
+  ar << t.x << t.y;
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, Vector2& t)
+{
+  ar >> t.x >> t.y;
+  return ar;
+}
+
+// Vector3
+Archive& operator<< (Archive& ar, const Vector3& t)
+{
+  ar << t.x << t.y << t.z;
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, Vector3& t)
+{
+  ar >> t.x >> t.y >> t.z;
+  return ar;
+}
+
+// Vector4
+Archive& operator<< (Archive& ar, const Vector4& t)
+{
+  ar << t.x << t.y << t.z << t.w;
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, Vector4& t)
+{
+  ar >> t.x >> t.y >> t.z >> t.w;
+  return ar;
+}
+
+// Quaternion
+Archive& operator<< (Archive& ar, const Quaternion& t)
+{
+  ar << t.mVector;
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, Quaternion& t)
+{
+  ar >> t.mVector;
+
+  return ar;
+}
+
+// Matrix
+Archive& operator<< (Archive& ar, const Matrix& t)
+{
+  const float* data = t.AsFloat();
+
+  for( unsigned i = 0; i < sizeof(Matrix) / sizeof(float); ++i)
+  {
+    ar << *data;
+    ++data;
+  }
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, Matrix& t)
+{
+  float* data = t.AsFloat();
+
+  for( unsigned i = 0; i < sizeof(Matrix) / sizeof(float); ++i)
+  {
+    ar >> *data;
+    ++data;
+  }
+
+  return ar;
+}
+
+/*---- std::string ----*/
+Archive& operator<< (Archive& ar, const std::string& t)
+{
+  unsigned int length = t.size();
+  ar << length;
+  ar.Write(t.data(), length);
+
+  return ar;
+}
+
+Archive& operator>> (Archive& ar, std::string& t)
+{
+  unsigned int length = 0;
+  char* data = NULL;
+
+  ar >> length;
+  data = new char[ length ];
+  ar.Read(data, length);
+  t.assign(data, length);
+  delete [] data;
+
+  return ar;
+}
+
+} // namespace Serialize
+
+} // Internal
+
+} // Dali
+
diff --git a/dali/internal/event/resources/archive.h b/dali/internal/event/resources/archive.h
new file mode 100644 (file)
index 0000000..2cd0d93
--- /dev/null
@@ -0,0 +1,283 @@
+#if !defined(__DALI_INTERNAL_ARCHIVE_H__)
+#define __DALI_INTERNAL_ARCHIVE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <iostream>
+#include <stack>
+
+namespace Dali
+{
+struct Vector2;
+struct Vector3;
+struct Vector4;
+class Matrix;
+class Quaternion;
+
+namespace Internal
+{
+
+/**
+ * Archive class. Serializes data to a Tag-Length-Value archive
+ */
+class Archive
+{
+public:
+  typedef std::pair<unsigned int, std::streampos> ChunkHeader;
+
+public:
+  /**
+   * Constructor
+   * @param[in] buf An open streambuf
+   */
+  Archive(std::streambuf& buf);
+
+  /**
+   * Destructor
+   */
+  virtual ~Archive();
+
+  /**
+   * Get archive version
+   */
+  unsigned int GetVersion() const
+  {
+    return mVersion;
+  }
+
+  /**
+   * Set archive version
+   * @param[in] version the version number
+   */
+  void SetVersion(const unsigned int version)
+  {
+    mVersion = version;
+  }
+
+  /**
+   * Returns the result of the archiving operation
+   * The result status is initialised to true on construction
+   * Any failure will set it to false
+   * @return the archiving result, true signals success.
+   */
+  bool GetResult() const
+  {
+    return mResult;
+  }
+
+  /**
+   * Set the archive status to failed
+   */
+  void SetResultFailed()
+  {
+    mResult = false;
+  }
+
+  /**
+   * Write a bytestream to the archive
+   * @param[in] data    A pointer to the data
+   * @param[in] length  The length of the data in bytes
+   * @return            true if the data was successfully written
+   */
+  virtual bool Write(const char* data, const unsigned int length)
+  {
+    return false;
+  }
+
+  /**
+   * Read a bytestream from the archive
+   * @param[in] data    A pointer to a buffer to store the data
+   * @param[in] length  The length of the data in bytes
+   * @return            true if the data was successfully read
+   */
+  virtual bool Read(char* data, const unsigned int length)
+  {
+    return false;
+  }
+
+  /**
+   * Open a new chunk
+   * @param[in] tag The FourCC tag for the chunk
+   * @return true if success.
+   */
+  virtual bool OpenChunk(const unsigned int tag) = 0;
+
+  /**
+   * Skip an entire chunk
+   * @param[in] tag The FourCC tag for the chunk
+   */
+  virtual void SkipChunk(const unsigned int tag)
+  {
+  }
+
+  /**
+   * Close the current chunk
+   * The chunk length is written to the archive
+   */
+  virtual void CloseChunk() = 0;
+
+  /**
+   * Peek at the tag of the next chunk.
+   * This will move the file pointer to the next even byte,
+   * then read the next four bytes
+   * @result The FourCC tag for the next chunk.
+   */
+  virtual unsigned int PeekChunk()
+  {
+    return 0;
+  }
+
+protected:
+  unsigned int            mVersion;
+  std::iostream           mStream;
+  std::stack<ChunkHeader> mChunkStack;
+  bool                    mResult;
+}; // class Archive
+
+/**
+ * Archive specialization. Performs serialization to an Archive
+ */
+class OutputArchive : public Archive
+{
+public:
+  OutputArchive(std::streambuf& buf, const unsigned int version);
+  virtual ~OutputArchive();
+
+public: // from Archive
+  /**
+   * @copydoc Archive::Write()
+   */
+  virtual bool Write(const char* data, const unsigned int length);
+
+  /**
+   * @copydoc Archive::OpenChunk()
+   * @param[in] tag The chunk tag
+   */
+  virtual bool OpenChunk(const unsigned int tag);
+
+  /**
+   * @copydoc Archive::CloseChunk()
+   */
+  virtual void CloseChunk();
+
+}; // class OutputArchive
+
+/**
+ * Archive specialization. Performs serialization from an Archive
+ */
+class InputArchive : public Archive
+{
+public:
+  InputArchive(std::streambuf& buf, const unsigned int version);
+  virtual ~InputArchive();
+
+public: // from Archive
+  /**
+   * @copydoc Archive::Read()
+   */
+  virtual bool Read(char* data, const unsigned int length);
+
+  /**
+   * @copydoc Archive::OpenChunk()
+   * @param[in] tag The chunk tag
+   */
+  virtual bool OpenChunk(const unsigned int tag);
+
+  /**
+   * @copydoc Archive::SkipChunk()
+   * @param[in] tag The chunk tag
+   */
+  virtual void SkipChunk(const unsigned int tag);
+
+  /**
+   * @copydoc Archive::CloseChunk()
+   */
+  virtual void CloseChunk();
+
+  /**
+   * @copydoc Archive::PeekChunk()
+   */
+  virtual unsigned int PeekChunk();
+
+public:
+  /**
+   * Set the archive version as read from the archive
+   * @param[in] version The archives version number
+   */
+  void SetFileVersion(unsigned int version)
+  {
+    mFileVersion = version;
+  }
+
+  /**
+   * Get the archive version number read from the archive
+   */
+  unsigned int GetFileVersion() const
+  {
+    return mFileVersion;
+  }
+private:
+  unsigned int  mFileVersion;
+
+}; // class InputArchive
+
+namespace Serialize
+{
+
+Archive& operator<< (Archive&, const char&);
+Archive& operator>> (Archive&, char&);
+Archive& operator<< (Archive&, const unsigned char&);
+Archive& operator>> (Archive&, unsigned char&);
+Archive& operator<< (Archive&, const bool&);
+Archive& operator>> (Archive&, bool&);
+Archive& operator<< (Archive&, const short&);
+Archive& operator>> (Archive&, short&);
+Archive& operator<< (Archive&, const unsigned short&);
+Archive& operator>> (Archive&, unsigned short&);
+Archive& operator<< (Archive&, const int&);
+Archive& operator>> (Archive&, int&);
+Archive& operator<< (Archive&, const unsigned int&);
+Archive& operator>> (Archive&, unsigned int&);
+Archive& operator<< (Archive&, const float&);
+Archive& operator>> (Archive&, float&);
+
+Archive& operator<< (Archive&, const std::string&);
+Archive& operator>> (Archive&, std::string&);
+
+// math
+Archive& operator<< (Archive&, const Vector2&);
+Archive& operator>> (Archive&, Vector2&);
+Archive& operator<< (Archive&, const Vector3&);
+Archive& operator>> (Archive&, Vector3&);
+Archive& operator<< (Archive&, const Vector4&);
+Archive& operator>> (Archive&, Vector4&);
+Archive& operator<< (Archive&, const Quaternion&);
+Archive& operator>> (Archive&, Quaternion&);
+Archive& operator<< (Archive&, const Matrix&);
+Archive& operator>> (Archive&, Matrix&);
+
+} // namespace Serialize
+} // Internal
+
+} // Dali
+
+#endif // !defined(__DALI_INTERNAL_ARCHIVE_H__)
+
+
diff --git a/dali/internal/event/resources/image-ticket.cpp b/dali/internal/event/resources/image-ticket.cpp
new file mode 100644 (file)
index 0000000..e815791
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/resources/image-ticket.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ImageTicket::ImageTicket( ResourceTicketLifetimeObserver& observer, unsigned int id, ResourceTypePath& typePath )
+: ResourceTicket( observer, id, typePath )
+{
+}
+
+int ImageTicket::GetWidth() const
+{
+  return mAttributes.GetWidth();
+}
+
+int ImageTicket::GetHeight() const
+{
+  return mAttributes.GetHeight();
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/resources/image-ticket.h b/dali/internal/event/resources/image-ticket.h
new file mode 100644 (file)
index 0000000..09007db
--- /dev/null
@@ -0,0 +1,124 @@
+#ifndef __DALI_INTERNAL_IMAGE_TICKET_H__
+#define __DALI_INTERNAL_IMAGE_TICKET_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/resources/resource-ticket.h>
+#include <dali/public-api/images/image.h>
+#include <dali/internal/common/image-attributes.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class ImageTicket;
+class  ResourceManager;
+
+typedef IntrusivePtr<ImageTicket>    ImageTicketPtr;
+
+/**
+ * ImageTicket is essentially the same as a ResourceTicket,
+ * except that it contains additional information about the loaded image resource.
+ * The data is the result of the resource loading request.
+ *
+ * Multi-threading note: this class should be used in the main thread only
+ * i.e. not from within Dali::Integration::Core::Render().
+ */
+class ImageTicket : public ResourceTicket
+{
+public:
+
+  /**
+   * Create an image resource request.
+   * This should only be done by the ResourceTicketRegistry.
+   * @param [in] observer A resource ticket lifetime observer.
+   * @param [in] id A unique ID for this ticket (loading request).
+   * @param [in] typePath The resource Type & Path pair.
+   */
+  ImageTicket( ResourceTicketLifetimeObserver& observer, unsigned int id, ResourceTypePath& typePath );
+
+  /**
+   * Get the attributes of an image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * Reflects the last cached values after a LoadComplete.
+   * If requested width or height was 0, they are replaced by concrete dimensions.
+   * @return a copy of the image attributes
+   */
+  const ImageAttributes& GetAttributes() const { return mAttributes;}
+
+  /**
+   * Get the width of an image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * Reflects the last cached values after a LoadComplete.
+   * If requested width or height was 0, they are replaced by concrete dimensions.
+   * @return the width
+   */
+  int GetWidth() const;
+
+  /**
+   * Get the height of an image.
+   * Only to be used after the image has finished loading.
+   * (Ticket's LoadingSucceeded callback was called)
+   * Reflects the last cached values after a LoadComplete.
+   * If requested width or height was 0, they are replaced by concrete dimensions.
+   * @return the height
+   */
+  int GetHeight() const;
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ImageTicket()
+  {
+  }
+
+private:
+
+  // Undefined copy constructor.
+  ImageTicket(const ImageTicket& typePath);
+
+  // Undefined copy constructor.
+  ImageTicket& operator=(const ImageTicket& rhs);
+
+private:
+
+  /**
+   * Loaded Image attributes (width, height, pixelformat etc.).
+   * Contains actual values only after the image has finished loading.
+   * If requested width or height was 0, the natural size is used.
+   */
+  ImageAttributes mAttributes;
+
+  /*
+   * ResourceClient needs to set dimensions and pixelformat.
+   * Image needs to know about them.
+   */
+  friend class ResourceClient;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_IMAGE_TICKET_H__
diff --git a/dali/internal/event/resources/resource-client-declarations.h b/dali/internal/event/resources/resource-client-declarations.h
new file mode 100644 (file)
index 0000000..12f17b4
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef __DALI_INTERNAL_RESOURCE_CLIENT_DECLARATIONS_H__
+#define __DALI_INTERNAL_RESOURCE_CLIENT_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/common/type-abstraction.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+template <> struct ParameterType< Integration::LoadStatus >
+: public BasicType< Integration::LoadStatus > {};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_CLIENT_DECLARATIONS_H__
diff --git a/dali/internal/event/resources/resource-client.cpp b/dali/internal/event/resources/resource-client.cpp
new file mode 100644 (file)
index 0000000..4d8a755
--- /dev/null
@@ -0,0 +1,490 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/resources/resource-client.h>
+#include <dali/devel-api/common/map-wrapper.h>
+
+#include <dali/integration-api/resource-request.h>
+#include <dali/integration-api/debug.h>
+
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/update/resources/resource-manager.h>
+
+
+namespace Dali
+{
+namespace Internal
+{
+using namespace Dali::Integration;
+
+typedef std::map<ResourceId, ResourceTicket*>        TicketContainer;
+typedef TicketContainer::iterator                    TicketContainerIter;
+typedef TicketContainer::size_type                   TicketContainerSize;
+typedef std::pair<ResourceId, ResourceTicket*>       TicketPair;
+
+typedef std::map<ResourceId, Bitmap*>                BitmapCache;
+typedef BitmapCache::iterator                        BitmapCacheIter;
+
+struct ResourceClient::Impl
+{
+  Impl()
+  : mNextId(0)
+  {
+  }
+
+  ResourceId       mNextId;
+  TicketContainer  mTickets;
+  BitmapCache      mBitmaps;
+};
+
+ResourceClient::ResourceClient( ResourceManager& resourceManager,
+                                EventThreadServices& eventThreadServices)
+: mResourceManager(resourceManager),
+  mEventThreadServices(eventThreadServices)
+{
+  mImpl = new ResourceClient::Impl();
+  mResourceManager.SetClient(*this);
+}
+
+ResourceClient::~ResourceClient()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if ( Stage::IsInstalled() )
+  {
+    for (TicketContainerIter iter = mImpl->mTickets.begin(); iter != mImpl->mTickets.end(); ++iter)
+    {
+      (*iter).second->StopLifetimeObservation();
+    }
+  }
+  delete mImpl;
+}
+
+ResourceTicketPtr ResourceClient::RequestResource(
+  const ResourceType& type,
+  const std::string& path,
+  LoadResourcePriority priority )
+{
+  ResourceTicketPtr newTicket;
+  ResourceTypePath typePath(type, path);
+  ResourceId newId = 0;
+
+  // Create the ticket first
+  // NOTE: pre-increment, otherwise we get 0 for first one.
+  newId = ++(mImpl->mNextId);
+
+  switch (type.id)
+  {
+    case ResourceBitmap:
+    {
+      const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> (type);
+      // image tickets will cache the requested parameters, which are updated on successful loading
+      ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
+      imageTicket->mAttributes.Reset( bitmapResource.size, bitmapResource.scalingMode, bitmapResource.samplingMode, bitmapResource.orientationCorrection );
+      newTicket = imageTicket;
+      break;
+    }
+
+    case ResourceNativeImage:
+    {
+      const NativeImageResourceType& nativeResource = static_cast <const NativeImageResourceType&> (type);
+      // image tickets will cache the requested parameters, which are updated on successful loading
+      ImageTicket* imageTicket = new ImageTicket(*this, newId, typePath);
+      imageTicket->mAttributes.SetSize( nativeResource.imageDimensions.GetWidth(), nativeResource.imageDimensions.GetHeight() );
+      newTicket = imageTicket;
+      break;
+    }
+    case ResourceTargetImage:
+    {
+      newTicket = new ResourceTicket(*this, newId, typePath);
+      break;
+    }
+  }
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResource(path:%s type.id:%d) newId:%u\n", path.c_str(), type.id, newId);
+
+  RequestLoadResourceMessage( mEventThreadServices, mResourceManager, newId, typePath, priority );
+  return newTicket;
+}
+
+ResourceTicketPtr ResourceClient::DecodeResource(
+  const ResourceType& type,
+  RequestBufferPtr buffer,
+  LoadResourcePriority priority )
+{
+  DALI_ASSERT_DEBUG( type.id == ResourceBitmap && "Only bitmap resources are currently decoded from memory buffers. It should be easy to expand to other resource types though. The public API function at the front and the resource thread at the back end are all that should need to be changed. The code in the middle should be agnostic to the the resource type it is conveying.\n" );
+  DALI_ASSERT_DEBUG( buffer.Get() && "Null resource buffer passed for decoding." );
+  ResourceTicketPtr newTicket;
+  if( buffer.Get() ) //< Check to avoid SEGV on a null pointer.
+  {
+    ResourceTypePath typePath( type, "" );
+    ResourceId newId = 0;
+
+    // Create the correct ticket type for the resource:
+    switch (type.id)
+    {
+      case ResourceBitmap:
+      {
+        // NOTE: pre-increment, otherwise we get 0 for first one.
+        newId = ++(mImpl->mNextId);
+        const BitmapResourceType& bitmapResource = static_cast <const BitmapResourceType&> ( type );
+        // Image tickets will cache the requested parameters, which are updated on successful loading
+        ImageTicket* imageTicket = new ImageTicket( *this, newId, typePath );
+        imageTicket->mAttributes.Reset( bitmapResource.size, bitmapResource.scalingMode, bitmapResource.samplingMode, bitmapResource.orientationCorrection );;
+        newTicket = imageTicket;
+        break;
+      }
+
+      // FALLTHROUGH:
+      case ResourceNativeImage:
+      case ResourceTargetImage:
+      {
+        DALI_LOG_ERROR( "Unsupported resource type passed for decoding from a memory buffer." );
+      }
+    }
+
+    if( newTicket )
+    {
+      mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+      DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: DecodeResource( type.id:%d ) newId:%u\n", type.id, newId);
+
+      RequestDecodeResourceMessage( mEventThreadServices, mResourceManager, newId, typePath, buffer, priority );
+    }
+  }
+  return newTicket;
+}
+
+bool ResourceClient::ReloadResource( ResourceId id, bool resetFinishedStatus, LoadResourcePriority priority )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ReloadResource(Id: %u)\n", id);
+
+  bool resourceExists = false;
+  TicketContainerIter ticketIter;
+  ticketIter = mImpl->mTickets.find(id);
+
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    resourceExists = true;
+    // The ticket is already being observed
+    ResourceTicket* ticket = ticketIter->second;
+    DALI_ASSERT_DEBUG(ticket && "Null ticket for tracked resource request." );
+    const ResourceTypePath * const typePathPtr = &ticket->GetTypePath();
+    DALI_ASSERT_DEBUG( typePathPtr );
+    RequestReloadResourceMessage( mEventThreadServices, mResourceManager, id, *typePathPtr, priority, resetFinishedStatus );
+  }
+  else
+  {
+    DALI_LOG_ERROR ("Resource %d does not exist\n", id);
+  }
+  return resourceExists;
+}
+
+ResourceTicketPtr ResourceClient::RequestResourceTicket( ResourceId id )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: RequestResourceTicket(Id: %u)\n", id);
+
+  ResourceTicketPtr ticket;
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find( id );
+
+  if ( mImpl->mTickets.end() != ticketIter )
+  {
+    ticket = ticketIter->second;
+  }
+
+  return ticket;
+}
+
+ImageTicketPtr ResourceClient::AllocateBitmapImage( unsigned int width,
+                                                    unsigned int height,
+                                                    unsigned int bufferWidth,
+                                                    unsigned int bufferHeight,
+                                                    Pixel::Format pixelformat )
+{
+  /* buffer is available via public-api, therefore not discardable */
+  Bitmap* const bitmap = Bitmap::New( Bitmap::BITMAP_2D_PACKED_PIXELS, ResourcePolicy::OWNED_RETAIN );
+  Bitmap::PackedPixelsProfile* const packedBitmap = bitmap->GetPackedPixelsProfile();
+  DALI_ASSERT_DEBUG(packedBitmap);
+
+  packedBitmap->ReserveBuffer(pixelformat, width, height, bufferWidth, bufferHeight);
+  DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
+  DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
+
+  ImageTicketPtr ticket = AddBitmapImage(bitmap);
+
+  DALI_ASSERT_DEBUG(bitmap->GetBuffer() != 0);
+  DALI_ASSERT_DEBUG(bitmap->GetBufferSize() >= width * height);
+  return ticket;
+}
+
+ImageTicketPtr ResourceClient::AddBitmapImage(Bitmap* bitmap)
+{
+  DALI_ASSERT_DEBUG( bitmap != NULL );
+
+  ImageTicketPtr newTicket;
+
+  const ResourceId newId = ++(mImpl->mNextId);
+
+  ImageAttributes imageAttributes = ImageAttributes::New(bitmap->GetImageWidth(), bitmap->GetImageHeight());
+  BitmapResourceType bitmapResourceType( ImageDimensions::FromFloatVec2( imageAttributes.GetSize() ) ); // construct first as no copy ctor (needed to bind ref to object)
+  ResourceTypePath typePath(bitmapResourceType, "");
+  newTicket = new ImageTicket(*this, newId, typePath);
+  newTicket->mAttributes = imageAttributes;
+  newTicket->LoadingSucceeded();
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+
+  // Store bitmap for immediate access.
+  mImpl->mBitmaps[newId] = bitmap;
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddBitmapImage() New id = %u\n", newId);
+  RequestAddBitmapImageMessage( mEventThreadServices, mResourceManager, newId, bitmap );
+
+  return newTicket;
+}
+
+ResourceTicketPtr ResourceClient::AddNativeImage ( NativeImageInterface& resourceData )
+{
+  ImageTicketPtr newTicket;
+
+  const ResourceId newId = ++(mImpl->mNextId);
+  NativeImageResourceType nativeImageResourceType; // construct first as no copy ctor (needed to bind ref to object)
+  ResourceTypePath typePath(nativeImageResourceType, "");
+  newTicket = new ImageTicket(*this, newId, typePath);
+  newTicket->mAttributes = ImageAttributes::New(resourceData.GetWidth(),
+                                                resourceData.GetHeight());
+  newTicket->LoadingSucceeded();
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddNativeImage() New id = %u\n", newId);
+
+  RequestAddNativeImageMessage( mEventThreadServices, mResourceManager, newId, &resourceData );
+
+  return newTicket;
+}
+
+ImageTicketPtr ResourceClient::AddFrameBufferImage ( unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
+{
+  ImageTicketPtr newTicket;
+
+  const ResourceId newId = ++(mImpl->mNextId);
+
+  ImageAttributes imageAttributes = ImageAttributes::New(width, height);
+  RenderTargetResourceType renderTargetResourceType( ImageDimensions( width, height ) ); // construct first as no copy ctor (needed to bind ref to object)
+  ResourceTypePath typePath(renderTargetResourceType, "");
+  newTicket = new ImageTicket(*this, newId, typePath);
+  newTicket->mAttributes = imageAttributes;
+  newTicket->LoadingSucceeded();
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
+  RequestAddFrameBufferImageMessage( mEventThreadServices, mResourceManager, newId, width, height, pixelFormat, bufferFormat );
+
+  return newTicket;
+}
+
+ImageTicketPtr ResourceClient::AddFrameBufferImage ( NativeImageInterface& nativeImage )
+{
+  ImageTicketPtr newTicket;
+
+  const ResourceId newId = ++(mImpl->mNextId);
+
+  ImageAttributes imageAttributes = ImageAttributes::New( nativeImage.GetWidth(), nativeImage.GetHeight() );
+  RenderTargetResourceType renderTargetResourceType( ImageDimensions( nativeImage.GetWidth(), nativeImage.GetHeight() ) ); // construct first as no copy ctor (needed to bind ref to object)
+  ResourceTypePath typePath(renderTargetResourceType, "");
+  newTicket = new ImageTicket(*this, newId, typePath);
+  newTicket->mAttributes = imageAttributes;
+  newTicket->LoadingSucceeded();
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AddFrameBufferImage() New id = %u\n", newId);
+  RequestAddFrameBufferImageMessage( mEventThreadServices, mResourceManager, newId, &nativeImage );
+
+  return newTicket;
+}
+
+
+ResourceTicketPtr ResourceClient::AllocateTexture( unsigned int width,
+                                                   unsigned int height,
+                                                   Pixel::Format pixelformat )
+{
+  ImageTicketPtr newTicket;
+  const ResourceId newId = ++(mImpl->mNextId);
+
+  ImageAttributes imageAttributes = ImageAttributes::New( width, height);
+  BitmapResourceType bitmapResourceType( ImageDimensions( width, height ) ); // construct first as no copy ctor (needed to bind ref to object)
+  ResourceTypePath typePath(bitmapResourceType, "");
+  newTicket = new ImageTicket(*this, newId, typePath);
+
+  mImpl->mTickets.insert(TicketPair(newId, newTicket.Get()));
+  newTicket->mAttributes = imageAttributes;
+  newTicket->LoadingSucceeded();
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: AllocateTexture() New id = %u\n", newId);
+
+  RequestAllocateTextureMessage( mEventThreadServices, mResourceManager, newId, width, height, pixelformat );
+
+  return newTicket;
+}
+
+void ResourceClient::UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea )
+{
+  DALI_ASSERT_DEBUG( ticket );
+
+  RequestUpdateBitmapAreaMessage( mEventThreadServices, mResourceManager, ticket->GetId(), updateArea );
+}
+
+void ResourceClient::UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  RequestUploadBitmapMessage( mEventThreadServices,
+                              mResourceManager,
+                              destId,
+                              srcId,
+                              xOffset,
+                              yOffset );
+}
+
+
+void ResourceClient::UploadBitmap( ResourceId destId,Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset)
+{
+  RequestUploadBitmapMessage( mEventThreadServices,
+                              mResourceManager,
+                              destId,
+                              bitmap,
+                              xOffset,
+                              yOffset );
+}
+
+Bitmap* ResourceClient::GetBitmap(ResourceTicketPtr ticket)
+{
+  DALI_ASSERT_DEBUG( ticket );
+
+  Bitmap* bitmap = NULL;
+  BitmapCacheIter iter = mImpl->mBitmaps.find(ticket->GetId());
+
+  if( iter != mImpl->mBitmaps.end() )
+  {
+    bitmap = iter->second;
+  }
+  return bitmap;
+}
+
+void ResourceClient::CreateGlTexture( ResourceId id )
+{
+  RequestCreateGlTextureMessage( mEventThreadServices, mResourceManager, id );
+}
+
+
+/********************************************************************************
+ ********************   ResourceTicketLifetimeObserver methods   ****************
+ ********************************************************************************/
+
+void ResourceClient::ResourceTicketDiscarded(const ResourceTicket& ticket)
+{
+  const ResourceId deadId = ticket.GetId();
+  const ResourceTypePath& typePath = ticket.GetTypePath();
+
+  // Ensure associated event owned resources are also removed
+  mImpl->mBitmaps.erase(ticket.GetId());
+
+  // The ticket object is dead, remove from tickets container
+  TicketContainerSize erased = mImpl->mTickets.erase(deadId);
+  DALI_ASSERT_DEBUG(erased != 0);
+  (void)erased; // Avoid "unused variable erased" in release builds
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: ResourceTicketDiscarded() deadId = %u\n", deadId);
+  RequestDiscardResourceMessage( mEventThreadServices, mResourceManager, deadId, typePath.type->id );
+}
+
+/********************************************************************************
+ ***********************   Notifications from ResourceManager  ******************
+ ********************************************************************************/
+
+void ResourceClient::NotifyUploaded( ResourceId id )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyUpdated(id:%u)\n", id);
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find(id);
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    ResourceTicket* ticket = ticketIter->second;
+    ticket->Uploaded();
+  }
+}
+
+void ResourceClient::NotifyLoading( ResourceId id )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoading(id:%u)\n", id);
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find(id);
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    ResourceTicket* ticket = ticketIter->second;
+    ticket->Loading();
+  }
+}
+
+void ResourceClient::NotifyLoadingSucceeded( ResourceId id )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingSucceeded(id:%u)\n", id);
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find(id);
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    ResourceTicket* ticket = ticketIter->second;
+    ticket->LoadingSucceeded();
+  }
+}
+
+void ResourceClient::NotifyLoadingFailed( ResourceId id )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: NotifyLoadingFailed(id:%u)\n", id);
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find(id);
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    ResourceTicket* ticket = ticketIter->second;
+    ticket->LoadingFailed();
+  }
+}
+
+void ResourceClient::UpdateImageTicket( ResourceId id, const ImageAttributes& imageAttributes ) ///!< Issue #AHC01
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceClient: UpdateImageTicket(id:%u)\n", id);
+
+  TicketContainerIter ticketIter = mImpl->mTickets.find(id);
+  if(ticketIter != mImpl->mTickets.end())
+  {
+    ResourceTicket* ticket = ticketIter->second;
+    ImageTicketPtr imageTicket = dynamic_cast<ImageTicket*>(ticket);
+    if(imageTicket)
+    {
+      imageTicket->mAttributes = imageAttributes;
+    }
+  }
+}
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/event/resources/resource-client.h b/dali/internal/event/resources/resource-client.h
new file mode 100644 (file)
index 0000000..8433bde
--- /dev/null
@@ -0,0 +1,317 @@
+#ifndef __DALI_INTERNAL_RESOURCE_CLIENT_H__
+#define __DALI_INTERNAL_RESOURCE_CLIENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/devel-api/common/ref-counted-dali-vector.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/internal/event/resources/resource-client-declarations.h>
+#include <dali/internal/event/resources/image-ticket.h>
+#include <dali/internal/event/resources/resource-ticket-lifetime-observer.h>
+#include <dali/internal/common/message.h>
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+class NativeImage;
+
+namespace Integration
+{
+class Bitmap;
+}
+
+namespace Internal
+{
+class EventThreadServices;
+class ResourceManager;
+class NotificationManager;
+
+
+typedef Integration::ResourceId ResourceId;
+
+/** Raw bytes of a resource laid out exactly as it wouldbe in a file, but in memory. */
+typedef Dali::RefCountedVector<uint8_t> RequestBuffer;
+/** Counting smart pointer for managing a buffer of raw bytes. */
+typedef IntrusivePtr<RequestBuffer> RequestBufferPtr;
+
+/**
+ * ResourceClient is an event side object that manages resource requests.
+ * It uses ResourceTicket objects to keep track of the lifetime of each request.
+ * If the same resource is required by two client objects, they will share the same ResourceTicket
+ * i.e. only one load will occur using the native filesystem.
+ *
+ * Resources themselves are handled by the Resource Manager in the update thread
+ */
+class ResourceClient : public ResourceTicketLifetimeObserver
+{
+public:
+  typedef Rect<unsigned int>    RectArea;     ///< rectangular area (x,y,w,h)
+
+  /**
+   * Create a resource client.
+   * There should exactly one of these objects per Dali Core.
+   * @param[in] resourceManager The resource manager
+   * @param[in] eventThreadServices Used for messaging to and reading from scene-graph.
+   */
+  ResourceClient( ResourceManager& resourceManager,
+                  EventThreadServices& eventThreadServices );
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~ResourceClient();
+
+public:
+
+  /**
+   * Request a resource from the native filesystem.
+   * Adding an observer to the ticket will enable the application to determine when the
+   * resource has finished loading.
+   * @param[in] type The type of requested resource.
+   * @param[in] path The path to the requested resource.
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ResourceTicketPtr RequestResource( const Integration::ResourceType& type,
+                                     const std::string& path,
+                                     Integration::LoadResourcePriority priority = Integration::LoadPriorityNormal );
+  /**
+   * Request that a resource be decoded in the background from the memory buffer
+   * that is passed-in. The data in the memory buffer should be formatted exactly
+   * as it would be in a file of a supported resource type.
+   *
+   * Adding an observer to the ticket will enable the application to determine when the
+   * resource has finished decoding.
+   * @note Only images are currently supported by this function.
+   * @param[in] type The type of resource. Must be BitmapResourceType.
+   * @param[in] buffer The raw data of the resource.
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
+   * @return A ref-counted request object on success or a null pointer on failure.
+   *         Keep a copy until the resource is no longer required.
+   */
+  ResourceTicketPtr DecodeResource( const Integration::ResourceType& type,
+                                    RequestBufferPtr buffer,
+                                    Integration::LoadResourcePriority priority = Integration::LoadPriorityNormal );
+
+  /**
+   * Request reloading a resource from the native filesystem.
+   * If the resource is still loading, this request is ignored.
+   * The ticket observer will be notified of completion with ResourceLoadingSucceeded() or
+   * ResourceLoadingFailed()
+   *
+   * @param[in] id resource id
+   * @param[in] resetFinishedStatus True if the finished status of the current image should be reset.
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
+   * @return true if successful, false if resource doesn't exist
+   */
+  bool ReloadResource( ResourceId id, bool resetFinishedStatus = false, Integration::LoadResourcePriority priority = Integration::LoadPriorityNormal );
+
+  /**
+   * Get the ticket for the associated resource ID.
+   * If no ticket can be found for this resource, then this returns
+   * NULL to indicate the resource doesn't exist.
+   * @param[in] id The resource ID.
+   * @return A resource ticket, or NULL if no resource existed with the given ID.
+   */
+  ResourceTicketPtr RequestResourceTicket( ResourceId id );
+
+  /**
+   * Reqeust allocation of a bitmap resource
+   * @note Older hardware may require bufferWidth and bufferHeight to be a power of two
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] bufferWidth   Buffer width (stride) in pixels
+   * @param[in] bufferHeight  Buffer height in pixels
+   * @param[in] pixelformat   Pixel format
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ImageTicketPtr AllocateBitmapImage ( unsigned int width,
+                                       unsigned int height,
+                                       unsigned int bufferWidth,
+                                       unsigned int bufferHeight,
+                                       Pixel::Format pixelformat );
+
+  /**
+   * Injects a bitmap resource (does not require loading).
+   * @pre bitmap has to be initialized
+   * @param[in] bitmap an initialized bitmap
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ImageTicketPtr AddBitmapImage(Integration::Bitmap* bitmap);
+
+  /**
+   * Add an existing resource to the resource manager.
+   * @param [in] resourceData the NativeImage object
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ResourceTicketPtr AddNativeImage ( NativeImageInterface& resourceData );
+
+  /**
+   * Add a framebuffer resource to the resource manager.
+   * @param[in] width       width in pixels
+   * @param[in] height      height in pixels
+   * @param[in] pixelFormat Pixel format
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ImageTicketPtr AddFrameBufferImage ( unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat );
+
+  /**
+   * Add a framebuffer resource to the resource manager.
+   * @param[in] nativeImage the NativeImage object
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ImageTicketPtr AddFrameBufferImage ( NativeImageInterface& nativeImage );
+
+  /**
+   * Request allocation of a texture.
+   * The texture is initially empty.
+   * @note Older hardware may require image width and image height to be a power of two
+   * @param[in] width         Image width in pixels
+   * @param[in] height        Image height in pixels
+   * @param[in] pixelformat   Pixel format
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  ResourceTicketPtr AllocateTexture( unsigned int width,
+                                     unsigned int height,
+                                     Pixel::Format pixelformat );
+
+  /**
+   * Update bitmap area
+   * @param[in] ticket The ticket representing the bitmap
+   * @param[in] updateArea the area updated.
+   */
+  void UpdateBitmapArea( ResourceTicketPtr ticket, RectArea& updateArea );
+
+  /**
+   * Upload a bitmap to a texture
+   * @param[in] destId The destination texture ID
+   * @param[in] srcId The resource ID of the bitmap to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UploadBitmap( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Upload a bitmap to a texture
+   * @param[in] destId The destination texture ID
+   * @param[in] bitmap The pointer pointing to the bitmap to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UploadBitmap( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset);
+
+  /**
+   * Find Bitmap by ticket.
+   * @pre ticket has to identify a Bitmap
+   * @param[in] ticket The ticket returned from AllocateBitmapImage() or AddBitmapImage()
+   * @return The bitmap, or NULL if the ticket did not reference a bitmap
+   */
+  Integration::Bitmap* GetBitmap(ResourceTicketPtr ticket);
+   /**
+    * @brief Trigger asynchronous creation of GL texture to back resource immediately.
+    * @param[in] id The resource ID to allocate a GL texture for.
+    */
+   void CreateGlTexture( ResourceId id );
+
+public: // From ResourceTicketLifetimeObserver.
+
+  /**
+   * This indicates that the previously requested resource is no longer needed.
+   * @param[in] ticket The ticket to remove from resource manager.
+   */
+  virtual void ResourceTicketDiscarded(const ResourceTicket& ticket);
+
+public: // Message methods
+
+  /**
+   * Notify associated ticket observers that the resource has been uploaded to GL.
+   * @param[in] id The resource id of the uploaded resource
+   */
+  void NotifyUploaded( ResourceId id );
+
+  /**
+   * Notify associated ticket observers that the resource is loading.
+   * @param[in] id The resource id of the loading resource
+   */
+  void NotifyLoading( ResourceId id );
+
+  /**
+   * Notify associated ticket observers that the resource has loaded.
+   * @param[in] id The resource id of the loaded resource
+   */
+  void NotifyLoadingSucceeded( ResourceId id );
+
+  /**
+   * Notify associated ticket observers that the resource has failed to load
+   * @param[in] id The resource id of the resource
+   */
+  void NotifyLoadingFailed( ResourceId id );
+
+ /**
+   * Finds ImageTicket which belongs to resource identified by id and updates the cached
+   * attributes with a new set which contains the actual width and height of the loaded
+   * image but has undefined values for all other fields.
+   * @param id The resource id to find the ticket of
+   * @param imageAttributes The image attributes to assign to the ticket
+   */
+  void UpdateImageTicket( ResourceId id, const ImageAttributes& imageAttributes ); ///!< Issue #AHC01
+
+private:
+  ResourceManager& mResourceManager;          ///< The resource manager
+  EventThreadServices& mEventThreadServices;        ///< Interface to send messages through
+
+private:
+  struct Impl;
+  Impl* mImpl;
+};
+
+inline MessageBase* UpdateImageTicketMessage( ResourceClient& client, ResourceId id, const ImageAttributes& attrs )
+{
+  return new MessageValue2< ResourceClient, ResourceId, ImageAttributes >(
+    &client, &ResourceClient::UpdateImageTicket, id, attrs );
+}
+
+inline MessageBase* UploadedMessage( ResourceClient& client, ResourceId id )
+{
+  return new MessageValue1< ResourceClient, ResourceId >( &client, &ResourceClient::NotifyUploaded, id );
+}
+
+inline MessageBase* LoadingMessage( ResourceClient& client, ResourceId id )
+{
+  return new MessageValue1< ResourceClient, ResourceId  >( &client, &ResourceClient::NotifyLoading, id );
+}
+
+inline MessageBase* LoadingSucceededMessage( ResourceClient& client, ResourceId id )
+{
+  return new MessageValue1< ResourceClient, ResourceId  >( &client, &ResourceClient::NotifyLoadingSucceeded, id );
+}
+
+inline MessageBase* LoadingFailedMessage( ResourceClient& client, ResourceId id )
+{
+  return new MessageValue1< ResourceClient, ResourceId  >( &client, &ResourceClient::NotifyLoadingFailed, id );
+}
+
+} // namespace Internal
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_CLIENT_H__
diff --git a/dali/internal/event/resources/resource-ticket-lifetime-observer.h b/dali/internal/event/resources/resource-ticket-lifetime-observer.h
new file mode 100644 (file)
index 0000000..77ee03d
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TICKET_LIFETIME_OBSERVER_H__
+#define __DALI_INTERNAL_RESOURCE_TICKET_LIFETIME_OBSERVER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceTicket;
+
+/**
+ * The ResourceTicketLifetimeObserver observes the lifetime of resource tickets.
+ */
+class ResourceTicketLifetimeObserver
+{
+public:
+
+  /**
+   * Called when a resource ticket is discarded.
+   * This occurs during the ResourceTicket destructor.
+   * @param[in] ticket The discarded ticket.
+   */
+  virtual void ResourceTicketDiscarded( const ResourceTicket& ticket ) = 0;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_TICKET_LIFETIME_OBSERVER_H__
diff --git a/dali/internal/event/resources/resource-ticket-observer.h b/dali/internal/event/resources/resource-ticket-observer.h
new file mode 100644 (file)
index 0000000..8b7c154
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TICKET_OBSERVER_H__
+#define __DALI_INTERNAL_RESOURCE_TICKET_OBSERVER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceTicket;
+
+typedef IntrusivePtr<ResourceTicket> ResourceTicketPtr;
+
+/**
+ * ResourceTicketObserver is used to observe the status of resource loading requests.
+ */
+class ResourceTicketObserver
+{
+public:
+
+  /**
+   * Called when a resource loads successfully.
+   * @param[in] ticket The ticket for this resource.
+   */
+  virtual void ResourceLoadingSucceeded( const ResourceTicket& ticket ) = 0;
+
+  /**
+   * Called when a resource fails to load.
+   * @param[in] ticket The ticket for this resource.
+   */
+  virtual void ResourceLoadingFailed( const ResourceTicket& ticket ) = 0;
+
+  /**
+   * Called when a resource is uploaded to graphics memory.
+   * @param[in] ticket The ticket for this resource.
+   */
+  virtual void ResourceUploaded( const ResourceTicket& ticket ) = 0;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_TICKET_OBSERVER_H__
diff --git a/dali/internal/event/resources/resource-ticket.cpp b/dali/internal/event/resources/resource-ticket.cpp
new file mode 100644 (file)
index 0000000..0ebb28f
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/resources/resource-ticket.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/images/image.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/resources/resource-ticket-observer.h>
+#include <dali/internal/event/resources/resource-ticket-lifetime-observer.h>
+
+namespace // unnamed namespace
+{
+
+// predicate for std::remove_if algorithm for compressing observer list
+bool isNULL(void* ptr)
+{
+  return ptr == NULL;
+}
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ResourceTicket::ResourceTicket( ResourceTicketLifetimeObserver& observer, unsigned int id, ResourceTypePath& typePath )
+: mLifetimeObserver( &observer ),
+  mId( id ),
+  mTypePath( typePath ),
+  mLoadingState( ResourceLoading )
+{
+}
+
+ResourceTicket::~ResourceTicket()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  if ( Stage::IsInstalled() &&
+       mLifetimeObserver )
+  {
+    mLifetimeObserver->ResourceTicketDiscarded( *this );
+  }
+}
+
+void ResourceTicket::AddObserver(ResourceTicketObserver& observer)
+{
+  mObservers.push_back(&observer);
+}
+
+void ResourceTicket::RemoveObserver(ResourceTicketObserver& observer)
+{
+  ObserverIter iter = find(mObservers.begin(), mObservers.end(), &observer);
+  DALI_ASSERT_DEBUG( mObservers.end() != iter );
+  if( mObservers.end() != iter )
+  {
+    (*iter) = NULL;
+  }
+}
+
+void ResourceTicket::LoadingSucceeded()
+{
+  DALI_ASSERT_DEBUG(mLoadingState == ResourceLoading);
+
+  mLoadingState = ResourceLoadingSucceeded;
+
+  // Using array operator as the call back out to application code might call back in
+  // and corrupt the mObservers list. Presumption is the operator gets the current address
+  // and adds an offset so a push_back() triggered reallocation should still work.
+  size_t count = mObservers.size();
+  for(size_t i = 0; i < count; i++)
+  {
+    if( mObservers[i] != NULL)
+    {
+      mObservers[i]->ResourceLoadingSucceeded(*this);
+    }
+  }
+
+  // Move NULL pointers to the end...
+  ObserverIter endIter = remove_if( mObservers.begin(), mObservers.end(), isNULL );
+
+  // ...and remove them
+  mObservers.erase( endIter, mObservers.end() );
+}
+
+void ResourceTicket::LoadingFailed()
+{
+  DALI_ASSERT_DEBUG(mLoadingState == ResourceLoading);
+
+  mLoadingState = ResourceLoadingFailed;
+
+  // Using array operator as the call back out to application code might call back in
+  // and corrupt the mObservers list. Presumption is the operator gets the current address
+  // and adds an offset so a push_back() triggered reallocation should still work.
+  size_t count = mObservers.size();
+  for(size_t i = 0; i < count; i++)
+  {
+    if( mObservers[i] != NULL)
+    {
+      mObservers[i]->ResourceLoadingFailed(*this);
+    }
+  }
+
+  // Move NULL pointers to the end...
+  ObserverIter endIter = remove_if( mObservers.begin(), mObservers.end(), isNULL );
+
+  // ...and remove them
+  mObservers.erase( endIter, mObservers.end() );
+}
+
+void ResourceTicket::Loading()
+{
+  mLoadingState = ResourceLoading;
+
+  // Move NULL pointers to the end...
+  ObserverIter endIter = remove_if( mObservers.begin(), mObservers.end(), isNULL );
+
+  // ...and remove them
+  mObservers.erase( endIter, mObservers.end() );
+}
+
+void ResourceTicket::Uploaded()
+{
+  // Using array operator as the call back out to application code might call back in
+  // and corrupt the mObservers list. Presumption is the operator gets the current address
+  // and adds an offset so a push_back() triggered reallocation should still work.
+  size_t count = mObservers.size();
+  for(size_t i = 0; i < count; i++)
+  {
+    if( mObservers[i] != NULL)
+    {
+      mObservers[i]->ResourceUploaded(*this);
+    }
+  }
+
+  // Move NULL pointers to the end...
+  ObserverIter endIter = remove_if( mObservers.begin(), mObservers.end(), isNULL );
+
+  // ...and remove them
+  mObservers.erase( endIter, mObservers.end() );
+}
+
+void ResourceTicket::StopLifetimeObservation()
+{
+  mLifetimeObserver = NULL;
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/event/resources/resource-ticket.h b/dali/internal/event/resources/resource-ticket.h
new file mode 100644 (file)
index 0000000..da510a4
--- /dev/null
@@ -0,0 +1,167 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TICKET_H__
+#define __DALI_INTERNAL_RESOURCE_TICKET_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/common/loading-state.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/event/resources/resource-type-path.h>
+#include <dali/integration-api/resource-cache.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceTicket;
+typedef IntrusivePtr<ResourceTicket> ResourceTicketPtr;
+typedef std::vector<ResourceTicketPtr> ResourceTicketContainer;
+
+class ResourceTicketObserver;
+class ResourceTicketLifetimeObserver;
+
+/**
+ * @brief ResourceTicket records the lifetime of a resource loading request.
+ *
+ * When a resource is requested from ResourceClient, you get a ticket.
+ * The state of the loading operation, can be observed using the ticket.
+ * After the ticket is destroyed, the resource will be discarded.
+ *
+ * Multi-threading note: this class should be used in the main thread only
+ * i.e. not from within Dali::Integration::Core::Render().
+ */
+class ResourceTicket : public RefObject
+{
+public:
+
+  /**
+   * Create a resource request.
+   * This should only be done by the ResourceTicketRegistry.
+   * @param [in] observer The object which observes ticket lifetimes.
+   * @param [in] id A unique ID for this ticket (loading request).
+   * @param [in] typePath The resource Type & Path pair.
+   */
+  ResourceTicket( ResourceTicketLifetimeObserver& observer, unsigned int id, ResourceTypePath& typePath );
+
+  /**
+   * Retrieve the unique ID of the resource request.
+   * This can be shared with Nodes etc. which will require the resource when rendering.
+   * @return The unique ID for this request.
+   */
+  unsigned int GetId() const { return mId; }
+
+  /**
+   * Retrieve the type and path of the resource request.
+   * @return The type and path.
+   */
+  const ResourceTypePath& GetTypePath() const { return mTypePath; }
+
+  /**
+   * Query the state of the resource loading request.
+   * @return The state.
+   */
+  Dali::LoadingState GetLoadingState() const { return mLoadingState; }
+
+  /**
+   * Adds an observer.
+   * @param[in] observer The observer.
+   */
+  void AddObserver(ResourceTicketObserver& observer);
+
+  /**
+   * Removes an observer.
+   * @param[in] observer The observer.
+   */
+  void RemoveObserver(ResourceTicketObserver& observer);
+
+public: // Used by the ResourceClient
+
+  /**
+   * Called when a resource loads successfully.
+   * The ResourceTicketObservers will be notified.
+   */
+  void LoadingSucceeded();
+
+  /**
+   * Called when a resource fails to load.
+   * The ResourceTicketObservers will be notified.
+   */
+  void LoadingFailed();
+
+  /**
+   * Reset state to ResourceLoading.
+   */
+  void Loading();
+
+  /**
+   * Notification when a resource has been uploaded to GL.
+   * The ResourceTicketObservers will be notified.
+   */
+  void Uploaded();
+
+  /**
+   * Called when the ResourceTicketLifetimeObserver is being destroyed.
+   * This method should only be called during destruction of the Dali core.
+   */
+  void StopLifetimeObservation();
+
+protected:
+
+  /**
+   * A reference counted object may only be deleted by calling Unreference()
+   */
+  virtual ~ResourceTicket();
+
+private:
+
+  /**
+   * Undefined copy constructor.
+   */
+  ResourceTicket(const ResourceTicket&);
+
+  /**
+   * Undefined assignment operator.
+   */
+  ResourceTicket& operator=(const ResourceTicket& rhs);
+
+private:
+
+  ResourceTicketLifetimeObserver* mLifetimeObserver; ///< reference to the lifetime-observer; not owned
+
+  unsigned int mId;
+  ResourceTypePath mTypePath;
+
+  Dali::LoadingState mLoadingState;
+
+  // These ticket observers are not owned by the ticket.
+  // Observers must remove themselves by calling RemoveObserver e.g. during destruction.
+  typedef std::vector<ResourceTicketObserver*> ObserverContainer;
+  typedef ObserverContainer::iterator ObserverIter;
+
+  ObserverContainer mObservers;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_MANAGER_H__
diff --git a/dali/internal/event/resources/resource-type-path.cpp b/dali/internal/event/resources/resource-type-path.cpp
new file mode 100644 (file)
index 0000000..1204e81
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/event/resources/resource-type-path.h>
+
+using namespace Dali::Integration;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+/**
+ * @brief Compare two sets of image loading parameters for equality.
+ */
+inline bool AttributesEqual( ImageDimensions aDims, FittingMode::Type aScaling, SamplingMode::Type aSampling, bool aOrient, ImageDimensions bDims, FittingMode::Type bScaling, SamplingMode::Type bSampling, bool bOrient )
+{
+  return aDims     == bDims &&
+         aScaling  == bScaling &&
+         aSampling == bSampling &&
+         aOrient   == bOrient;
+}
+
+/**
+ * @brief Compare two sets of image loading parameters
+ * @pre The two sets are not identical.
+ */
+inline bool AttributesLessAssumingNotEqual( ImageDimensions aDims, FittingMode::Type aScaling, SamplingMode::Type aSampling, bool aOrient, ImageDimensions bDims, FittingMode::Type bScaling, SamplingMode::Type bSampling, bool bOrient )
+{
+  return aDims     < bDims &&
+         aScaling  < bScaling &&
+         aSampling < bSampling &&
+         aOrient   < bOrient;
+}
+
+/**
+ * Compare two resource types.
+ * @return zero if the types are equal,
+ *         less than zero if lhs < rhs or
+ *         greater than zero if lhs > rhs
+ */
+int ResourceTypeCompare(const ResourceType& lhs, const ResourceType& rhs)
+{
+  int result = 0;
+
+  if (lhs.id != rhs.id)
+  {
+    result = lhs.id > rhs.id ? 1 : -1;
+  }
+  else // lhs.id == rhs.id
+  {
+    // Cast to a derived resource type and compare...
+
+    switch (lhs.id)
+    {
+      case ResourceBitmap:
+      {
+        // compare bitmap widths & heights
+        const BitmapResourceType& lhsBitmap = static_cast<const BitmapResourceType&>(lhs);
+        const BitmapResourceType& rhsBitmap = static_cast<const BitmapResourceType&>(rhs);
+
+        if( ! AttributesEqual( lhsBitmap.size, lhsBitmap.scalingMode, lhsBitmap.samplingMode, lhsBitmap.orientationCorrection,
+                               rhsBitmap.size, rhsBitmap.scalingMode, rhsBitmap.samplingMode, rhsBitmap.orientationCorrection ) )
+        {
+          result = AttributesLessAssumingNotEqual( lhsBitmap.size, lhsBitmap.scalingMode, lhsBitmap.samplingMode, lhsBitmap.orientationCorrection,
+                                                   rhsBitmap.size, rhsBitmap.scalingMode, rhsBitmap.samplingMode, rhsBitmap.orientationCorrection );
+        }
+        // else result = 0
+        break;
+      }
+
+      case ResourceNativeImage:
+      {
+        // compare native image widths & heights
+
+        const NativeImageResourceType& lhsNativeImage = static_cast<const NativeImageResourceType&>(lhs);
+        const NativeImageResourceType& rhsNativeImage = static_cast<const NativeImageResourceType&>(rhs);
+
+        if (lhsNativeImage.imageDimensions != rhsNativeImage.imageDimensions)
+        {
+          result = lhsNativeImage.imageDimensions < rhsNativeImage.imageDimensions ? -1 : 1;
+        }
+        // else result = 0
+        break;
+      }
+
+      case ResourceTargetImage:
+      {
+        // compare bitmap widths & heights
+        const RenderTargetResourceType& lhsImage = static_cast<const RenderTargetResourceType&>(lhs);
+        const RenderTargetResourceType& rhsImage = static_cast<const RenderTargetResourceType&>(rhs);
+
+        if (lhsImage.imageDimensions != rhsImage.imageDimensions)
+        {
+          result = lhsImage.imageDimensions < rhsImage.imageDimensions ? -1 : 1;
+        }
+        // else result = 0
+        break;
+      }
+    }
+  }
+  return result;
+}
+}
+
+bool ResourceTypePath::operator<(const ResourceTypePath& rhs) const
+{
+  int typeComparison = ResourceTypeCompare(*type, *(rhs.type));
+
+  if (typeComparison != 0)
+  {
+    return (typeComparison < 0);
+  }
+  else
+  {
+    return path < rhs.path;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/resources/resource-type-path.h b/dali/internal/event/resources/resource-type-path.h
new file mode 100644 (file)
index 0000000..e0d0b2c
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TYPE_PATH_H__
+#define __DALI_INTERNAL_RESOURCE_TYPE_PATH_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <memory>
+// INTERNAL INCLUDES
+#include <dali/integration-api/resource-types.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A resource Type & Path pair. This is used by ResourceManager when creating tickets.
+ * A new ticket will only be needed, if the same resource Type & Path has not already been requested.
+ */
+class ResourceTypePath
+{
+public:
+
+  /**
+   * Create a resource Type and Path pair.
+   * @param[in] requestType The type of resource.
+   * @param[in] requestPath The path of the resource.
+   */
+  ResourceTypePath(const Integration::ResourceType& requestType,
+                   const std::string& requestPath)
+  : type(requestType.Clone()),
+    path(requestPath)
+  {
+  }
+
+  /**
+   * Copy constructor.
+   * @param[in] typePath The Type & Path to copy.
+   */
+  ResourceTypePath(const ResourceTypePath& typePath)
+  : type(typePath.type->Clone()),
+    path(typePath.path)
+  {
+  }
+
+  ~ResourceTypePath()
+  {
+    delete type;
+  }
+
+  /**
+   * Less than operator.
+   * @param[in] rhs The request to compare with.
+   */
+  bool operator<(const ResourceTypePath& rhs) const;
+
+private:
+
+  /**
+   * Undefined assignment operator.
+   * @param[in] rhs The resource request to copy.
+   */
+  ResourceTypePath& operator=(const ResourceTypePath& rhs);
+
+public:
+
+  const Integration::ResourceType* type;
+  const std::string path;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_TYPE_PATH_H__
diff --git a/dali/internal/event/size-negotiation/memory-pool-relayout-container.cpp b/dali/internal/event/size-negotiation/memory-pool-relayout-container.cpp
new file mode 100644 (file)
index 0000000..617f801
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// FILE HEADER
+#include "memory-pool-relayout-container.h"
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+MemoryPoolRelayoutContainer::MemoryPoolRelayoutContainer( MemoryPoolObjectAllocator< RelayoutInfo >& objectAllocator )
+: mAllocator( objectAllocator )
+{
+}
+
+MemoryPoolRelayoutContainer::~MemoryPoolRelayoutContainer()
+{
+}
+
+bool MemoryPoolRelayoutContainer::Contains( const Dali::Actor& actor )
+{
+  for( RelayoutInfoContainer::Iterator it = mRelayoutInfos.Begin(), itEnd = mRelayoutInfos.End(); it != itEnd; ++it )
+  {
+    RelayoutInfo* info = *it;
+
+    if( info->actor == actor )
+    {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void MemoryPoolRelayoutContainer::Add( const Dali::Actor& actor, const Vector2& size )
+{
+  if( !Contains( actor ) )
+  {
+    RelayoutInfo* info = mAllocator.Allocate();
+    info->actor = actor;
+    info->size = size;
+
+    mRelayoutInfos.PushBack( info );
+  }
+}
+
+void MemoryPoolRelayoutContainer::PopBack()
+{
+  if( mRelayoutInfos.Size() > 0 )
+  {
+    RelayoutInfoContainer::Iterator back = mRelayoutInfos.End();
+    back--;
+    RelayoutInfo* info = *back;
+    mAllocator.Free( info );
+    mRelayoutInfos.Erase( back );
+  }
+}
+
+void MemoryPoolRelayoutContainer::Get( size_t index, Dali::Actor& actorOut, Vector2& sizeOut  ) const
+{
+  DALI_ASSERT_DEBUG( index < Size() );
+
+  RelayoutInfo* info = mRelayoutInfos[ index ];
+  actorOut = info->actor;
+  sizeOut = info->size;
+}
+
+size_t MemoryPoolRelayoutContainer::Size() const
+{
+  return mRelayoutInfos.Size();
+}
+
+void MemoryPoolRelayoutContainer::Reserve( size_t capacity )
+{
+  mRelayoutInfos.Reserve( capacity );
+}
+
+void MemoryPoolRelayoutContainer::Clear()
+{
+  for( size_t i = 0; i < Size(); ++i )
+  {
+    RelayoutInfo* info = mRelayoutInfos[ i ];
+    mAllocator.Free( info );
+  }
+
+  mRelayoutInfos.Clear();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/size-negotiation/memory-pool-relayout-container.h b/dali/internal/event/size-negotiation/memory-pool-relayout-container.h
new file mode 100644 (file)
index 0000000..02eda8f
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef __DALI_INTERNAL_MEMORY_POOL_RELAYOUT_CONTAINER_H__
+#define __DALI_INTERNAL_MEMORY_POOL_RELAYOUT_CONTAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/size-negotiation/relayout-container.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/actors/actor.h>
+
+#include <dali/internal/common/memory-pool-object-allocator.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Container to encapsulate information required for relayout.
+ *
+ * Uses a memory pool to manage data allocations.
+ */
+class MemoryPoolRelayoutContainer : public RelayoutContainer
+{
+public:
+
+  /**
+   * Struct to store the relayout information
+   */
+  struct RelayoutInfo
+  {
+    Dali::Actor actor;            ///< The actor to relayout
+    Vector2 size;           ///< The desired size of the actor
+  };
+
+  /**
+   * @brief Default constructor
+   *
+   * @param objectAllocator A memory pool that can allocate memory for RelayoutInfos
+   */
+  MemoryPoolRelayoutContainer( MemoryPoolObjectAllocator< RelayoutInfo >& objectAllocator );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~MemoryPoolRelayoutContainer();
+
+  /**
+   * @brief Add relayout information to the container if it does'nt already exist
+   *
+   * @param actor The actor to relayout
+   * @param size The size to relayout
+   */
+  virtual void Add( const Dali::Actor& actor, const Vector2& size );
+
+  /**
+   * @brief Remove information from the container
+   */
+  void PopBack();
+
+  /**
+   * @brief Retrieve relayout information for the given index
+   *
+   * @param index The index of the information to retrieve
+   */
+  void Get( size_t index, Dali::Actor& actorOut, Vector2& sizeOut  ) const;
+
+  /**
+   * @brief The count of information in the container
+   */
+  size_t Size() const;
+
+  /**
+   * @brief Set the capacity of the container
+   *
+   * @param capacity The new capacity for the container
+   */
+  void Reserve( size_t capacity );
+
+  /**
+   * @brief Reset the container, freeing all memory
+   */
+  void Clear();
+
+  /**
+   * @brief Returns if the container contains the actor or not
+   *
+   * @param actor The actor to search for
+   * @return Return if the actor was found or not
+   */
+  bool Contains( const Dali::Actor& actor );
+
+private:
+
+  typedef Vector< RelayoutInfo* > RelayoutInfoContainer;
+
+  RelayoutInfoContainer mRelayoutInfos;     ///< The list of relayout infos
+
+  MemoryPoolObjectAllocator< RelayoutInfo >& mAllocator;         ///< The memory pool from which the infos are allocated
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_MEMORY_POOL_RELAYOUT_CONTAINER_H__
diff --git a/dali/internal/event/size-negotiation/relayout-controller-impl.cpp b/dali/internal/event/size-negotiation/relayout-controller-impl.cpp
new file mode 100644 (file)
index 0000000..9efe523
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "relayout-controller-impl.h"
+
+// EXTERNAL INCLUDES
+#if defined(DEBUG_ENABLED)
+#include <sstream>
+#include <dali/internal/event/common/system-overlay-impl.h>
+#endif // defined(DEBUG_ENABLED)
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/render-controller.h>
+#include <dali/public-api/object/type-registry.h>
+#include <dali/public-api/object/object-registry.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+
+Integration::Log::Filter* gLogFilter( Integration::Log::Filter::New(Debug::NoLogging, false, "LOG_RELAYOUT_CONTROLLER") );
+
+/**
+ * Prints out all the children of the given actor when debug is enabled.
+ *
+ * @param[in]  actor  The actor whose children to print.
+ * @param[in]  level  The number of " | " to put in front of the children.
+ */
+void PrintChildren( Dali::Actor actor, int level )
+{
+  std::ostringstream output;
+
+  for ( int t = 0; t < level; ++t )
+  {
+    output << " | ";
+  }
+
+  output << actor.GetTypeName();
+
+  output << ", " << actor.GetName();
+
+  output << " - Pos: " << actor.GetCurrentPosition() << " Size: " << actor.GetTargetSize();
+
+  output << ", Dirty: (" << ( GetImplementation( actor ).IsLayoutDirty( Dimension::WIDTH ) ? "TRUE" : "FALSE" ) << "," << ( GetImplementation( actor ).IsLayoutDirty( Dimension::HEIGHT ) ? "TRUE" : "FALSE" ) << ")";
+  output << ", Negotiated: (" << ( GetImplementation( actor ).IsLayoutNegotiated( Dimension::WIDTH ) ? "TRUE" : "FALSE" ) << "," << ( GetImplementation( actor ).IsLayoutNegotiated( Dimension::HEIGHT ) ? "TRUE" : "FALSE" ) << ")";
+  output << ", Enabled: " << ( GetImplementation( actor ).IsRelayoutEnabled() ? "TRUE" : "FALSE" );
+
+  output << ", (" << actor.GetObjectPtr() << ")" << std::endl;
+
+  DALI_LOG_INFO( gLogFilter, Debug::Verbose, output.str().c_str() );
+
+  ++level;
+  unsigned int numChildren = actor.GetChildCount();
+  for( unsigned int i=0; i<numChildren; ++i )
+  {
+    PrintChildren( actor.GetChildAt(i), level );
+  }
+  --level;
+}
+
+/**
+ * Prints the entire hierarchy of the scene.
+ */
+void PrintHierarchy()
+{
+  if ( gLogFilter->IsEnabledFor( Debug::Verbose ) )
+  {
+    DALI_LOG_INFO( gLogFilter, Debug::Verbose, "---------- ROOT LAYER ----------\n" );
+    PrintChildren( Stage::GetCurrent()->GetRootLayer(), 0 );
+  }
+}
+
+#define PRINT_HIERARCHY PrintHierarchy()
+
+#else // defined(DEBUG_ENABLED)
+
+#define PRINT_HIERARCHY
+
+#endif // defined(DEBUG_ENABLED)
+
+} // unnamed namespace
+
+RelayoutController::RelayoutController( Integration::RenderController& controller )
+: mRenderController( controller ),
+  mRelayoutInfoAllocator(),
+  mSlotDelegate( this ),
+  mRelayoutStack( new MemoryPoolRelayoutContainer( mRelayoutInfoAllocator ) ),
+  mStageSize(), // zero initialized
+  mRelayoutConnection( false ),
+  mRelayoutFlag( false ),
+  mEnabled( false ),
+  mPerformingRelayout( false ),
+  mProcessingCoreEvents( false )
+{
+  // Make space for 32 controls to avoid having to copy construct a lot in the beginning
+  mRelayoutStack->Reserve( 32 );
+}
+
+RelayoutController::~RelayoutController()
+{
+  delete mRelayoutStack;
+}
+
+RelayoutController* RelayoutController::Get()
+{
+  return &ThreadLocalStorage::Get().GetRelayoutController();
+}
+
+void RelayoutController::SetStageSize( unsigned int width, unsigned int height )
+{
+  mStageSize.width = width;
+  mStageSize.height = height;
+}
+
+void RelayoutController::QueueActor( Dali::Actor& actor, RelayoutContainer& actors, Vector2 size )
+{
+  if( GetImplementation( actor ).RelayoutRequired() )
+  {
+    actors.Add( actor, size );
+  }
+}
+
+void RelayoutController::RequestRelayout( Dali::Actor& actor, Dimension::Type dimension )
+{
+  if( !mEnabled )
+  {
+    return;
+  }
+
+  std::vector< Dali::Actor > potentialRedundantSubRoots;
+  std::vector< Dali::Actor > topOfSubTreeStack;
+
+  topOfSubTreeStack.push_back( actor );
+
+  // Propagate on all dimensions
+  for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+  {
+    if( dimension & ( 1 << i ) )
+    {
+      // Do the propagation
+      PropagateAll( actor, static_cast< Dimension::Type >( 1 << i ), topOfSubTreeStack, potentialRedundantSubRoots );
+    }
+  }
+
+  while( !topOfSubTreeStack.empty() )
+  {
+    // Request this actor as head of sub-tree if it is not dependent on a parent that is dirty
+    Dali::Actor subTreeActor = topOfSubTreeStack.back();
+    topOfSubTreeStack.pop_back();
+
+    Dali::Actor parent = subTreeActor.GetParent();
+    if( !parent || !( GetImplementation( subTreeActor ).RelayoutDependentOnParent() && GetImplementation( parent ).RelayoutRequired() ) )
+    {
+      // Add sub tree root to relayout list
+      AddRequest( subTreeActor );
+
+      // Flag request for end of frame
+      Request();
+    }
+    else
+    {
+      potentialRedundantSubRoots.push_back( subTreeActor );
+    }
+  }
+
+  // Remove any redundant sub-tree heads
+  for( std::vector< Dali::Actor >::iterator it = potentialRedundantSubRoots.begin(), itEnd = potentialRedundantSubRoots.end(); it != itEnd; ++it )
+  {
+    Dali::Actor subRoot = *it;
+
+    RemoveRequest( subRoot );
+  }
+
+  if ( !mProcessingCoreEvents )
+  {
+    mRenderController.RequestProcessEventsOnIdle();
+  }
+}
+
+void RelayoutController::OnApplicationSceneCreated()
+{
+  DALI_LOG_INFO( gLogFilter, Debug::General, "[Internal::RelayoutController::OnApplicationSceneCreated]\n" );
+
+  // Open relayout controller to receive relayout requests
+  mEnabled = true;
+
+  // Spread the dirty flag through whole tree - don't need to explicity
+  // add request on rootLayer as it will automatically be added below.
+  Dali::Actor rootLayer = Dali::Stage::GetCurrent().GetRootLayer();
+  RequestRelayoutTree( rootLayer );
+
+  // Flag request for end of frame
+  Request();
+}
+
+void RelayoutController::RequestRelayoutTree( Dali::Actor& actor )
+{
+  if( !mEnabled )
+  {
+    return;
+  }
+
+  // Only set dirty flag if doing relayout and not already marked as dirty
+  Actor& actorImpl = GetImplementation( actor );
+  if( actorImpl.RelayoutPossible() )
+  {
+    // If parent is not in relayout we are at the top of a new sub-tree
+    Dali::Actor parent = actor.GetParent();
+    if( !parent || !GetImplementation( parent ).IsRelayoutEnabled() )
+    {
+      AddRequest( actor );
+    }
+
+    // Set dirty flag on actors that are enabled
+    actorImpl.SetLayoutDirty( true );
+    actorImpl.SetLayoutNegotiated( false );    // Reset this flag ready for next relayout
+  }
+
+  // Propagate down to children
+  for( unsigned int i = 0; i < actor.GetChildCount(); ++i )
+  {
+    Dali::Actor child = actor.GetChildAt( i );
+
+    RequestRelayoutTree( child );
+  }
+}
+
+void RelayoutController::PropagateAll( Dali::Actor& actor, Dimension::Type dimension, std::vector< Dali::Actor >& topOfSubTreeStack, std::vector< Dali::Actor >& potentialRedundantSubRoots )
+{
+  // Only set dirty flag if doing relayout and not already marked as dirty
+  Actor& actorImpl = GetImplementation( actor );
+  if( actorImpl.RelayoutPossible( dimension ) )
+  {
+    // Set dirty and negotiated flags
+    actorImpl.SetLayoutDirty( true, dimension );
+    actorImpl.SetLayoutNegotiated( false, dimension );    // Reset this flag ready for next relayout
+
+    // Check for dimension dependecy: width for height/height for width etc
+    // Check each possible dimension and see if it is dependent on the input one
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
+
+      if( actorImpl.RelayoutDependentOnDimension( dimension, dimensionToCheck ) &&
+          !actorImpl.IsLayoutDirty( dimensionToCheck ) )
+      {
+        PropagateAll( actor, dimensionToCheck, topOfSubTreeStack, potentialRedundantSubRoots );
+      }
+    }
+
+    // Propagate up to parent
+    Dali::Actor parent = actor.GetParent();
+    if( parent )
+    {
+      Actor& parentImpl = GetImplementation( parent );
+      if( parentImpl.RelayoutDependentOnChildren( dimension ) && !parentImpl.IsLayoutDirty( dimension ) )
+      {
+        // Store the highest parent reached
+        bool found = false;
+        for( unsigned int i = 0, count = topOfSubTreeStack.size(); i < count; ++i )
+        {
+          if( topOfSubTreeStack[ i ] == parent )
+          {
+            found = true;
+            break;
+          }
+        }
+
+        if( !found )
+        {
+          topOfSubTreeStack.push_back( parent );
+        }
+
+        // Propagate up
+        PropagateAll( parent, dimension, topOfSubTreeStack, potentialRedundantSubRoots );
+      }
+    }
+
+    // Propagate down to children
+    for( unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i )
+    {
+      Dali::Actor child = actor.GetChildAt( i );
+      Actor& childImpl = GetImplementation( child );
+
+      if( childImpl.IsRelayoutEnabled() && childImpl.RelayoutDependentOnParent( dimension ) )
+      {
+        if( childImpl.IsLayoutDirty( dimension ) )
+        {
+          // We have found a child that could potentially have already been collected for relayout
+          potentialRedundantSubRoots.push_back( child );
+        }
+        else
+        {
+          PropagateAll( child, dimension, topOfSubTreeStack, potentialRedundantSubRoots );
+        }
+      }
+    }
+  }
+}
+
+
+void RelayoutController::PropagateFlags( Dali::Actor& actor, Dimension::Type dimension )
+{
+  // Only set dirty flag if doing relayout and not already marked as dirty
+  Actor& actorImpl = GetImplementation( actor );
+  if( actorImpl.IsRelayoutEnabled() )
+  {
+    // Set dirty and negotiated flags
+    actorImpl.SetLayoutDirty( true, dimension );
+    actorImpl.SetLayoutNegotiated( false, dimension );    // Reset this flag ready for next relayout
+
+    // Check for dimension dependecy: width for height/height for width etc
+    // Check each possible dimension and see if it is dependent on the input one
+    for( unsigned int i = 0; i < Dimension::DIMENSION_COUNT; ++i )
+    {
+      Dimension::Type dimensionToCheck = static_cast< Dimension::Type >( 1 << i );
+
+      if( actorImpl.RelayoutDependentOnDimension( dimension, dimensionToCheck ) )
+      {
+        PropagateFlags( actor, dimensionToCheck );
+      }
+    }
+
+    // Propagate up to parent
+    Dali::Actor parent = actor.GetParent();
+    if( parent )
+    {
+      Actor& parentImpl = GetImplementation( parent );
+      if( parentImpl.RelayoutDependentOnChildren( dimension ) )
+      {
+        // Propagate up
+        PropagateFlags( parent, dimension );
+      }
+    }
+
+    // Propagate down to children
+    for( unsigned int i = 0, childCount = actor.GetChildCount(); i < childCount; ++i )
+    {
+      Dali::Actor child = actor.GetChildAt( i );
+      Actor& childImpl = GetImplementation( child );
+
+      if( childImpl.RelayoutDependentOnParent( dimension ) )
+      {
+        PropagateFlags( child, dimension );
+      }
+    }
+  }
+}
+
+void RelayoutController::AddRequest( Dali::Actor& actor )
+{
+  BaseObject* actorPtr = &GetImplementation( actor );
+
+  // Only add the rootActor if it is not already recorded
+  bool found = false;
+  for( unsigned int i = 0, count = mDirtyLayoutSubTrees.Size(); i < count; ++i )
+  {
+    if( mDirtyLayoutSubTrees[ i ] == actorPtr )
+    {
+      found = true;
+      break;
+    }
+  }
+
+  if( !found )
+  {
+    mDirtyLayoutSubTrees.PushBack( actorPtr );
+  }
+}
+
+void RelayoutController::RemoveRequest( Dali::Actor& actor )
+{
+  BaseObject* actorPtr = &GetImplementation( actor );
+
+  // Remove actor from dirty sub trees
+  for( RawActorList::Iterator it = mDirtyLayoutSubTrees.Begin(), itEnd = mDirtyLayoutSubTrees.End(); it != itEnd; ++it )
+  {
+    if( *it == actorPtr )
+    {
+      mDirtyLayoutSubTrees.Erase( it );
+      break;
+    }
+  }
+}
+
+void RelayoutController::Request()
+{
+  mRelayoutFlag = true;
+
+  if( !mRelayoutConnection )
+  {
+    Dali::Stage stage = Dali::Stage::GetCurrent();
+    stage.GetObjectRegistry().ObjectDestroyedSignal().Connect( mSlotDelegate, &RelayoutController::OnObjectDestroyed );
+
+    mRelayoutConnection = true;
+  }
+}
+
+void RelayoutController::OnObjectDestroyed( const Dali::RefObject* object )
+{
+  // Search for and null the object if found in the following lists
+  FindAndZero( mDirtyLayoutSubTrees, object );
+}
+
+void RelayoutController::Relayout()
+{
+  // Only do something when requested
+  if( mRelayoutFlag )
+  {
+    mPerformingRelayout = true;
+
+    // Clear the flag as we're now doing the relayout
+    mRelayoutFlag = false;
+
+    // 1. Finds all top-level controls from the dirty list and allocate them the size of the stage
+    //    These controls are paired with the parent/stage size and added to the stack.
+    for( RawActorList::Iterator it = mDirtyLayoutSubTrees.Begin(), itEnd = mDirtyLayoutSubTrees.End(); it != itEnd; ++it )
+    {
+      BaseObject* dirtyActor = *it;
+
+      // Need to test if actor is valid (could have been deleted and had the pointer cleared)
+      if( dirtyActor )
+      {
+        // We know that BaseObject is a base class of Internal::Actor but need to instruct the compiler to do the cast
+        Dali::Actor actor = Dali::Actor( reinterpret_cast<Dali::Internal::Actor*>( dirtyActor ) );
+
+        // Only negotiate actors that are on stage
+        if( actor.OnStage() )
+        {
+          Dali::Actor parent = actor.GetParent();
+          QueueActor( actor, *mRelayoutStack, ( parent ) ? Vector2( parent.GetTargetSize() ) : mStageSize );
+        }
+      }
+    }
+
+    mDirtyLayoutSubTrees.Clear();
+
+    // 2. Iterate through the stack until it's empty.
+    if( mRelayoutStack->Size() > 0 )
+    {
+      PRINT_HIERARCHY;
+
+      while( mRelayoutStack->Size() > 0 )
+      {
+        Dali::Actor actor;
+        Vector2 size;
+        mRelayoutStack->Get( mRelayoutStack->Size() - 1, actor, size );
+        Actor& actorImpl = GetImplementation( actor );
+        mRelayoutStack->PopBack();
+
+        if( actorImpl.RelayoutRequired() )
+        {
+          DALI_LOG_INFO( gLogFilter, Debug::General, "[Internal::RelayoutController::Relayout] Negotiating %p %s %s (%.2f, %.2f)\n", &actorImpl, actor.GetTypeName().c_str(), actor.GetName().c_str(), size.width, size.height );
+
+          // 3. Negotiate the size with the current actor. Pass it an empty container which the actor
+          //    has to fill with all the actors it has not done any size negotiation for.
+          actorImpl.NegotiateSize( size, *mRelayoutStack );
+        }
+      }
+
+      // We are done with the RelayoutInfos now so delete the pool
+      mRelayoutInfoAllocator.ResetMemoryPool();
+
+      PRINT_HIERARCHY;
+    }
+
+    mPerformingRelayout = false;
+  }
+  // should not disconnect the signal as that causes some control size negotiations to not work correctly
+  // this algorithm needs more optimization as well
+}
+
+void RelayoutController::SetEnabled( bool enabled )
+{
+  mEnabled = enabled;
+}
+
+bool RelayoutController::IsPerformingRelayout() const
+{
+  return mPerformingRelayout;
+}
+
+void RelayoutController::SetProcessingCoreEvents( bool processingEvents )
+{
+  mProcessingCoreEvents = processingEvents;
+}
+
+void RelayoutController::FindAndZero( const RawActorList& list, const Dali::RefObject* object )
+{
+  // Object has been destroyed so clear it from this list
+  for( RawActorList::Iterator it = list.Begin(), itEnd = list.End(); it != itEnd; ++it )
+  {
+    BaseObject* actor = *it;
+
+    if( actor && ( actor == object ) )
+    {
+      *it = NULL;    // Reset the pointer in the list. We don't want to remove it in case something is iterating over the list.
+    }
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/event/size-negotiation/relayout-controller-impl.h b/dali/internal/event/size-negotiation/relayout-controller-impl.h
new file mode 100644 (file)
index 0000000..d8e7bfa
--- /dev/null
@@ -0,0 +1,231 @@
+#ifndef __DALI_INTERNAL_RELAYOUT_CONTROLLER_IMPL_H__
+#define __DALI_INTERNAL_RELAYOUT_CONTROLLER_IMPL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/size-negotiation/relayout-container.h>
+#include <dali/internal/common/memory-pool-object-allocator.h>
+#include <dali/internal/event/size-negotiation/memory-pool-relayout-container.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class RenderController;
+}
+
+namespace Internal
+{
+
+/**
+ * @brief The relayout controller is responsible for taking request from actors to relayout their sizes.
+ * The requests are actioned on at the end of the frame where all actors that have made a request are
+ * resized.
+ */
+class RelayoutController : public Dali::BaseObject
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * We should only create a unique instance.
+   * @param[in] controller to request a render from the RenderController if core is not processing events.
+   */
+  RelayoutController( Integration::RenderController& controller );
+
+  /**
+   * Destructor
+   */
+  virtual ~RelayoutController();
+
+  /**
+   * @brief Get the singleton of RelayoutController object.
+   *
+   * @return A handle to the RelayoutController control.
+   */
+  static RelayoutController* Get();
+
+  /**
+   * Set the stage size
+   * @param width of the stage
+   * @param height of the stage
+   */
+  void SetStageSize( unsigned int width, unsigned int height );
+
+  /**
+   * @brief Request to relayout the given actor and all sub-actors of it.
+   *
+   * This flags the actor and all actors dependent on it for relayout. The actual
+   * relayout is performed at the end of the frame. This means that multiple calls to relayout
+   * will not cause multiple relayouts to occur.
+   *
+   * @param[in] actor The actor to request relayout on
+   * @param[in] dimension The dimension(s) to request the relayout on. Defaults to all dimensions
+   */
+  void RequestRelayout( Dali::Actor& actor, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Request to relayout of all actors in the sub-tree below the given actor.
+   *
+   * This flags the actor and all actors below it for relayout. The actual
+   * relayout is performed at the end of the frame. This means that multiple calls to relayout
+   * will not cause multiple relayouts to occur.
+   *
+   * @param[in] actor The actor to request relayout on
+   */
+  void RequestRelayoutTree( Dali::Actor& actor );
+
+  /**
+   * @brief Force propagate relayout flags through the tree. This is similiar to Request Relayout
+   * except all dependencies have their flags reset in spite of whether they are all ready set.
+   *
+   * This is useful for resetting layout flags during the layout process.
+   *
+   * @param[in] actor The actor to propagate from
+   * @param[in] dimension The dimension to propagate on
+   */
+  void PropagateFlags( Dali::Actor& actor, Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+  /**
+   * @brief Relayouts all actors that have been marked as dirty
+   */
+  void Relayout();
+
+  /**
+   * @brief Enable/disable the controller
+   *
+   * @param[in] enabled Flag to indicate whether the controller should be enabled or disabled
+   */
+  void SetEnabled( bool enabled );
+
+  /**
+   * @brief Return true if the relayout controller is currently performing a relayout
+   *
+   * @return Return true if the relayout controller is currently performing a relayout
+   */
+  bool IsPerformingRelayout() const;
+
+  /**
+   * @brief Sets whether core is processing events.
+   *
+   * @param[in] processingEvents whether core is processing events.
+   */
+  void SetProcessingCoreEvents( bool processingEvents );
+
+public: // CALLBACKS
+
+  /**
+   * @brief Callback raised after the application creates the scene
+   */
+  void OnApplicationSceneCreated();
+
+  /**
+   * @brief Callback for when an object is destroyed
+   *
+   * @param[in] object The object being destroyed
+   */
+  void OnObjectDestroyed( const Dali::RefObject* object );
+
+private:
+
+  typedef Dali::Vector< BaseObject* > RawActorList;
+
+  /**
+   * @brief Request for relayout. Relays out whole scene.
+   */
+  void Request();
+
+  /**
+   * @brief Add actor to request list
+   *
+   * @param[in] actor The root of the sub tree to add
+   */
+  void AddRequest( Dali::Actor& actor );
+
+  /**
+   * @brief Remove actor from request list
+   *
+   * @param[in] actor The root of the sub tree to remove
+   */
+  void RemoveRequest( Dali::Actor& actor );
+
+  /**
+   * @brief Disconnect the Relayout() method from the Stage::EventProcessingFinishedSignal().
+   */
+  void Disconnect();
+
+  /**
+   * @brief Propagate dirty layout flags to actor and all sub-actors. This will stop propagating when a dirty actor
+   * is found.
+   *
+   * @param[in] actor The actor to propagate on
+   * @param[in] dimension The dimension to propagate on
+   * @param[in] topOfSubTreeStack The top of the sub tree that this actor is in
+   * @param[in] potentialRedundantSubRoots Actors collected as potentially already being included in relayout
+   */
+  void PropagateAll( Dali::Actor& actor, Dimension::Type dimension, std::vector< Dali::Actor >& topOfSubTreeStack, std::vector< Dali::Actor >& potentialRedundantSubRoots );
+
+  /**
+   * Queue an actor on the relayout container
+   *
+   * @param[in] actor The actor to be queued
+   * @param[in] actors The container to add the actor to
+   * @param[in] size The size that this actor should be
+   */
+  void QueueActor( Dali::Actor& actor, RelayoutContainer& actors, Vector2 size );
+
+  /**
+   * @brief Find the given object in the list and null it out
+   *
+   * @param[in] list The list to search
+   * @param[in] object The object to search for
+   */
+  void FindAndZero( const RawActorList& list, const Dali::RefObject* object );
+
+  // Undefined
+  RelayoutController(const RelayoutController&);
+  RelayoutController& operator=(const RelayoutController&);
+
+private:
+
+  Integration::RenderController& mRenderController;
+  MemoryPoolObjectAllocator< MemoryPoolRelayoutContainer::RelayoutInfo > mRelayoutInfoAllocator;
+
+  SlotDelegate< RelayoutController > mSlotDelegate;
+
+  RawActorList mDirtyLayoutSubTrees;    ///< List of roots of sub trees that are dirty
+  MemoryPoolRelayoutContainer* mRelayoutStack;  ///< Stack for relayouting
+
+  Vector2 mStageSize;              ///< size of the stage
+  bool mRelayoutConnection : 1;    ///< Whether EventProcessingFinishedSignal signal is connected.
+  bool mRelayoutFlag : 1;          ///< Relayout flag to avoid unnecessary calls
+  bool mEnabled : 1;               ///< Initially disabled. Must be enabled at some point.
+  bool mPerformingRelayout : 1;    ///< The relayout controller is currently performing a relayout
+  bool mProcessingCoreEvents : 1;  ///< Whether core is processing events.
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RELAYOUT_CONTROLLER_IMPL_H__
diff --git a/dali/internal/file.list b/dali/internal/file.list
new file mode 100644 (file)
index 0000000..f8b00b2
--- /dev/null
@@ -0,0 +1,175 @@
+# Add internal source files here
+
+internal_src_files = \
+  $(internal_src_dir)/common/blending-options.cpp \
+  $(internal_src_dir)/common/core-impl.cpp \
+  $(internal_src_dir)/common/internal-constants.cpp \
+  $(internal_src_dir)/common/message-buffer.cpp \
+  $(internal_src_dir)/common/image-sampler.cpp \
+  $(internal_src_dir)/common/image-attributes.cpp \
+  $(internal_src_dir)/common/fixed-size-memory-pool.cpp \
+  \
+  $(internal_src_dir)/event/actor-attachments/actor-attachment-impl.cpp \
+  $(internal_src_dir)/event/actor-attachments/camera-attachment-impl.cpp \
+  $(internal_src_dir)/event/actor-attachments/image-attachment-impl.cpp \
+  $(internal_src_dir)/event/actor-attachments/renderable-attachment-impl.cpp \
+  $(internal_src_dir)/event/actor-attachments/renderer-attachment-impl.cpp \
+  $(internal_src_dir)/event/actors/actor-impl.cpp \
+  $(internal_src_dir)/event/actors/custom-actor-internal.cpp \
+  $(internal_src_dir)/event/actors/image-actor-impl.cpp \
+  $(internal_src_dir)/event/actors/layer-impl.cpp \
+  $(internal_src_dir)/event/actors/layer-list.cpp \
+  $(internal_src_dir)/event/actors/camera-actor-impl.cpp \
+  $(internal_src_dir)/event/animation/animation-impl.cpp \
+  $(internal_src_dir)/event/animation/animation-playlist.cpp \
+  $(internal_src_dir)/event/animation/constrainer.cpp \
+  $(internal_src_dir)/event/animation/constraint-base.cpp \
+  $(internal_src_dir)/event/animation/key-frames-impl.cpp \
+  $(internal_src_dir)/event/animation/linear-constrainer-impl.cpp \
+  $(internal_src_dir)/event/animation/path-impl.cpp \
+  $(internal_src_dir)/event/animation/path-constrainer-impl.cpp \
+  $(internal_src_dir)/event/common/demangler.cpp \
+  $(internal_src_dir)/event/common/event-thread-services.cpp \
+  $(internal_src_dir)/event/common/notification-manager.cpp \
+  $(internal_src_dir)/event/common/object-impl.cpp \
+  $(internal_src_dir)/event/common/object-registry-impl.cpp \
+  $(internal_src_dir)/event/common/projection.cpp \
+  $(internal_src_dir)/event/common/property-buffer-impl.cpp  \
+  $(internal_src_dir)/event/common/property-conditions-impl.cpp  \
+  $(internal_src_dir)/event/common/property-notification-impl.cpp  \
+  $(internal_src_dir)/event/common/property-notification-manager.cpp \
+  $(internal_src_dir)/event/common/stage-impl.cpp \
+  $(internal_src_dir)/event/common/system-overlay-impl.cpp \
+  $(internal_src_dir)/event/common/thread-local-storage.cpp \
+  $(internal_src_dir)/event/common/type-info-impl.cpp \
+  $(internal_src_dir)/event/common/type-registry-impl.cpp \
+  $(internal_src_dir)/event/effects/shader-effect-impl.cpp \
+  $(internal_src_dir)/event/effects/shader-factory.cpp \
+  $(internal_src_dir)/event/events/actor-gesture-data.cpp \
+  $(internal_src_dir)/event/events/actor-observer.cpp \
+  $(internal_src_dir)/event/events/event-processor.cpp \
+  $(internal_src_dir)/event/events/key-event-processor.cpp \
+  $(internal_src_dir)/event/events/gesture-detector-impl.cpp \
+  $(internal_src_dir)/event/events/gesture-event-processor.cpp \
+  $(internal_src_dir)/event/events/gesture-processor.cpp \
+  $(internal_src_dir)/event/events/hit-test-algorithm-impl.cpp \
+  $(internal_src_dir)/event/events/hover-event-processor.cpp \
+  $(internal_src_dir)/event/events/long-press-gesture-detector-impl.cpp \
+  $(internal_src_dir)/event/events/long-press-gesture-processor.cpp \
+  $(internal_src_dir)/event/events/wheel-event-processor.cpp \
+  $(internal_src_dir)/event/events/multi-point-event-util.cpp \
+  $(internal_src_dir)/event/events/pan-gesture-detector-impl.cpp \
+  $(internal_src_dir)/event/events/pan-gesture-processor.cpp \
+  $(internal_src_dir)/event/events/pinch-gesture-detector-impl.cpp \
+  $(internal_src_dir)/event/events/pinch-gesture-processor.cpp \
+  $(internal_src_dir)/event/events/tap-gesture-detector-impl.cpp \
+  $(internal_src_dir)/event/events/tap-gesture-processor.cpp \
+  $(internal_src_dir)/event/events/touch-event-processor.cpp \
+  $(internal_src_dir)/event/images/atlas-impl.cpp \
+  $(internal_src_dir)/event/images/bitmap-external.cpp \
+  $(internal_src_dir)/event/images/bitmap-packed-pixel.cpp \
+  $(internal_src_dir)/event/images/bitmap-compressed.cpp \
+  $(internal_src_dir)/event/images/image-impl.cpp \
+  $(internal_src_dir)/event/images/buffer-image-impl.cpp \
+  $(internal_src_dir)/event/images/frame-buffer-image-impl.cpp \
+  $(internal_src_dir)/event/images/encoded-buffer-image-impl.cpp \
+  $(internal_src_dir)/event/images/image-connector.cpp \
+  $(internal_src_dir)/event/images/image-factory.cpp \
+  $(internal_src_dir)/event/images/image-factory-cache.cpp \
+  $(internal_src_dir)/event/images/nine-patch-image-impl.cpp \
+  $(internal_src_dir)/event/images/resource-image-impl.cpp \
+  $(internal_src_dir)/event/images/native-image-impl.cpp \
+  $(internal_src_dir)/event/object/custom-object-internal.cpp \
+  $(internal_src_dir)/event/render-tasks/render-task-impl.cpp \
+  $(internal_src_dir)/event/render-tasks/render-task-list-impl.cpp \
+  $(internal_src_dir)/event/rendering/geometry-impl.cpp \
+  $(internal_src_dir)/event/rendering/material-impl.cpp \
+  $(internal_src_dir)/event/rendering/renderer-impl.cpp \
+  $(internal_src_dir)/event/rendering/sampler-impl.cpp \
+  $(internal_src_dir)/event/rendering/shader-impl.cpp \
+  $(internal_src_dir)/event/resources/archive.cpp \
+  $(internal_src_dir)/event/resources/image-ticket.cpp \
+  $(internal_src_dir)/event/resources/resource-client.cpp \
+  $(internal_src_dir)/event/resources/resource-ticket.cpp \
+  $(internal_src_dir)/event/resources/resource-type-path.cpp \
+  $(internal_src_dir)/event/size-negotiation/memory-pool-relayout-container.cpp \
+  $(internal_src_dir)/event/size-negotiation/relayout-controller-impl.cpp \
+  \
+  $(internal_src_dir)/render/common/culling-algorithms.cpp \
+  $(internal_src_dir)/render/common/render-algorithms.cpp \
+  $(internal_src_dir)/render/common/render-debug.cpp \
+  $(internal_src_dir)/render/common/render-instruction.cpp \
+  $(internal_src_dir)/render/common/render-instruction-container.cpp \
+  $(internal_src_dir)/render/common/render-item.cpp \
+  $(internal_src_dir)/render/common/render-tracker.cpp \
+  $(internal_src_dir)/render/common/render-manager.cpp \
+  $(internal_src_dir)/render/common/texture-cache-dispatcher.cpp \
+  $(internal_src_dir)/render/data-providers/render-data-provider.cpp \
+  $(internal_src_dir)/render/gl-resources/bitmap-texture.cpp \
+  $(internal_src_dir)/render/gl-resources/context.cpp \
+  $(internal_src_dir)/render/gl-resources/frame-buffer-state-cache.cpp \
+  $(internal_src_dir)/render/gl-resources/compressed-bitmap-texture.cpp \
+  $(internal_src_dir)/render/gl-resources/frame-buffer-texture.cpp \
+  $(internal_src_dir)/render/gl-resources/gl-call-debug.cpp \
+  $(internal_src_dir)/render/gl-resources/gpu-buffer.cpp \
+  $(internal_src_dir)/render/gl-resources/native-frame-buffer-texture.cpp \
+  $(internal_src_dir)/render/gl-resources/native-texture.cpp \
+  $(internal_src_dir)/render/gl-resources/texture.cpp \
+  $(internal_src_dir)/render/gl-resources/texture-factory.cpp \
+  $(internal_src_dir)/render/gl-resources/texture-cache.cpp \
+  $(internal_src_dir)/render/queue/render-queue.cpp \
+  $(internal_src_dir)/render/renderers/render-geometry.cpp \
+  $(internal_src_dir)/render/renderers/render-renderer.cpp \
+  $(internal_src_dir)/render/renderers/render-renderer-property-buffer.cpp \
+  $(internal_src_dir)/render/renderers/scene-graph-image-renderer.cpp \
+  $(internal_src_dir)/render/renderers/scene-graph-renderer.cpp \
+  $(internal_src_dir)/render/renderers/scene-graph-renderer-debug.cpp \
+  $(internal_src_dir)/render/shaders/custom-uniform.cpp \
+  $(internal_src_dir)/render/shaders/program.cpp \
+  $(internal_src_dir)/render/shaders/program-controller.cpp \
+  $(internal_src_dir)/render/shaders/scene-graph-shader.cpp \
+  \
+  $(internal_src_dir)/update/animation/scene-graph-animation.cpp \
+  $(internal_src_dir)/update/animation/scene-graph-constraint-base.cpp \
+  $(internal_src_dir)/update/common/discard-queue.cpp \
+  $(internal_src_dir)/update/common/property-base.cpp \
+  $(internal_src_dir)/update/common/property-owner-messages.cpp \
+  $(internal_src_dir)/update/common/property-condition-functions.cpp \
+  $(internal_src_dir)/update/common/property-condition-step-functions.cpp \
+  $(internal_src_dir)/update/common/property-condition-variable-step-functions.cpp \
+  $(internal_src_dir)/update/common/property-owner.cpp \
+  $(internal_src_dir)/update/common/scene-graph-buffers.cpp \
+  $(internal_src_dir)/update/common/scene-graph-connection-change-propagator.cpp \
+  $(internal_src_dir)/update/common/scene-graph-property-buffer.cpp \
+  $(internal_src_dir)/update/common/scene-graph-property-notification.cpp \
+  $(internal_src_dir)/update/common/uniform-map.cpp \
+  $(internal_src_dir)/update/controllers/render-message-dispatcher.cpp \
+  $(internal_src_dir)/update/controllers/scene-controller-impl.cpp \
+  $(internal_src_dir)/update/gestures/pan-gesture-profiling.cpp \
+  $(internal_src_dir)/update/gestures/scene-graph-pan-gesture.cpp \
+  $(internal_src_dir)/update/queue/update-message-queue.cpp \
+  $(internal_src_dir)/update/touch/touch-resampler.cpp \
+  $(internal_src_dir)/update/manager/prepare-render-algorithms.cpp \
+  $(internal_src_dir)/update/manager/prepare-render-instructions.cpp \
+  $(internal_src_dir)/update/manager/process-render-tasks.cpp \
+  $(internal_src_dir)/update/manager/update-algorithms.cpp \
+  $(internal_src_dir)/update/manager/update-manager.cpp \
+  $(internal_src_dir)/update/manager/update-manager-debug.cpp \
+  $(internal_src_dir)/update/node-attachments/node-attachment.cpp \
+  $(internal_src_dir)/update/node-attachments/scene-graph-camera-attachment.cpp \
+  $(internal_src_dir)/update/node-attachments/scene-graph-image-attachment.cpp \
+  $(internal_src_dir)/update/node-attachments/scene-graph-renderable-attachment.cpp \
+  $(internal_src_dir)/update/node-attachments/scene-graph-renderer-attachment.cpp \
+  $(internal_src_dir)/update/nodes/node.cpp \
+  $(internal_src_dir)/update/nodes/node-messages.cpp \
+  $(internal_src_dir)/update/nodes/scene-graph-layer.cpp \
+  $(internal_src_dir)/update/render-tasks/scene-graph-render-task.cpp \
+  $(internal_src_dir)/update/render-tasks/scene-graph-render-task-list.cpp \
+  $(internal_src_dir)/update/rendering/scene-graph-geometry.cpp \
+  $(internal_src_dir)/update/rendering/scene-graph-material.cpp \
+  $(internal_src_dir)/update/rendering/scene-graph-sampler.cpp \
+  $(internal_src_dir)/update/resources/bitmap-metadata.cpp \
+  $(internal_src_dir)/update/resources/resource-manager.cpp \
+  $(internal_src_dir)/update/resources/resource-tracker.cpp \
+  $(internal_src_dir)/update/resources/sync-resource-tracker.cpp \
+  $(internal_src_dir)/update/resources/complete-status-manager.cpp
diff --git a/dali/internal/render/common/culling-algorithms.cpp b/dali/internal/render/common/culling-algorithms.cpp
new file mode 100644 (file)
index 0000000..d60f7ef
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "culling-algorithms.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+bool Is2dBoxOutsideClipSpace(const Matrix& modelMatrix,
+                             const Matrix& modelViewProjectionMatrix,
+                             const Rect<float>& boundingBox )
+{
+  // First, calculate if the center is inside clip space:
+
+  // Downside is mvp matrix calc per renderer per frame
+  // and up to 4 matrix * vector calls.
+  const Matrix& mvp = modelViewProjectionMatrix;
+  const Vector4 translation = mvp.GetTranslation();
+
+  // Upside is point test is very simple:
+  if( -translation.w <= translation.x  &&  translation.x <= translation.w &&
+      -translation.w <= translation.y  &&  translation.y <= translation.w &&
+      -translation.w <= translation.z  &&  translation.z <= translation.w)
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  // Transform oriented bounding box to clip space:
+  Vector4 topLeft(    boundingBox.x, boundingBox.y, 0.0f, 1.0f);
+  Vector4 topRight(   boundingBox.x + boundingBox.width, boundingBox.y, 0.0f, 1.0f);
+  Vector4 bottomLeft( boundingBox.x, boundingBox.y + boundingBox.height, 0.0f, 1.0f);
+  Vector4 bottomRight(boundingBox.x + boundingBox.width, boundingBox.y + boundingBox.height, 0.0f, 1.0f);
+
+  Vector4 topLeftClip = mvp * topLeft;
+  if( -topLeftClip.w <= topLeftClip.x && topLeftClip.x <= topLeftClip.w &&
+      -topLeftClip.w <= topLeftClip.y && topLeftClip.y <= topLeftClip.w &&
+      -topLeftClip.w <= topLeftClip.z && topLeftClip.z <= topLeftClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 bottomRightClip = mvp * bottomRight;
+  if( -bottomRightClip.w <= bottomRightClip.x && bottomRightClip.x <= bottomRightClip.w &&
+      -bottomRightClip.w <= bottomRightClip.y && bottomRightClip.y <= bottomRightClip.w &&
+      -bottomRightClip.w <= bottomRightClip.z && bottomRightClip.z <= bottomRightClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 topRightClip = mvp * topRight;
+  if( -topRightClip.w <= topRightClip.x && topRightClip.x <= topRightClip.w &&
+      -topRightClip.w <= topRightClip.y && topRightClip.y <= topRightClip.w &&
+      -topRightClip.w <= topRightClip.z && topRightClip.z <= topRightClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  Vector4 bottomLeftClip = mvp * bottomLeft;
+  if( -bottomLeftClip.w <= bottomLeftClip.x && bottomLeftClip.x <= bottomLeftClip.w &&
+      -bottomLeftClip.w <= bottomLeftClip.y && bottomLeftClip.y <= bottomLeftClip.w &&
+      -bottomLeftClip.w <= bottomLeftClip.z && bottomLeftClip.z <= bottomLeftClip.w )
+  {
+    // Definitely inside clip space - don't do any more processing
+    return false;
+  }
+
+  // Check to see if all four points are outside each plane
+
+  unsigned int insideLeftPlaneCount=0;
+  unsigned int insideRightPlaneCount=0;
+  unsigned int insideTopPlaneCount=0;
+  unsigned int insideBottomPlaneCount=0;
+
+  if(-topLeftClip.w <= topLeftClip.x) { insideLeftPlaneCount++; }
+  if(-topRightClip.w <= topRightClip.x){ insideLeftPlaneCount++; }
+  if(-bottomRightClip.w <= bottomRightClip.x) {insideLeftPlaneCount++;}
+  if(-bottomLeftClip.w <= bottomLeftClip.x) {insideLeftPlaneCount++;}
+
+  if( insideLeftPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(topLeftClip.x <= topLeftClip.w) { insideRightPlaneCount++;}
+  if(topRightClip.x <= topRightClip.w) { insideRightPlaneCount++; }
+  if(bottomRightClip.x <= bottomRightClip.w) { insideRightPlaneCount++; }
+  if(bottomLeftClip.x <= bottomLeftClip.w ) { insideRightPlaneCount++; }
+
+  if( insideRightPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(-topLeftClip.w <= topLeftClip.y ) {insideTopPlaneCount++; }
+  if(-topRightClip.w <= topRightClip.y) {insideTopPlaneCount++; }
+  if(-bottomRightClip.w <= bottomRightClip.y) {insideTopPlaneCount++;}
+  if(-bottomLeftClip.w <= bottomLeftClip.y) { insideTopPlaneCount++;}
+
+  if( insideTopPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  if(topLeftClip.y <= topLeftClip.w) { insideBottomPlaneCount++; }
+  if(topRightClip.y <= topRightClip.w) { insideBottomPlaneCount++; }
+  if(bottomRightClip.y <= bottomRightClip.w) { insideBottomPlaneCount++; }
+  if(bottomLeftClip.y <= bottomLeftClip.w) { insideBottomPlaneCount++; }
+
+  if( insideBottomPlaneCount == 0 )
+  {
+    return true;
+  }
+
+  // Test if any planes are bisected, if they are, then there is likely to
+  // be an intersection into clip space.
+
+  if( insideLeftPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideRightPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideTopPlaneCount < 4 )
+  {
+    return false;
+  }
+  if( insideBottomPlaneCount < 4 )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/common/culling-algorithms.h b/dali/internal/render/common/culling-algorithms.h
new file mode 100644 (file)
index 0000000..b2e451e
--- /dev/null
@@ -0,0 +1,46 @@
+#ifndef _DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
+#define _DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * Determine if the given bounding box is outside clip space (given by the
+ * model view projection matrix).
+ * @param[in] modelMatrix The world matrix of the bounding box.
+ * @param[in] modelViewProjectionMatrix The clip space matrix
+ * @param[in] boundingBox The bounding box of the geometry in object space
+ * @return true if the bounding box is outside clip space
+ */
+bool Is2dBoxOutsideClipSpace(const Matrix& modelMatrix,
+                             const Matrix& modelViewProjectionMatrix,
+                             const Rect<float>& boundingBox );
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif //_DALI_INTERNAL_SCENE_GRAPH_CULLING_ALGORITHMS_H_
diff --git a/dali/internal/render/common/performance-monitor.h b/dali/internal/render/common/performance-monitor.h
new file mode 100644 (file)
index 0000000..cba8ec0
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef __DALI_INTERNAL_PERFORMANCE_MONITOR_H__
+#define __DALI_INTERNAL_PERFORMANCE_MONITOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+
+
+/**
+ * @brief PerformanceMonitor.
+ * Empty stubs should we decided to hook into monitoring counters
+ */
+class PerformanceMonitor
+{
+public:
+
+  /*
+   * Metric enums
+   */
+  enum Metric
+  {
+    FRAME_RATE,
+    MATRIX_MULTIPLYS,
+    QUATERNION_TO_MATRIX,
+    FLOAT_POINT_MULTIPLY,
+    RESET_PROPERTIES,
+    PROCESS_MESSAGES,
+    ANIMATE_NODES,
+    ANIMATORS_APPLIED,
+    APPLY_CONSTRAINTS,
+    CONSTRAINTS_APPLIED,
+    CONSTRAINTS_SKIPPED,
+    UPDATE_NODES,
+    PREPARE_RENDERABLES,
+    PROCESS_RENDER_TASKS,
+    DRAW_NODES,
+  };
+};
+
+#define PERFORMANCE_MONITOR_INIT(x)
+#define PERF_MONITOR_START(x)     // start of timed event
+#define PERF_MONITOR_END(x)       // end of a timed event
+#define INCREASE_COUNTER(x)       // increase a counter by 1
+#define INCREASE_BY(x,y)          // increase a count by x
+#define MATH_INCREASE_COUNTER(x)  // increase a math counter ( MATRIX_MULTIPLYS, QUATERNION_TO_MATRIX, FLOAT_POINT_MULTIPLY)
+#define MATH_INCREASE_BY(x,y)     // increase a math counter by x
+#define PERF_MONITOR_NEXT_FRAME() // update started rendering a new frame
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PERFORMANCE_MONITOR_H_
diff --git a/dali/internal/render/common/post-process-resource-dispatcher.h b/dali/internal/render/common/post-process-resource-dispatcher.h
new file mode 100644 (file)
index 0000000..ccea682
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_POST_PROCESS_RESOURCE_DISPATCHER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_POST_PROCESS_RESOURCE_DISPATCHER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Internal
+{
+struct ResourcePostProcessRequest;
+
+namespace SceneGraph
+{
+
+/**
+ * Interface which offers a dispatch mechanism for post process requests on resources
+ * Should be offered by a Render Thread object
+ */
+class PostProcessResourceDispatcher
+{
+public:
+  /**
+   * Dispatch a post process resource request to the Update thread
+   * @param[in] request A post process request
+   */
+  virtual void DispatchPostProcessRequest(ResourcePostProcessRequest& request) = 0;
+
+protected:
+  /**
+   * Virtual destructor
+   */
+  virtual ~PostProcessResourceDispatcher(){}
+};
+
+
+} // namespaces
+}
+}
+
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_POST_PROCESS_RESOURCE_DISPATCHER_H__
diff --git a/dali/internal/render/common/render-algorithms.cpp b/dali/internal/render/common/render-algorithms.cpp
new file mode 100644 (file)
index 0000000..faa4b4e
--- /dev/null
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-algorithms.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/common/render-debug.h>
+#include <dali/internal/render/common/render-list.h>
+#include <dali/internal/render/common/render-instruction.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+
+using Dali::Internal::SceneGraph::RenderItem;
+using Dali::Internal::SceneGraph::RenderList;
+using Dali::Internal::SceneGraph::RenderListContainer;
+using Dali::Internal::SceneGraph::RenderInstruction;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Render
+{
+
+/**
+ * Sets up the scissor test if required.
+ * @param[in] renderList The render list from which to get the clipping flag
+ * @param[in] context The context
+ */
+inline void SetScissorTest( const RenderList& renderList, Context& context )
+{
+  // Scissor testing
+  if( renderList.IsClipping() )
+  {
+    context.SetScissorTest( true );
+
+    const Dali::ClippingBox& clip = renderList.GetClippingBox();
+    context.Scissor(clip.x, clip.y, clip.width, clip.height);
+  }
+  else
+  {
+    context.SetScissorTest( false );
+  }
+}
+
+/**
+ * Sets the render flags for depth testing and stencil buffer
+ *
+ * @param[in] renderList The render list from which to get the render flags
+ * @param[in] context The context
+ */
+inline void SetRenderFlags( const RenderList& renderList, Context& context )
+{
+  const unsigned int renderFlags = renderList.GetFlags();
+
+  bool enableDepthBuffer = ( ( renderFlags & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
+
+  GLbitfield clearMask   = ( renderFlags & RenderList::DEPTH_CLEAR ) ? GL_DEPTH_BUFFER_BIT : 0u;
+
+  context.EnableDepthBuffer( enableDepthBuffer );
+
+  // Stencil enabled, writing, and clearing...
+  const bool enableStencilBuffer( renderFlags & RenderList::STENCIL_BUFFER_ENABLED );
+  const bool enableStencilWrite( renderFlags & RenderList::STENCIL_WRITE );
+
+  context.EnableStencilBuffer( enableStencilBuffer );
+
+  if( enableStencilBuffer )
+  {
+    context.StencilFunc( (enableStencilWrite ? GL_ALWAYS : GL_EQUAL), 1, 0xFF );
+    context.StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
+
+    clearMask |= (renderFlags & RenderList::STENCIL_CLEAR) ? GL_STENCIL_BUFFER_BIT : 0u;
+  }
+
+  // Write to stencil buffer or color buffer, but not both
+  context.StencilMask( enableStencilWrite ? 0xFF : 0x00 );
+  context.ColorMask( !enableStencilWrite );
+
+  // Clear depth and/or stencil buffer.
+  if( clearMask )
+  {
+    // only clear if the depth and/or stencil buffer have been written to after a previous clear
+    context.Clear( clearMask, Context::CHECK_CACHED_VALUES );
+  }
+}
+
+
+/**
+ * Process a render-list.
+ * @param[in] renderList The render-list to process.
+ * @param[in] context The GL context.
+ * @param[in] defaultShader The default shader to use.
+ * @param[in] buffer The current render buffer index (previous update buffer)
+ * @param[in] frameTime The elapsed time between the last two updates.
+ * @param[in] viewMatrix The view matrix from the appropriate camera.
+ * @param[in] projectionMatrix The projection matrix from the appropriate camera.
+ * @param[in] cullMode True if the renderers should be subjected to clipspace culling
+ */
+inline void ProcessRenderList(
+  const RenderList& renderList,
+  Context& context,
+  SceneGraph::TextureCache& textureCache,
+  SceneGraph::Shader& defaultShader,
+  BufferIndex bufferIndex,
+  float frameTime,
+  const Matrix& viewMatrix,
+  const Matrix& projectionMatrix,
+  bool cullMode )
+{
+  DALI_PRINT_RENDER_LIST( renderList );
+
+  SetScissorTest( renderList, context );
+  SetRenderFlags( renderList, context );
+
+  if( renderList.HasColorRenderItems() )
+  {
+    bool depthBufferEnabled = ( ( renderList.GetFlags() & RenderList::DEPTH_BUFFER_ENABLED ) != 0u );
+    size_t count = renderList.Count();
+    for ( size_t index = 0; index < count; ++index )
+    {
+      const RenderItem& item = renderList.GetItem( index );
+      DALI_PRINT_RENDER_ITEM( item );
+
+      //Enable depth writes if depth buffer is enabled and item is opaque
+      context.DepthMask( depthBufferEnabled && item.IsOpaque() );
+
+      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
+      renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
+    }
+  }
+  else
+  {
+    size_t count = renderList.Count();
+    for ( size_t index = 0; index < count; ++index )
+    {
+      const RenderItem& item = renderList.GetItem( index );
+      DALI_PRINT_RENDER_ITEM( item );
+
+      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( item.GetRenderer() );
+      renderer->Render( context, textureCache, bufferIndex, defaultShader, item.GetModelViewMatrix(), viewMatrix, projectionMatrix, frameTime, cullMode );
+    }
+
+  }
+}
+
+/**
+ * Render items from the currentIndex until the depth index changes.
+ * Leaves currentIndex pointing at the
+ *
+ * @param[in] renderList The render-list to process.
+ * @param[in] context The GL context.
+ * @param[in] defaultShader The default shader to use.
+ * @param[in] buffer The current render buffer index (previous update buffer)
+ * @param[in] frameTime The elapsed time between the last two updates.
+ * @param[in] viewMatrix The view matrix from the appropriate camera.
+ * @param[in] projectionMatrix The projection matrix from the appropriate camera.
+ * @param[in] cullMode True if the renderers should be subjected to clipspace culling
+ * @param[in] depthIndex The current depth index
+ * @param[inout] currentIndex On entry, the index in the render list of the first item at the given depth index. On exit, the index of the first item at the next depth index.
+ */
+inline void RenderItemsAtDepthIndex(
+  const RenderList&         renderList,
+  Context&                  context,
+  SceneGraph::TextureCache& textureCache,
+  SceneGraph::Shader&       defaultShader,
+  BufferIndex               bufferIndex,
+  float                     frameTime,
+  const Matrix&             viewMatrix,
+  const Matrix&             projectionMatrix,
+  bool                      cullMode,
+  int                       depthIndex,
+  size_t&                   currentIndex ) // Out parameter
+{
+  const size_t count = renderList.Count();
+
+  // Don't initialise currentIndex. Ever.
+  for( ; currentIndex < count ; currentIndex++ )
+  {
+    const RenderItem& renderItem = renderList.GetItem( currentIndex );
+    DALI_PRINT_RENDER_ITEM( renderItem );
+
+    if( renderItem.GetDepthIndex() == depthIndex )
+    {
+      SceneGraph::Renderer* renderer = const_cast< SceneGraph::Renderer* >( renderItem.GetRenderer() );
+      const Matrix& modelViewMatrix = renderItem.GetModelViewMatrix();
+      renderer->Render( context, textureCache, bufferIndex, defaultShader, modelViewMatrix, viewMatrix, projectionMatrix, frameTime, cullMode );
+
+    }
+    else
+    {
+      break; // Stop iterating when we reach a new depth index
+    }
+  }
+}
+
+
+
+void ProcessRenderInstruction( const RenderInstruction& instruction,
+                               Context& context,
+                               SceneGraph::TextureCache& textureCache,
+                               SceneGraph::Shader& defaultShader,
+                               BufferIndex bufferIndex,
+                               float frameTime )
+{
+  DALI_PRINT_RENDER_INSTRUCTION( instruction, bufferIndex );
+
+  const Matrix* viewMatrix       = instruction.GetViewMatrix( bufferIndex );
+  const Matrix* projectionMatrix = instruction.GetProjectionMatrix( bufferIndex );
+
+  DALI_ASSERT_DEBUG( NULL != viewMatrix );
+  DALI_ASSERT_DEBUG( NULL != projectionMatrix );
+
+  if( NULL != viewMatrix &&
+      NULL != projectionMatrix )
+  {
+    const RenderListContainer::SizeType count = instruction.RenderListCount();
+
+    // Iterate through each render list in order. If a pair of render lists
+    // are marked as interleaved, then process them together.
+    for( RenderListContainer::SizeType index = 0; index < count; ++index )
+    {
+      const RenderList* renderList = instruction.GetRenderList( index );
+
+      if(  renderList &&
+          !renderList->IsEmpty() )
+      {
+          ProcessRenderList( *renderList, context, textureCache, defaultShader, bufferIndex, frameTime, *viewMatrix, *projectionMatrix, instruction.mCullMode );
+      }
+    }
+  }
+}
+
+} // namespace Render
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/common/render-algorithms.h b/dali/internal/render/common/render-algorithms.h
new file mode 100644 (file)
index 0000000..f06ceca
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __DALI_INTERNAL_RENDER_ALGORITHMS_H__
+#define __DALI_INTERNAL_RENDER_ALGORITHMS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class Context;
+
+namespace SceneGraph
+{
+class RenderInstruction;
+class Shader;
+class TextureCache;
+}
+
+namespace Render
+{
+
+/**
+ * Process a render-instruction.
+ * @param[in] instruction The render-instruction to process.
+ * @param[in] context The GL context.
+ * @param[in] textureCache The texture cache used to get textures.
+ * @param[in] defaultShader The default shader.
+ * @param[in] buffer The current render buffer index (previous update buffer)
+ * @param[in] frameTime The elapsed time between the last two updates.
+ */
+void ProcessRenderInstruction( const SceneGraph::RenderInstruction& instruction,
+                               Context& context,
+                               SceneGraph::TextureCache& textureCache,
+                               SceneGraph::Shader& defaultShader,
+                               BufferIndex bufferIndex,
+                               float frameTime );
+
+} // namespace Render
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RENDER_ALGORITHMS_H__
diff --git a/dali/internal/render/common/render-debug.cpp b/dali/internal/render/common/render-debug.cpp
new file mode 100644 (file)
index 0000000..9e43d44
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-debug.h>
+
+// EXTERNAL INCLUDES
+#include <sstream>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/common/render-item.h>
+#include <dali/internal/render/common/render-list.h>
+#include <dali/internal/render/common/render-instruction.h>
+
+using Dali::Internal::SceneGraph::RenderList;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace Render
+{
+
+void PrintFrameStart( BufferIndex bufferIndex )
+{
+  DALI_LOG_RENDER_INFO( "RENDER START - bufferIndex: %d\n", bufferIndex );
+}
+
+void PrintFrameEnd()
+{
+  DALI_LOG_RENDER_INFO( "RENDER END\n\n" );
+}
+
+void PrintRenderInstruction( const SceneGraph::RenderInstruction& instruction, BufferIndex index )
+{
+  const char* target = (0 != instruction.mOffscreenTextureId) ? "FrameBuffer" : "Screen";
+
+  std::stringstream debugStream;
+  debugStream << "Rendering to " << target << ", View: " << *(instruction.GetViewMatrix(index)) << " Projection: " << *(instruction.GetProjectionMatrix(index));
+
+  if( instruction.mIsViewportSet )
+  {
+    debugStream << " Viewport: " << instruction.mViewport.x << "," << instruction.mViewport.y << " " << instruction.mViewport.width << "x" << instruction.mViewport.height;
+  }
+
+  if( instruction.mIsClearColorSet )
+  {
+    debugStream << " ClearColor: " << instruction.mClearColor;
+  }
+
+  std::string debugString( debugStream.str() );
+  DALI_LOG_RENDER_INFO( "   %s\n", debugString.c_str() );
+}
+
+void PrintRenderList( const RenderList& list )
+{
+  unsigned int flags = list.GetFlags();
+
+  std::stringstream debugStream;
+  debugStream << "Rendering items";
+
+  if( flags )
+  {
+    debugStream << " with:";
+
+    if( flags & RenderList::DEPTH_BUFFER_ENABLED )
+    {
+      debugStream << " DEPTH_TEST";
+    }
+
+    if( flags & RenderList::DEPTH_WRITE )
+    {
+      debugStream << " DEPTH_WRITE";
+    }
+
+    if( flags & RenderList::DEPTH_CLEAR )
+    {
+      debugStream << " DEPTH_CLEAR";
+    }
+
+    if( flags & RenderList::STENCIL_BUFFER_ENABLED )
+    {
+      debugStream << " STENCIL_TEST";
+    }
+
+    if( flags & RenderList::STENCIL_WRITE )
+    {
+      debugStream << " STENCIL_WRITE";
+    }
+
+    if( flags & RenderList::STENCIL_CLEAR )
+    {
+      debugStream << " STENCIL_CLEAR";
+    }
+  }
+  else
+  {
+    debugStream << " without any DEPTH_TEST, DEPTH_WRITE etc";
+  }
+
+  if( list.IsClipping() )
+  {
+    debugStream << ", ClippingBox: " << list.GetClippingBox().x << "," << list.GetClippingBox().y << " " << list.GetClippingBox().width << "x" << list.GetClippingBox().height;
+  }
+
+  std::string debugString( debugStream.str() );
+  DALI_LOG_RENDER_INFO( "      %s\n", debugString.c_str() );
+}
+
+void PrintRenderItem( const SceneGraph::RenderItem& item )
+{
+  std::stringstream debugStream;
+  debugStream << "Rendering item, ModelView: " << item.GetModelViewMatrix();
+
+  std::string debugString( debugStream.str() );
+  DALI_LOG_RENDER_INFO( "         %s\n", debugString.c_str() );
+}
+
+void PrintRendererCount( unsigned int frameCount, unsigned int rendererCount )
+{
+  if( frameCount % 120 == 30 ) // Print every 2 seconds reg
+  {
+    Debug::LogMessage( Debug::DebugInfo, "Renderer Total # renderers: %u\n", rendererCount );
+  }
+}
+
+void PrintCullCount( unsigned int frameCount, unsigned int culledCount )
+{
+  if( frameCount % 120 == 30 ) // Print every 2 seconds reg
+  {
+    Debug::LogMessage( Debug::DebugInfo, "Renderer # Culled renderers: %u\n", culledCount );
+  }
+}
+
+
+
+} // Render
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/render/common/render-debug.h b/dali/internal/render/common/render-debug.h
new file mode 100644 (file)
index 0000000..59dbf66
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __DALI_INTERNAL_RENDER_DEBUG_H__
+#define __DALI_INTERNAL_RENDER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+
+// define this to print information about the items rendered each frame
+#undef DALI_PRINT_RENDER_INFO
+
+#ifdef DALI_PRINT_RENDER_INFO
+
+#define DALI_PRINT_RENDER_START(x) Render::PrintFrameStart(x);
+#define DALI_PRINT_RENDER_END() Render::PrintFrameEnd();
+#define DALI_PRINT_RENDER_INSTRUCTION(x,index) Render::PrintRenderInstruction(x,index);
+#define DALI_PRINT_RENDER_LIST(x) Render::PrintRenderList(x);
+#define DALI_PRINT_RENDER_ITEM(x) Render::PrintRenderItem(x);
+
+#else // DALI_PRINT_RENDER_INFO
+
+#define DALI_PRINT_RENDER_START(x)
+#define DALI_PRINT_RENDER_END()
+#define DALI_PRINT_RENDER_INSTRUCTION(x,index)
+#define DALI_PRINT_RENDER_LIST(x)
+#define DALI_PRINT_RENDER_ITEM(x)
+
+#endif // DALI_PRINT_RENDER_INFO
+
+#undef DALI_PRINT_RENDERERS
+
+// Turn this on to see a snapshot of # renderers and # culled renderers every 2 seconds
+//#define DALI_PRINT_RENDERERS 1
+
+#ifdef DALI_PRINT_RENDERERS
+#define DALI_PRINT_RENDERER_COUNT(x, y)  Render::PrintRendererCount(x, y)
+#define DALI_PRINT_CULL_COUNT(x, y)      Render::PrintCullCount(x, y)
+#else // DALI_PRINT_RENDERERS
+#define DALI_PRINT_RENDERER_COUNT(x, y)
+#define DALI_PRINT_CULL_COUNT(x, y)
+#endif // DALI_PRINT_RENDERERS
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class PropertyInputImpl;
+
+namespace SceneGraph
+{
+class RenderInstruction;
+struct RenderList;
+class RenderItem;
+}
+
+namespace Render
+{
+
+/**
+ * Print a debug message at the start of the render-thread.
+ * @param[in] buffer The current render buffer index (previous update buffer)
+ */
+void PrintFrameStart( BufferIndex bufferIndex );
+
+/**
+ * Print a debug message at the end of the render-thread.
+ */
+void PrintFrameEnd();
+
+/**
+ * Print some information about a render-instruction.
+ * @param[in] instruction The render-instruction.
+ * @param[in] index to use
+ */
+void PrintRenderInstruction( const SceneGraph::RenderInstruction& instruction, BufferIndex index );
+
+/**
+ * Print some information about a render-list.
+ * @param[in] instruction The render-list.
+ */
+void PrintRenderList( const SceneGraph::RenderList& list );
+
+/**
+ * Print some information about a render-item.
+ * @param[in] instruction The render-item.
+ */
+void PrintRenderItem( const SceneGraph::RenderItem& item );
+
+/**
+ * Print the number of culled renderers
+ * @param[in] frameCount The frame counter
+ * @param[in] culledCount The number of culled renderers
+ */
+void PrintCullCount( unsigned int frameCount, unsigned int culledCount );
+
+/**
+ * Print the number of image renderers
+ * @param[in] frameCount The frame counter
+ * @param[in] rendererCount The number of image renderers
+ */
+void PrintRendererCount( unsigned int frameCount, unsigned int rendererCount );
+
+} // Render
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_RENDER_DEBUG_H__
diff --git a/dali/internal/render/common/render-instruction-container.cpp b/dali/internal/render/common/render-instruction-container.cpp
new file mode 100644 (file)
index 0000000..3cbff8a
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-instruction-container.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/common/render-instruction.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderInstructionContainer::RenderInstructionContainer()
+{
+  // array initialisation in ctor initializer list not supported until C++ 11
+  mIndex[ 0 ] = 0u;
+  mIndex[ 1 ] = 0u;
+}
+
+RenderInstructionContainer::~RenderInstructionContainer()
+{
+  // OwnerContainer deletes the instructions
+}
+
+void RenderInstructionContainer::ResetAndReserve( BufferIndex bufferIndex, size_t capacityRequired )
+{
+  mIndex[ bufferIndex ] = 0u;
+  size_t oldcapacity = mInstructions[ bufferIndex ].Capacity();
+  if( oldcapacity < capacityRequired )
+  {
+    mInstructions[ bufferIndex ].Reserve( capacityRequired );
+    // add N new elements
+    for( ; oldcapacity < capacityRequired; ++oldcapacity )
+    {
+      mInstructions[ bufferIndex ].PushBack( new RenderInstruction );
+    }
+  }
+  // Note that we may have spare elements in the list, we don't remove them as that would
+  // decrease the capacity of our container and lead to possibly reallocating, which we hate
+  // RenderInstruction holds a lot of data so we keep them and recycle instead of new & delete
+}
+
+size_t RenderInstructionContainer::Count( BufferIndex bufferIndex )
+{
+  // mIndex contains the number of instructions that have been really prepared and updated
+  // (from UpdateManager through GetNextInstruction)
+  return mIndex[ bufferIndex ];
+}
+
+RenderInstruction& RenderInstructionContainer::GetNextInstruction( BufferIndex bufferIndex )
+{
+  // At protects against running out of space
+  return At( bufferIndex, mIndex[ bufferIndex ]++ );
+}
+
+RenderInstruction& RenderInstructionContainer::At( BufferIndex bufferIndex, size_t index )
+{
+  DALI_ASSERT_DEBUG( index < mInstructions[ bufferIndex ].Count() );
+
+  return *mInstructions[ bufferIndex ][ index ];
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/common/render-instruction-container.h b/dali/internal/render/common/render-instruction-container.h
new file mode 100644 (file)
index 0000000..4fb4cb5
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_CONTAINER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_CONTAINER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/owner-container.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderInstruction;
+
+/**
+ * Class to encapsulate double buffered render instruction data
+ */
+class RenderInstructionContainer
+{
+public:
+
+  /**
+   * Constructor
+   */
+  RenderInstructionContainer();
+
+  /**
+   * Destructor
+   */
+  ~RenderInstructionContainer();
+
+  /**
+   * Reset the container index and reserve space in the container if needed
+   * @param bufferIndex to reset
+   * @param capacityRequired in the container
+   */
+  void ResetAndReserve( BufferIndex bufferIndex, size_t capacityRequired );
+
+  /**
+   * Return the count of instructions in the container
+   * @param bufferIndex to use
+   * @return the count of elements
+   */
+  size_t Count( BufferIndex bufferIndex );
+
+  /**
+   * Get a reference to the next instruction
+   * @param bufferIndex to use
+   */
+  RenderInstruction& GetNextInstruction( BufferIndex bufferIndex );
+
+  /**
+   * Get a reference to the instruction at index
+   * @param bufferIndex to use
+   * @param index to use
+   */
+  RenderInstruction& At( BufferIndex bufferIndex, size_t index );
+
+private:
+
+  unsigned int mIndex[ 2 ]; ///< count of the elements that have been added
+  typedef OwnerContainer< RenderInstruction* > InstructionContainer;
+  InstructionContainer mInstructions[ 2 ]; /// Double buffered instruction lists
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_CONTAINER_H__
diff --git a/dali/internal/render/common/render-instruction.cpp b/dali/internal/render/common/render-instruction.cpp
new file mode 100644 (file)
index 0000000..74f641b
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-instruction.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h> // for Color::BLACK
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderInstruction::RenderInstruction()
+: mRenderTracker( NULL ),
+  mClearColor(),
+  mIsViewportSet( false ),
+  mIsClearColorSet( false ),
+  mCullMode(false),
+  mOffscreenTextureId( 0 ),
+  mCameraAttachment( 0 ),
+  mNextFreeRenderList( 0 )
+{
+  // reserve 6 lists, which is enough for three layers with opaque and transparent things on
+  mRenderLists.Reserve( 6 );
+}
+
+RenderInstruction::~RenderInstruction()
+{ // pointer container releases the renderlists
+}
+
+RenderList& RenderInstruction::GetNextFreeRenderList( size_t capacityRequired )
+{
+  // check if we have enough lists, we can only be one behind at worst
+  if( mRenderLists.Count() <= mNextFreeRenderList )
+  {
+    mRenderLists.PushBack( new RenderList ); // Push a new empty render list
+  }
+
+  // check capacity of the list and reserve if not big enough
+  if( mRenderLists[ mNextFreeRenderList ]->Capacity() < capacityRequired )
+  {
+    mRenderLists[ mNextFreeRenderList ]->Reserve( capacityRequired );
+  }
+
+  // return the list mNextFreeRenderList points to and increase by one
+  return *mRenderLists[ mNextFreeRenderList++ ];
+}
+
+void RenderInstruction::UpdateCompleted()
+{
+  // lets do some housekeeping, remove any lists that were not needed because
+  // application might have removed a layer permanently
+  RenderListContainer::Iterator iter = mRenderLists.Begin();
+  RenderListContainer::ConstIterator end = mRenderLists.End();
+  for( ;iter != end; ++iter )
+  {
+    // tell the list to do its housekeeping
+    (*iter)->ReleaseUnusedItems();
+  }
+
+  // release any extra lists
+  if( mRenderLists.Count() > mNextFreeRenderList )
+  {
+    mRenderLists.Resize( mNextFreeRenderList );
+  }
+}
+
+RenderListContainer::SizeType RenderInstruction::RenderListCount() const
+{
+  return mNextFreeRenderList;
+}
+
+const RenderList* RenderInstruction::GetRenderList( RenderListContainer::SizeType index ) const
+{
+  DALI_ASSERT_DEBUG( (index < mNextFreeRenderList ) && (index < mRenderLists.Size()) && "Renderlist index out of container bounds" );
+
+  // Return null if the caller has passed an invalid index:
+  if( index >= std::min( mNextFreeRenderList, mRenderLists.Size() ) )
+  {
+    return 0;
+  }
+
+  return mRenderLists[ index ];
+}
+
+void RenderInstruction::Reset( CameraAttachment* cameraAttachment,
+                               unsigned int      offscreenTextureId,
+                               const Viewport*   viewport,
+                               const Vector4*    clearColor )
+{
+  mCameraAttachment = cameraAttachment;
+  mViewport = viewport ? *viewport : Viewport();
+  mIsViewportSet = NULL != viewport;
+  mClearColor = clearColor ? *clearColor : Color::BLACK;
+  mIsClearColorSet = NULL != clearColor;
+  mCullMode = false;
+  mOffscreenTextureId = offscreenTextureId;
+  mRenderTracker = NULL;
+  mNextFreeRenderList = 0;
+
+  RenderListContainer::Iterator iter = mRenderLists.Begin();
+  RenderListContainer::ConstIterator end = mRenderLists.End();
+  for( ;iter != end; ++iter )
+  {
+    // since mRenderLists is a vector of RenderLists we dont want to clear it
+    // as it ends up releasing and later reallocating loads of vectors
+    // reset the renderlist
+    (*iter)->Reset();
+  }
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/common/render-instruction.h b/dali/internal/render/common/render-instruction.h
new file mode 100644 (file)
index 0000000..3713f99
--- /dev/null
@@ -0,0 +1,156 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/viewport.h>
+#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+#include <dali/internal/render/common/render-list.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderTracker;
+class CameraAttachment;
+
+/**
+ * A set of rendering instructions consisting of:
+ * - The list(s) of renderers sorted in the correct rendering order.
+ * - The camera related matrices to use when rendering.
+ * - An optional off-screen render target.
+ * There is one RenderInstruction per RenderTarget, all renderers of all layers
+ * get collated onto the single list of lists (mRenderLists)
+ */
+class RenderInstruction
+{
+public:
+
+  /**
+   * Default constructor so this can be stored in STL containers
+   */
+  RenderInstruction();
+
+  /**
+   * Destructor
+   */
+  ~RenderInstruction();
+
+  /**
+   * Get the next free Renderlist
+   * @param capacityRequired in this list
+   * @return the renderlist
+   */
+  RenderList& GetNextFreeRenderList( size_t capacityRequired );
+
+  /**
+   * Inform the RenderInstruction that processing for this frame is complete
+   * This method should only be called from Update thread
+   */
+  void UpdateCompleted();
+
+  /**
+   * @return the count of active Renderlists
+   */
+  RenderListContainer::SizeType RenderListCount() const;
+
+  /**
+   * Return the renderlist at given index
+   * @pre index is inside the valid range of initialized lists
+   * @param index of list to return
+   * @return pointer to the renderlist, or null if the index is out of bounds.
+   */
+  const RenderList* GetRenderList( RenderListContainer::SizeType index ) const;
+
+  /**
+   * Reset render-instruction
+   * render-lists are cleared but not released, while matrices and other settings reset in
+   * preparation for building a set of instructions for the renderer.
+   *
+   * @param[in] cameraAttachment to use to get view and projection matrices.
+   * @param[in] offscreenId A resource Id of an off-screen render target, or 0
+   * @param[in] viewport A pointer to a viewport, of NULL.
+   * @param[in] clearColor A pointer to a color to clear with, or NULL if no clear is required.
+   */
+  void Reset( CameraAttachment* cameraAttachment,
+              unsigned int offscreenId,
+              const Viewport* viewport,
+              const Vector4* clearColor );
+
+  /**
+   * Get the view matrix for rendering
+   * @param index of the rendering side
+   * @return the view matrix
+   */
+  const Matrix* GetViewMatrix( BufferIndex index ) const
+  {
+    // inlined as this is called once per frame per render instruction
+    return &mCameraAttachment->GetViewMatrix( index );
+  }
+
+  /**
+   * Get the projection matrix for rendering
+   * @param index of the rendering side
+   * @return the projection matrix
+   */
+  const Matrix* GetProjectionMatrix( BufferIndex index ) const
+  {
+    // inlined as this is called once per frame per render instruction
+    return &mCameraAttachment->GetProjectionMatrix( index );
+  }
+
+private:
+
+  // Undefined
+  RenderInstruction(const RenderInstruction&);
+  // Undefined
+  RenderInstruction& operator=(const RenderInstruction& rhs);
+
+public: // Data, TODO hide these
+
+  RenderTracker* mRenderTracker;        ///< Pointer to an optional tracker object (not owned)
+
+  Viewport mViewport;                   ///< Optional viewport
+  Vector4  mClearColor;                 ///< Optional color to clear with
+  bool     mIsViewportSet:1;            ///< Flag to determine whether the viewport is set
+  bool     mIsClearColorSet:1;          ///< Flag to determine whether the clear-color is set
+  bool     mCullMode:1;                 ///< True if renderers should be frustum culled
+
+  unsigned int mOffscreenTextureId;     ///< Optional offscreen target
+
+private: // Data
+
+  CameraAttachment* mCameraAttachment;  ///< camera that is used
+  RenderListContainer mRenderLists;     ///< container of all render lists
+  RenderListContainer::SizeType mNextFreeRenderList;     ///< index for the next free render list
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_INSTRUCTION_H__
diff --git a/dali/internal/render/common/render-item.cpp b/dali/internal/render/common/render-item.cpp
new file mode 100644 (file)
index 0000000..a082149
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-item.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderItem::RenderItem()
+: mModelViewMatrix( false ),
+  mRenderer( NULL ),
+  mDepthIndex(0),
+  mIsOpaque(true)
+{
+}
+
+RenderItem::~RenderItem()
+{
+}
+
+void RenderItem::Reset()
+{
+  mRenderer = NULL;
+}
+
+void RenderItem::SetRenderer( Renderer* renderer )
+{
+  mRenderer = renderer;
+}
+
+const Renderer* RenderItem::GetRenderer() const
+{
+  return mRenderer;
+}
+
+Matrix& RenderItem::GetModelViewMatrix()
+{
+  return mModelViewMatrix;
+}
+
+const Matrix& RenderItem::GetModelViewMatrix() const
+{
+  return mModelViewMatrix;
+}
+
+void RenderItem::SetDepthIndex( int depthIndex )
+{
+  mDepthIndex = depthIndex;
+}
+
+void RenderItem::SetIsOpaque( bool isOpaque )
+{
+  mIsOpaque = isOpaque;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/common/render-item.h b/dali/internal/render/common/render-item.h
new file mode 100644 (file)
index 0000000..839a1bd
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/math/matrix.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Renderer;
+class RenderItem;
+
+typedef std::vector< RenderItem > RendererItemContainer;
+
+/**
+ * A render-item is a renderer & modelView matrix pair.
+ */
+class RenderItem
+{
+public:
+
+  /**
+   * Create a new render-item.
+   */
+  RenderItem();
+
+  /**
+   * Non-virtual destructor; RenderItem is not suitable as a base class.
+   */
+  ~RenderItem();
+
+  /**
+   * Reset the render-item.
+   */
+  void Reset();
+
+  /**
+   * Retrieve the renderer.
+   * @return The renderer.
+   */
+  const Renderer* GetRenderer() const;
+
+  /**
+   * Set the renderer
+   * @param[in] renderer The renderer
+   */
+  void SetRenderer( Renderer* renderer );
+
+  /**
+   * Retrieve the modelView matrix.
+   * @return The modelView matrix.
+   */
+  Matrix& GetModelViewMatrix();
+
+  /**
+   * Retrieve the modelView matrix.
+   * @return The modelView matrix.
+   */
+  const Matrix& GetModelViewMatrix() const;
+
+  /**
+   * Retrieve the depth index
+   */
+  int GetDepthIndex() const
+  {
+    return mDepthIndex;
+  }
+
+  /**
+   * Set the depth index
+   */
+  void SetDepthIndex( int depthIndex );
+
+  /**
+   * Set if the RenderItem is opaque
+   * @param[in] isOpaque true if the RenderItem is opaque, false otherwise
+   */
+  void SetIsOpaque( bool isOpaque );
+
+  /**
+   * Check if the RenderItem is opaque
+   * @return True if it is opaque, false otherwise
+   */
+  bool IsOpaque() const
+  {
+    return mIsOpaque;
+  }
+
+private:
+
+  // RenderItems should not be copied as they are heavy
+  RenderItem( const RenderItem& item );
+  RenderItem& operator = ( const RenderItem& item );
+
+  Matrix    mModelViewMatrix;
+  Renderer* mRenderer;
+  int       mDepthIndex;
+  bool      mIsOpaque:1;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_ITEM_H__
diff --git a/dali/internal/render/common/render-list.h b/dali/internal/render/common/render-list.h
new file mode 100644 (file)
index 0000000..dfe58f1
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/rect.h>
+#include <dali/internal/render/common/render-item.h>
+#include <dali/internal/common/owner-container.h>
+
+namespace Dali
+{
+
+typedef Rect<int> ClippingBox;
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Layer;
+class Renderer;
+
+class RenderItem;
+typedef OwnerContainer< RenderItem* > RenderItemContainer;
+
+struct RenderList;
+typedef OwnerContainer< RenderList* > RenderListContainer;
+
+/**
+ * The RenderList structure provides the renderer with a list of renderers and
+ * a set of flags to tell it what depth buffering is required.
+ */
+struct RenderList
+{
+public:
+
+  /**
+   * The RenderFlags describe how the objects are rendered using the depth and stencil buffer.
+   *
+   * The flags which relate to GL_DEPTH_TEST and GL_STENCIL_TEST are called
+   * DEPTH_BUFFER_ENABLED and STENCIL_BUFFER_ENABLED to avoid any confusion.
+   * E.g. if GL_DEPTH_TEST is not enabled you can't write to the depth buffer, which can cause confusion.
+   *
+   */
+  enum RenderFlags
+  {
+    DEPTH_BUFFER_ENABLED   = 1 << 0, ///< If depth buffer should be used for writing / test operations
+    DEPTH_WRITE            = 1 << 1, ///< If the depth buffer is writable
+    DEPTH_CLEAR            = 1 << 2, ///< If the depth buffer should first be cleared
+    STENCIL_BUFFER_ENABLED = 1 << 3, ///< If stencil buffer should be used for writing / test operation
+    STENCIL_WRITE          = 1 << 4, ///< If the stencil buffer is writable
+    STENCIL_CLEAR          = 1 << 5, ///< If the stencil buffer should first be cleared
+
+  };
+
+  /**
+   * Constructor
+   */
+  RenderList()
+  : mNextFree( 0 ),
+    mRenderFlags( 0u ),
+    mClippingBox( NULL ),
+    mSourceLayer( NULL ),
+    mHasColorRenderItems( false )
+  {
+  }
+
+  /**
+   * Destructor
+   */
+  ~RenderList()
+  {
+    // pointer container deletes the render items
+    delete mClippingBox;
+  }
+
+  /**
+   * Clear the render flags
+   */
+  void ClearFlags()
+  {
+    mRenderFlags = 0u;
+  }
+
+  /**
+   * Set particular render flags
+   * @param[in] flags The set of flags to bitwise or with existing flags
+   */
+  void SetFlags( unsigned int flags )
+  {
+    mRenderFlags |= flags;
+  }
+
+  /**
+   * Retrieve the render flags.
+   * @return the render flags.
+   */
+  unsigned int GetFlags() const
+  {
+    return mRenderFlags;
+  }
+
+  /**
+   * Reset the render list for next frame
+   */
+  void Reset()
+  {
+    // we dont want to delete and re-create the render items every frame
+    mNextFree = 0;
+    mRenderFlags = 0u;
+
+    delete mClippingBox;
+    mClippingBox = NULL;
+  }
+
+  /**
+   * Reserve space in the render list
+   * @param size to reserve
+   */
+  void Reserve( RenderItemContainer::SizeType size )
+  {
+    mNextFree = 0;
+    mItems.Reserve( size );
+  }
+
+  /**
+   * @return the capacity of the render list
+   */
+  RenderItemContainer::SizeType Capacity()
+  {
+    return mItems.Capacity();
+  }
+
+  /**
+   * Get next free render item
+   * @return reference to the next available RenderItem
+   */
+  RenderItem& GetNextFreeItem()
+  {
+    // check if we have enough items, we can only be one behind at worst
+    if( mItems.Count() <= mNextFree )
+    {
+      mItems.PushBack( new RenderItem ); // Push a new empty render item
+    }
+    // get the item mNextFree points to and increase by one
+    RenderItem& item = *mItems[ mNextFree++ ];
+    item.Reset();
+    return item;
+  }
+
+  /**
+   * Get item at a given position in the list
+   */
+  RenderItem& GetItem( RenderItemContainer::SizeType index ) const
+  {
+    DALI_ASSERT_DEBUG( index < GetCachedItemCount() );
+    return *mItems[ index ];
+  }
+
+  /**
+   * Get renderer from an item in the list
+   */
+  const Renderer* GetRenderer( RenderItemContainer::SizeType index ) const
+  {
+    DALI_ASSERT_DEBUG( index < GetCachedItemCount() );
+    return mItems[ index ]->GetRenderer();
+  }
+
+  /**
+   * Get the number of real items
+   * Because of caching, the actual size may be bit more
+   * @return The number of items
+   */
+  RenderItemContainer::SizeType Count() const
+  {
+    return mNextFree;
+  }
+
+  /**
+   * @return the number of items cached by the list
+   */
+  RenderItemContainer::SizeType GetCachedItemCount() const
+  {
+    return mItems.Count();
+  }
+
+  /**
+   * Tells the render list to reuse the items from the cache
+   */
+  void ReuseCachedItems()
+  {
+    mNextFree = mItems.Count();
+  }
+
+  /**
+   * Predicate to inform if the list is empty
+   */
+  bool IsEmpty() const
+  {
+    return (mNextFree == 0);
+  }
+
+  /**
+   * Set clipping
+   * @param clipping on/off
+   * @param box for clipping
+   */
+  void SetClipping( bool clipping, const ClippingBox& box )
+  {
+    if( clipping )
+    {
+      ClippingBox* newBox = new ClippingBox( box );
+      delete mClippingBox;
+      mClippingBox = newBox;
+    }
+  }
+
+  /**
+   * @return true if clipping is on
+   */
+  bool IsClipping() const
+  {
+    return (NULL != mClippingBox);
+  }
+
+  /**
+   * @return the clipping box
+   */
+  const ClippingBox& GetClippingBox() const
+  {
+    return *mClippingBox;
+  }
+
+  /**
+   * @return the container (for sorting)
+   */
+  RenderItemContainer& GetContainer()
+  {
+    return mItems;
+  }
+
+  /**
+   * Do some housekeeping to keep memory consumption low
+   */
+  void ReleaseUnusedItems()
+  {
+    // release any non-used RenderItems
+    if( mItems.Count() > mNextFree )
+    {
+      mItems.Resize( mNextFree );
+    }
+  }
+
+  /**
+   * @return the source layer these renderitems originate from
+   */
+  Layer* GetSourceLayer()
+  {
+    return mSourceLayer;
+  }
+
+  /**
+   * @param layer these renderitems originate from
+   */
+  void SetSourceLayer( Layer* layer )
+  {
+    mSourceLayer = layer;
+  }
+
+  /**
+   * Set if the RenderList contains color RenderItems
+   * @param[in] hasColorRenderItems True if it contains color RenderItems, false otherwise
+   */
+  void SetHasColorRenderItems( bool hasColorRenderItems )
+  {
+    mHasColorRenderItems = hasColorRenderItems;
+  }
+
+  /**
+   * Check if the RenderList contains color RenderItems
+   * @return true if the RenderList contains color RenderItems, false otherwise
+   */
+  bool HasColorRenderItems() const
+  {
+    return mHasColorRenderItems;
+  }
+
+private:
+
+  /*
+   * Copy constructor and assignment operator not defined
+   */
+  RenderList( const RenderList& rhs );
+  const RenderList& operator=( const RenderList& rhs );
+
+  RenderItemContainer mItems; ///< Each item is a renderer and matrix pair
+  RenderItemContainer::SizeType mNextFree;              ///< index for the next free item to use
+
+  unsigned int mRenderFlags;    ///< The render flags
+
+  ClippingBox* mClippingBox;               ///< The clipping box, in window coordinates, when clipping is enabled
+  Layer*       mSourceLayer;              ///< The originating layer where the renderers are from
+  bool         mHasColorRenderItems : 1;  ///< True if list contains color render items
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_LIST_H__
diff --git a/dali/internal/render/common/render-manager.cpp b/dali/internal/render/common/render-manager.cpp
new file mode 100644 (file)
index 0000000..c3d5a41
--- /dev/null
@@ -0,0 +1,588 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/core.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/render-algorithms.h>
+#include <dali/internal/render/common/render-debug.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/internal/render/common/render-instruction.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/frame-buffer-texture.h>
+#include <dali/internal/render/gl-resources/native-frame-buffer-texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/render-geometry.h>
+#include <dali/internal/render/shaders/program-controller.h>
+
+// Uncomment the next line to enable frame snapshot logging
+//#define FRAME_SNAPSHOT_LOGGING
+
+#ifdef FRAME_SNAPSHOT_LOGGING
+
+using namespace Dali::Internal::Render;
+
+namespace // unnamed namespace
+{
+unsigned int SNAPSHOT_FRAME_FREQUENCY = 1200; // dump every 20-30 seconds
+} // unnamed namespace
+
+#define SET_SNAPSHOT_FRAME_LOG_LEVEL \
+  DALI_LOG_FILTER_SET_LEVEL(Context::gGlLogFilter, ((GetFrameCount() % SNAPSHOT_FRAME_FREQUENCY)==5 ? Debug::General : Debug::Concise));
+
+#else // FRAME_SNAPSHOT_LOGGING
+
+#define SET_SNAPSHOT_FRAME_LOG_LEVEL
+
+#endif // FRAME_SNAPSHOT_LOGGING
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+typedef OwnerContainer< Renderer* >            RendererOwnerContainer;
+typedef RendererOwnerContainer::Iterator       RendererOwnerIter;
+
+typedef OwnerContainer< RenderGeometry* >      RenderGeometryOwnerContainer;
+typedef RenderGeometryOwnerContainer::Iterator RenderGeometryOwnerIter;
+
+typedef OwnerContainer< RenderTracker* >       RenderTrackerContainer;
+typedef RenderTrackerContainer::Iterator       RenderTrackerIter;
+typedef RenderTrackerContainer::ConstIterator  RenderTrackerConstIter;
+
+/**
+ * Structure to contain internal data
+ */
+struct RenderManager::Impl
+{
+  Impl( Dali::Integration::GlAbstraction& glAbstraction,
+        ResourcePostProcessList& resourcePostProcessQ,
+        PostProcessResourceDispatcher& postProcessDispatcher )
+  : context( glAbstraction ),
+    renderQueue(),
+    textureCache( renderQueue, postProcessDispatcher, context ),
+    resourcePostProcessQueue( resourcePostProcessQ ),
+    instructions(),
+    backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
+    frameTime( 0.0f ),
+    lastFrameTime( 0.0f ),
+    frameCount( 0 ),
+    renderBufferIndex( SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX ),
+    defaultSurfaceRect(),
+    rendererContainer(),
+    renderersAdded( false ),
+    firstRenderCompleted( false ),
+    defaultShader( NULL ),
+    programController( glAbstraction )
+  {
+  }
+
+  ~Impl()
+  {
+  }
+
+  void AddRenderTracker( RenderTracker* renderTracker )
+  {
+    DALI_ASSERT_DEBUG( renderTracker != NULL );
+    mRenderTrackers.PushBack( renderTracker );
+  }
+
+  void RemoveRenderTracker( RenderTracker* renderTracker )
+  {
+    DALI_ASSERT_DEBUG( renderTracker != NULL );
+    for(RenderTrackerIter iter = mRenderTrackers.Begin(), end = mRenderTrackers.End(); iter != end; ++iter)
+    {
+      if( *iter == renderTracker )
+      {
+        mRenderTrackers.Erase( iter );
+        break;
+      }
+    }
+  }
+
+  void UpdateTrackers()
+  {
+    for(RenderTrackerIter iter = mRenderTrackers.Begin(), end = mRenderTrackers.End(); iter != end; ++iter)
+    {
+      (*iter)->PollSyncObject();
+    }
+  }
+
+  // the order is important for destruction,
+  // programs are owned by context at the moment.
+  Context                       context;                  ///< holds the GL state
+  RenderQueue                   renderQueue;              ///< A message queue for receiving messages from the update-thread.
+  TextureCache                  textureCache;             ///< Cache for all GL textures
+  ResourcePostProcessList&      resourcePostProcessQueue; ///< A queue for requesting resource post processing in update thread
+
+  // Render instructions describe what should be rendered during RenderManager::Render()
+  // Owned by RenderManager. Update manager updates instructions for the next frame while we render the current one
+  RenderInstructionContainer    instructions;
+
+  Vector4                       backgroundColor;          ///< The glClear color used at the beginning of each frame.
+
+  volatile float                frameTime;                ///< The elapsed time since the previous frame
+  float                         lastFrameTime;            ///< Last frame delta.
+
+  unsigned int                  frameCount;               ///< The current frame count
+  BufferIndex                   renderBufferIndex;        ///< The index of the buffer to read from; this is opposite of the "update" buffer
+
+  Rect<int>                     defaultSurfaceRect;       ///< Rectangle for the default surface we are rendering to
+
+  RendererOwnerContainer        rendererContainer;        ///< List of owned renderers
+  RenderGeometryOwnerContainer  renderGeometryContainer;  ///< List of owned RenderGeometries
+
+  bool                          renderersAdded;
+
+  RenderTrackerContainer        mRenderTrackers;          ///< List of render trackers
+
+  bool                          firstRenderCompleted;     ///< False until the first render is done
+  Shader*                       defaultShader;            ///< Default shader to use
+  ProgramController             programController;        ///< Owner of the GL programs
+};
+
+RenderManager* RenderManager::New( Integration::GlAbstraction& glAbstraction, ResourcePostProcessList& resourcePostProcessQ )
+{
+  RenderManager* manager = new RenderManager;
+  manager->mImpl = new Impl( glAbstraction, resourcePostProcessQ, *manager );
+  return manager;
+}
+
+RenderManager::RenderManager()
+: mImpl(NULL)
+{
+}
+
+RenderManager::~RenderManager()
+{
+  delete mImpl;
+}
+
+RenderQueue& RenderManager::GetRenderQueue()
+{
+  return mImpl->renderQueue;
+}
+
+TextureCache& RenderManager::GetTextureCache()
+{
+  return mImpl->textureCache;
+}
+
+void RenderManager::ContextCreated()
+{
+  mImpl->context.GlContextCreated();
+  mImpl->programController.GlContextCreated();
+
+  // renderers, textures and gpu buffers cannot reinitialize themselves
+  // so they rely on someone reloading the data for them
+}
+
+void RenderManager::ContextDestroyed()
+{
+  // @todo Set an atomic value to prevent render manager rendering again until
+  // ContextCreated has been called.
+
+  mImpl->context.GlContextDestroyed();
+  mImpl->programController.GlContextDestroyed();
+
+  // inform texture cache
+  mImpl->textureCache.GlContextDestroyed(); // Clears gl texture ids
+
+  // inform renderers
+  RendererOwnerContainer::Iterator end = mImpl->rendererContainer.End();
+  RendererOwnerContainer::Iterator iter = mImpl->rendererContainer.Begin();
+  for( ; iter != end; ++iter )
+  {
+    GlResourceOwner* renderer = *iter;
+    renderer->GlContextDestroyed(); // Clear up vertex buffers
+  }
+}
+
+void RenderManager::DispatchPostProcessRequest(ResourcePostProcessRequest& request)
+{
+  mImpl->resourcePostProcessQueue[ mImpl->renderBufferIndex ].push_back( request );
+}
+
+void RenderManager::SetShaderSaver( ShaderSaver& upstream )
+{
+  mImpl->programController.SetShaderSaver( upstream );
+}
+
+RenderInstructionContainer& RenderManager::GetRenderInstructionContainer()
+{
+  return mImpl->instructions;
+}
+
+void RenderManager::SetBackgroundColor( const Vector4& color )
+{
+  mImpl->backgroundColor = color;
+}
+
+void RenderManager::SetFrameDeltaTime( float deltaTime )
+{
+  Dali::Mutex::ScopedLock lock( mMutex );
+  mImpl->frameTime = deltaTime;
+}
+
+void RenderManager::SetDefaultSurfaceRect(const Rect<int>& rect)
+{
+  mImpl->defaultSurfaceRect = rect;
+}
+
+void RenderManager::AddRenderer( Renderer* renderer )
+{
+  // Initialize the renderer as we are now in render thread
+  renderer->Initialize( mImpl->context, mImpl->textureCache );
+
+  mImpl->rendererContainer.PushBack( renderer );
+
+  if( !mImpl->renderersAdded )
+  {
+    mImpl->renderersAdded = true;
+  }
+}
+
+void RenderManager::RemoveRenderer( Renderer* renderer )
+{
+  DALI_ASSERT_DEBUG( NULL != renderer );
+
+  RendererOwnerContainer& renderers = mImpl->rendererContainer;
+
+  // Find the renderer
+  for ( RendererOwnerIter iter = renderers.Begin(); iter != renderers.End(); ++iter )
+  {
+    if ( *iter == renderer )
+    {
+      renderers.Erase( iter ); // Renderer found; now destroy it
+      break;
+    }
+  }
+}
+
+void RenderManager::AddGeometry( RenderGeometry* renderGeometry )
+{
+  mImpl->renderGeometryContainer.PushBack( renderGeometry );
+}
+
+void RenderManager::RemoveGeometry( RenderGeometry* renderGeometry )
+{
+  DALI_ASSERT_DEBUG( NULL != renderGeometry );
+
+  RenderGeometryOwnerContainer& geometries = mImpl->renderGeometryContainer;
+
+  // Find the renderer
+  for ( RenderGeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
+  {
+    if ( *iter == renderGeometry )
+    {
+      geometries.Erase( iter ); // Geometry found; now destroy it
+      break;
+    }
+  }
+}
+
+void RenderManager::AddPropertyBuffer( RenderGeometry* renderGeometry, PropertyBufferDataProvider* propertyBuffer, const GpuBuffer::Target& target, const GpuBuffer::Usage& usage )
+{
+  DALI_ASSERT_DEBUG( NULL != renderGeometry );
+
+  RenderGeometryOwnerContainer& geometries = mImpl->renderGeometryContainer;
+
+  // Find the renderer
+  for ( RenderGeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
+  {
+    if ( *iter == renderGeometry )
+    {
+      (*iter)->AddPropertyBuffer( propertyBuffer, target, usage );
+      break;
+    }
+  }
+}
+
+void RenderManager::RemovePropertyBuffer( RenderGeometry* renderGeometry, PropertyBufferDataProvider* propertyBuffer )
+{
+  DALI_ASSERT_DEBUG( NULL != renderGeometry );
+
+  RenderGeometryOwnerContainer& geometries = mImpl->renderGeometryContainer;
+
+  // Find the renderer
+  for ( RenderGeometryOwnerIter iter = geometries.Begin(); iter != geometries.End(); ++iter )
+  {
+    if ( *iter == renderGeometry )
+    {
+      (*iter)->RemovePropertyBuffer( propertyBuffer );
+      break;
+    }
+  }
+}
+
+
+void RenderManager::AddRenderTracker( RenderTracker* renderTracker )
+{
+  mImpl->AddRenderTracker(renderTracker);
+}
+
+void RenderManager::RemoveRenderTracker( RenderTracker* renderTracker )
+{
+  mImpl->RemoveRenderTracker(renderTracker);
+}
+
+void RenderManager::SetDefaultShader( Shader* shader )
+{
+  mImpl->defaultShader = shader;
+}
+
+ProgramCache* RenderManager::GetProgramCache()
+{
+  return &(mImpl->programController);
+}
+
+bool RenderManager::Render( Integration::RenderStatus& status )
+{
+  DALI_PRINT_RENDER_START( mImpl->renderBufferIndex );
+
+  // Core::Render documents that GL context must be current before calling Render
+  DALI_ASSERT_DEBUG( mImpl->context.IsGlContextCreated() );
+
+  status.SetHasRendered( false );
+
+  // Increment the frame count at the beginning of each frame
+  ++(mImpl->frameCount);
+  mImpl->context.SetFrameCount(mImpl->frameCount);
+  mImpl->context.ClearRendererCount();
+  mImpl->context.ClearCulledCount();
+
+  PERF_MONITOR_START(PerformanceMonitor::DRAW_NODES);
+
+  SET_SNAPSHOT_FRAME_LOG_LEVEL;
+
+  // Process messages queued during previous update
+  mImpl->renderQueue.ProcessMessages( mImpl->renderBufferIndex );
+
+  // No need to make any gl calls if we've done 1st glClear & don't have any renderers to render during startup.
+  if( !mImpl->firstRenderCompleted || mImpl->renderersAdded )
+  {
+    // switch rendering to adaptor provided (default) buffer
+    mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+    mImpl->context.Viewport( mImpl->defaultSurfaceRect.x,
+                             mImpl->defaultSurfaceRect.y,
+                             mImpl->defaultSurfaceRect.width,
+                             mImpl->defaultSurfaceRect.height );
+
+    mImpl->context.ClearColor( mImpl->backgroundColor.r,
+                               mImpl->backgroundColor.g,
+                               mImpl->backgroundColor.b,
+                               mImpl->backgroundColor.a );
+
+    mImpl->context.ClearStencil( 0 );
+
+    // Clear the entire color, depth and stencil buffers for the default framebuffer.
+    // It is important to clear all 3 buffers, for performance on deferred renderers like Mali
+    // e.g. previously when the depth & stencil buffers were NOT cleared, it caused the DDK to exceed a "vertex count limit",
+    // and then stall. That problem is only noticeable when rendering a large number of vertices per frame.
+    mImpl->context.SetScissorTest( false );
+    mImpl->context.ColorMask( true );
+    mImpl->context.DepthMask( true );
+    mImpl->context.StencilMask( 0xFF ); // 8 bit stencil mask, all 1's
+    mImpl->context.Clear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,  Context::FORCE_CLEAR );
+
+    // reset the program matrices for all programs once per frame
+    // this ensures we will set view and projection matrix once per program per camera
+    // @todo move programs out of context onto a program controller and let that handle this
+    mImpl->programController.ResetProgramMatrices();
+
+    // if we don't have default shader, no point doing the render calls
+    if( mImpl->defaultShader )
+    {
+      size_t count = mImpl->instructions.Count( mImpl->renderBufferIndex );
+      for ( size_t i = 0; i < count; ++i )
+      {
+        RenderInstruction& instruction = mImpl->instructions.At( mImpl->renderBufferIndex, i );
+
+        DoRender( instruction, *mImpl->defaultShader, mImpl->lastFrameTime );
+
+        const RenderListContainer::SizeType countRenderList = instruction.RenderListCount();
+        if ( countRenderList > 0 )
+        {
+          status.SetHasRendered( true );
+        }
+      }
+      GLenum attachments[] = { GL_DEPTH, GL_STENCIL };
+      mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
+
+      mImpl->UpdateTrackers();
+
+      mImpl->firstRenderCompleted = true;
+    }
+  }
+
+  PERF_MONITOR_END(PerformanceMonitor::DRAW_NODES);
+
+  SetLastFrameTime();
+
+  // check if anything has been posted to the update thread
+  bool updateRequired = !mImpl->resourcePostProcessQueue[ mImpl->renderBufferIndex ].empty();
+
+  //Notify RenderGeometries that rendering has finished
+  for ( RenderGeometryOwnerIter iter = mImpl->renderGeometryContainer.Begin(); iter != mImpl->renderGeometryContainer.End(); ++iter )
+  {
+    (*iter)->OnRenderFinished();
+  }
+
+  /**
+   * The rendering has finished; swap to the next buffer.
+   * Ideally the update has just finished using this buffer; otherwise the render thread
+   * should block until the update has finished.
+   */
+  mImpl->renderBufferIndex = (0 != mImpl->renderBufferIndex) ? 0 : 1;
+
+  DALI_PRINT_RENDER_END();
+
+  DALI_PRINT_RENDERER_COUNT(mImpl->frameCount, mImpl->context.GetRendererCount());
+  DALI_PRINT_CULL_COUNT(mImpl->frameCount, mImpl->context.GetCulledCount());
+
+  return updateRequired;
+}
+
+void RenderManager::SetLastFrameTime()
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  mImpl->lastFrameTime = mImpl->frameTime;
+}
+
+void RenderManager::DoRender( RenderInstruction& instruction, Shader& defaultShader, float elapsedTime )
+{
+  Rect<int> viewportRect;
+  Vector4   clearColor;
+
+  if ( instruction.mIsClearColorSet )
+  {
+    clearColor = instruction.mClearColor;
+  }
+  else
+  {
+    clearColor = Dali::RenderTask::DEFAULT_CLEAR_COLOR;
+  }
+
+  FrameBufferTexture* offscreen = NULL;
+
+  if ( instruction.mOffscreenTextureId != 0 )
+  {
+    offscreen = mImpl->textureCache.GetFramebuffer( instruction.mOffscreenTextureId );
+    DALI_ASSERT_DEBUG( NULL != offscreen );
+
+    if( NULL != offscreen &&
+        offscreen->Prepare() )
+    {
+      // Check whether a viewport is specified, otherwise the full surface size is used
+      if ( instruction.mIsViewportSet )
+      {
+        // For glViewport the lower-left corner is (0,0)
+        const int y = ( offscreen->GetHeight() - instruction.mViewport.height ) - instruction.mViewport.y;
+        viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
+      }
+      else
+      {
+        viewportRect.Set( 0, 0, offscreen->GetWidth(), offscreen->GetHeight() );
+      }
+    }
+    else
+    {
+      // Offscreen is NULL or could not be prepared.
+      return;
+    }
+  }
+  else // !(instruction.mOffscreenTexture)
+  {
+    // switch rendering to adaptor provided (default) buffer
+    mImpl->context.BindFramebuffer( GL_FRAMEBUFFER, 0 );
+
+    // Check whether a viewport is specified, otherwise the full surface size is used
+    if ( instruction.mIsViewportSet )
+    {
+      // For glViewport the lower-left corner is (0,0)
+      const int y = ( mImpl->defaultSurfaceRect.height - instruction.mViewport.height ) - instruction.mViewport.y;
+      viewportRect.Set( instruction.mViewport.x,  y, instruction.mViewport.width, instruction.mViewport.height );
+    }
+    else
+    {
+      viewportRect = mImpl->defaultSurfaceRect;
+    }
+  }
+
+  mImpl->context.Viewport(viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height);
+
+  if ( instruction.mIsClearColorSet )
+  {
+    mImpl->context.ClearColor( clearColor.r,
+                               clearColor.g,
+                               clearColor.b,
+                               clearColor.a );
+
+    // Clear the viewport area only
+    mImpl->context.SetScissorTest( true );
+    mImpl->context.Scissor( viewportRect.x, viewportRect.y, viewportRect.width, viewportRect.height );
+    mImpl->context.ColorMask( true );
+    mImpl->context.Clear( GL_COLOR_BUFFER_BIT , Context::CHECK_CACHED_VALUES );
+    mImpl->context.SetScissorTest( false );
+  }
+
+  Render::ProcessRenderInstruction( instruction,
+                                    mImpl->context,
+                                    mImpl->textureCache,
+                                    defaultShader,
+                                    mImpl->renderBufferIndex,
+                                    elapsedTime );
+
+  if(instruction.mOffscreenTextureId != 0)
+  {
+    GLenum attachments[] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
+    mImpl->context.InvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
+  }
+
+  if( instruction.mRenderTracker && offscreen != NULL )
+  {
+    instruction.mRenderTracker->CreateSyncObject();
+    instruction.mRenderTracker = NULL; // Only create once.
+  }
+}
+
+void RenderManager::SetPixmapYInverted( bool yInverted )
+{
+  mImpl->context.SetPixmapYInverted( yInverted );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/common/render-manager.h b/dali/internal/render/common/render-manager.h
new file mode 100644 (file)
index 0000000..9a6003e
--- /dev/null
@@ -0,0 +1,268 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_MANAGER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/mutex.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/internal/common/shader-saver.h>
+#include <dali/internal/render/common/post-process-resource-dispatcher.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GlAbstraction;
+class RenderStatus;
+}
+
+struct Vector4;
+
+namespace Internal
+{
+class Context;
+class ProgramCache;
+class ShaderSaver;
+
+namespace SceneGraph
+{
+class Renderer;
+class RenderQueue;
+class TextureCache;
+class RenderInstruction;
+class RenderInstructionContainer;
+class RenderTracker;
+class Shader;
+class RenderGeometry;
+class PropertyBufferDataProvider;
+
+/**
+ * RenderManager is responsible for rendering the result of the previous "update", which
+ * is provided in a RenderCommand during UpdateManager::Update().
+ */
+class RenderManager : public PostProcessResourceDispatcher
+{
+public:
+
+  /**
+   * Construct a new RenderManager.
+   * @param[in]  glAbstraction The GL abstraction used for rendering.
+   * @param[out] resourcePostProcessQueue A queue for sending rendered texture ids to the update-thread.
+   */
+  static RenderManager* New( Dali::Integration::GlAbstraction& glAbstraction, ResourcePostProcessList& resourcePostProcessQueue );
+
+  /**
+   * Non-virtual destructor; not intended as a base class
+   */
+  ~RenderManager();
+
+  /**
+   * Retrieve the RenderQueue. Messages should only be added to this from the update-thread.
+   * @return The render queue.
+   */
+  RenderQueue& GetRenderQueue();
+
+  /**
+   * Retrieve the texture cache. Messages should only be sent to this from the update thread,
+   * accessor methods should only be used from the render thread.
+   * @return The texture cache
+   */
+  TextureCache& GetTextureCache();
+
+  /**
+   * @copydoc Dali::Integration::Core::ContextCreated()
+   */
+  void ContextCreated();
+
+  /**
+   * @copydoc Dali::Integration::Core::ContextToBeDestroyed()
+   */
+  void ContextDestroyed();
+
+  /**
+   * Dispatch requests onto the postProcessResourcesQueue
+   * @param[in] request The request to dispatch
+   */
+  virtual void DispatchPostProcessRequest( ResourcePostProcessRequest& request );
+
+  /**
+   * Set the upstream interface for compiled shader binaries to be sent back to for eventual
+   * caching and saving.
+   * @param[in] upstream The abstract interface to send any received ShaderDatas onwards to..
+   * @note This should be called during core initialisation if shader binaries are to be used.
+   */
+  void SetShaderSaver( ShaderSaver& upstream );
+
+  /**
+   * Retrieve the render instructions; these should be set during each "update" traversal.
+   * @return The render instruction container.
+   */
+  RenderInstructionContainer& GetRenderInstructionContainer();
+
+  // The following methods should be called via RenderQueue messages
+
+  /**
+   * Set the background color i.e. the glClear color used at the beginning of each frame.
+   * @param[in] color The new background color.
+   */
+  void SetBackgroundColor( const Vector4& color );
+
+  /*
+   * Set the frame time delta (time elapsed since the last frame.
+   * @param[in] deltaTime the delta time
+   */
+  void SetFrameDeltaTime( float deltaTime );
+
+  /**
+   * Returns the rectangle for the default surface (probably the application window).
+   * @return Rectangle for the surface.
+   */
+  void SetDefaultSurfaceRect( const Rect<int>& rect );
+
+  /**
+   * Add a Renderer to the render manager.
+   * @param[in] renderer The renderer to add.
+   * @post renderer is owned by RenderManager
+   */
+  void AddRenderer( Renderer* renderer );
+
+  /**
+   * Remove a Renderer from the render manager.
+   * @param[in] renderer The renderer to remove.
+   * @post renderer is destroyed.
+   */
+  void RemoveRenderer( Renderer* renderer );
+
+  /**
+   * Add a geometry to the render manager.
+   * @param[in] geometry The geometry to add.
+   * @post geometry is owned by RenderManager
+   */
+  void AddGeometry( RenderGeometry* geometry );
+
+  /**
+   * Remove a geometry from the render manager.
+   * @param[in] geometry The geometry to remove.
+   * @post geometry is destroyed.
+   */
+  void RemoveGeometry( RenderGeometry* geometry );
+
+  /**
+   * Adds a property buffer to a RenderGeometry from the render manager.
+   * @param[in] geometry The geometry
+   * @param[in] propertyBuffer The property buffer to remove.
+   * @param[in] target Specifies the type of the buffer
+   * @param[in] usage Specifies how will the buffer be used
+   */
+  void AddPropertyBuffer( RenderGeometry* renderGeometry, PropertyBufferDataProvider* propertyBuffer, const GpuBuffer::Target& target, const GpuBuffer::Usage& usage );
+
+  /**
+   * Remove a property buffer from a RenderGeometry from the render manager.
+   * @param[in] geometry The geometry
+   * @param[in] propertyBuffer The property buffer to remove.
+   * @post property buffer is destroyed.
+   */
+  void RemovePropertyBuffer( RenderGeometry* renderGeometry, PropertyBufferDataProvider* propertyBuffer );
+
+  /**
+   * Adds a render tracker to the RenderManager. RenderManager takes ownership of the
+   * tracker. The lifetime of the tracker is related to the lifetime of the tracked
+   * object, usually an offscreen render task.
+   * @param[in] renderTracker The render tracker
+   */
+  void AddRenderTracker( RenderTracker* renderTracker );
+
+  /**
+   * Removes a render tracker from the RenderManager.
+   * @param[in] renderTracker The render tracker to remove.
+   */
+  void RemoveRenderTracker( RenderTracker* renderTracker );
+
+  /**
+   * Set the default shader that is to be used in absence of custom shader
+   * @param[in] shader that is the default one
+   */
+  void SetDefaultShader( Shader* shader );
+
+  /**
+   * returns the Program controller for sending program messages
+   * @return the ProgramController
+   */
+  ProgramCache* GetProgramCache();
+
+  // This method should be called from Core::Render()
+
+  /**
+   * Renders the results of the previous "update" traversal.
+   * @param[out] status contains the flag that indicates if render instructions exist
+   * @return true if a further update is required
+   */
+  bool Render( Integration::RenderStatus& status );
+
+  // Pixmap
+
+  /**
+   * @copydoc Dali::Integration::Core::SetPixmapYInverted()
+   */
+  void SetPixmapYInverted( bool yInverted );
+
+private:
+
+  /**
+   * Helper to process a single RenderInstruction.
+   * @param[in] instruction A description of the rendering operation.
+   * @param[in] defaultShader default shader to use.
+   * @param[in] elapsedTime from previous render.
+   */
+  void DoRender( RenderInstruction& instruction, Shader& defaultShader, float elapsedTime );
+
+private:
+
+  /**
+   * Construct a new RenderManager.
+   */
+  RenderManager();
+
+  // Undefined
+  RenderManager( const RenderManager& );
+
+  // Undefined
+  RenderManager& operator=( const RenderManager& rhs );
+
+  // Set the last frame time while locking access
+  void SetLastFrameTime();
+
+private:
+
+  struct Impl;
+  Impl* mImpl;
+  Dali::Mutex mMutex;
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_MANAGER_H__
diff --git a/dali/internal/render/common/render-tracker-debug.h b/dali/internal/render/common/render-tracker-debug.h
new file mode 100644 (file)
index 0000000..0c2229a
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_TRACKER_DEBUG_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_TRACKER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+#if defined(DEBUG_ENABLED)
+
+Debug::Filter* gRenderTrackerLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_TRACKER");
+
+#define TRACKER_LOG(level)                                              \
+  DALI_LOG_INFO(gRenderTrackerLogFilter, level, "RenderTracker::%s: this:%p\n", __FUNCTION__, this)
+
+#define TRACKER_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gRenderTrackerLogFilter, level, "RenderTracker::%s: this:%p " format, __FUNCTION__, this, ## args)
+#else
+#define TRACKER_LOG(level)
+#define TRACKER_LOG_FMT(level, format, args...)
+#endif
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_TRACKER_DEBUG_H__
diff --git a/dali/internal/render/common/render-tracker.cpp b/dali/internal/render/common/render-tracker.cpp
new file mode 100644 (file)
index 0000000..ef9723b
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/render-tracker.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/internal/render/common/render-tracker-debug.h>
+
+// EXTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+
+RenderTracker::RenderTracker(Integration::GlSyncAbstraction& glSyncAbstraction)
+: mGlSyncAbstraction(glSyncAbstraction),
+  mSyncTrigger(0),
+  mSyncObject(NULL)
+{
+  TRACKER_LOG(Debug::Verbose);
+}
+
+RenderTracker::~RenderTracker()
+{
+  TRACKER_LOG(Debug::Verbose);
+  if( mSyncObject )
+  {
+    mGlSyncAbstraction.DestroySyncObject( mSyncObject );
+    mSyncObject = NULL;
+  }
+}
+
+void RenderTracker::CreateSyncObject()
+{
+  TRACKER_LOG(Debug::General);
+
+  // Destroy any previous sync object
+  if( mSyncObject )
+  {
+     mGlSyncAbstraction.DestroySyncObject( mSyncObject );
+     mSyncObject = NULL;
+  }
+  ResetSyncFlag();
+  mSyncObject = mGlSyncAbstraction.CreateSyncObject( );
+}
+
+void RenderTracker::PollSyncObject()
+{
+  if( mSyncObject && mSyncObject->IsSynced() )
+  {
+    SetSyncFlag();
+    mGlSyncAbstraction.DestroySyncObject( mSyncObject );
+    mSyncObject = NULL;
+
+    TRACKER_LOG_FMT(Debug::General, " Synced\n");
+    return;
+  }
+  TRACKER_LOG_FMT(Debug::General, " Not Synced\n");
+}
+
+bool RenderTracker::IsSynced()
+{
+  int x = __sync_val_compare_and_swap(&mSyncTrigger, 0xFF, 0x0);
+
+  TRACKER_LOG_FMT(Debug::General, " = %s\n", x!=0?"T":"F");
+  return x != 0;
+}
+
+void RenderTracker::ResetSyncFlag()
+{
+  TRACKER_LOG(Debug::General);
+  (void)__sync_lock_test_and_set(&mSyncTrigger, 0x0);
+}
+
+void RenderTracker::SetSyncFlag()
+{
+  (void)__sync_lock_test_and_set(&mSyncTrigger, 0xFF);
+}
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/common/render-tracker.h b/dali/internal/render/common/render-tracker.h
new file mode 100644 (file)
index 0000000..2e2bbf6
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_TRACKER_H
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_TRACKER_H
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * This class is used to communicate with Fence Sync objects, keeping access solely in
+ * the RenderThread to avoid having mutual exclusion locks or messages back to the UpdateThread.
+ */
+class RenderTracker
+{
+public:
+  /**
+   * Constructor
+   * @param[in] glSyncAbstraction The GlSyncAbstraction
+   * @param[in] resourceId The resource ID of the framebuffer texture being tracked
+   */
+  RenderTracker(Integration::GlSyncAbstraction& glSyncAbstraction);
+
+  /**
+   * Destructor
+   * Delete any outstanding sync objects?
+   */
+  ~RenderTracker();
+
+  /**
+   * Creates a sync object for this tracker. Will delete any existing sync object.
+   */
+  void CreateSyncObject();
+
+  /**
+   * Check the GL Sync objects. This is called from Render Thread.
+   * If the GlSyncObject has been triggered, then atomically set the sync trigger
+   */
+  void PollSyncObject();
+
+  /**
+   * Check the sync trigger. This is called from Update Thread, so atomically reads the sync trigger
+   * It clears the sync trigger if it was set.
+   * @return true if the tracker has been synced
+   */
+  bool IsSynced();
+
+  /**
+   * Atomically reset the sync trigger. This may be called from any thread
+   */
+  void ResetSyncFlag();
+
+  /**
+   * Atomically sets the sync trigger. This may be called from any thread
+   */
+  void SetSyncFlag();
+
+private:
+  Integration::GlSyncAbstraction& mGlSyncAbstraction; // The sync abstraction
+  volatile int mSyncTrigger;             // Trigger that update thread can read & reset
+  Integration::GlSyncAbstraction::SyncObject* mSyncObject; // Associated sync object
+};
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+
+#endif // __DALI_INTERNAL_RENDER_TRACKER_H
diff --git a/dali/internal/render/common/rendering-types.h b/dali/internal/render/common/rendering-types.h
new file mode 100644 (file)
index 0000000..a5d85a6
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __DALI_INTERNAL_RENDERING_TYPES_H__
+#define __DALI_INTERNAL_RENDERING_TYPES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/*
+ * Paint style used for certain nodes
+ */
+struct PaintStyle
+{
+  /**
+   * Default constructor, initializes everything to zero
+   */
+  PaintStyle()
+  : mStyleMode( STYLE_1x1 ),
+    mFadeIn(false),
+    mFadeInTime(0),
+    mBorderX0( 0.0f ), mBorderY0( 0.0f ), mBorderX1( 0.0f ), mBorderY1( 0.0f ),
+    mClipX0( 0.0f ), mClipY0( 0.0f ), mClipX1( 0.0f ), mClipY1( 0.0f )
+  { }
+
+  enum StyleMode
+  {
+     STYLE_1x1,
+     STYLE_3x1,
+     STYLE_1x3,
+     STYLE_3x3,
+     STYLE_GRID,
+     STYLE_BORDER_1x1
+  };
+
+  StyleMode   mStyleMode;
+  bool        mFadeIn;                      ///< whether to fade the image in
+  unsigned int mFadeInTime;                 ///< how quickly to fade an image in, in milliseconds
+
+  float       mBorderX0;  // Border for 3x3 grid
+  float       mBorderY0;
+  float       mBorderX1;
+  float       mBorderY1;
+
+  float       mClipX0;  // clip region for centre rectangle
+  float       mClipY0;
+  float       mClipX1;
+  float       mClipY1;
+};
+
+} // namespace Dali
+
+} // namespace Internal
+
+#endif // __DALI_INTERNAL_RENDERING_TYPES_H__
diff --git a/dali/internal/render/common/texture-cache-dispatcher.cpp b/dali/internal/render/common/texture-cache-dispatcher.cpp
new file mode 100644 (file)
index 0000000..ade6d75
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/common/texture-cache-dispatcher.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/queue/render-queue.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+TextureCacheDispatcher::TextureCacheDispatcher( RenderQueue& renderQueue )
+: mRenderQueue(renderQueue),
+  mSceneGraphBuffers(NULL)
+{
+}
+
+TextureCacheDispatcher::~TextureCacheDispatcher()
+{
+}
+
+void TextureCacheDispatcher::SetBufferIndices( const SceneGraphBuffers* bufferIndices )
+{
+  mSceneGraphBuffers = bufferIndices;
+}
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/render/common/texture-cache-dispatcher.h b/dali/internal/render/common/texture-cache-dispatcher.h
new file mode 100644 (file)
index 0000000..6ef3c22
--- /dev/null
@@ -0,0 +1,183 @@
+#ifndef __DALI_INTERNAL_TEXTURE_CACHE_DISPATCHER_H__
+#define __DALI_INTERNAL_TEXTURE_CACHE_DISPATCHER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/integration-api/bitmap.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+typedef Integration::ResourceId ResourceId;
+
+namespace SceneGraph
+{
+
+class RenderQueue;
+
+class TextureCacheDispatcher
+{
+public:
+
+  /**
+   * Constructor
+   * @param[in] renderQueue The queue to which to send messages
+   */
+  TextureCacheDispatcher( RenderQueue& renderQueue );
+
+  /**
+   * Virtual destructor; TextureCacheDispatcher is a base class.
+   */
+  virtual ~TextureCacheDispatcher();
+
+  /**
+   * mRenderQueue needs the update buffer index when any of the dispatch methods are
+   * called. Should really store a functor to get this index, but existing functors
+   * use references. Could heap allocate the functor, but that seems overly wasteful.
+   * Instead, store a pointer to the SceneGraphBuffers object, and call the relevant
+   * function when required. (increases coupling, requires object lifetime management :/ )
+   *
+   * @param[in] bufferIndices Pointer to SceneGraphBuffers object that can query
+   * the current RenderQueue buffer index.
+   */
+  void SetBufferIndices( const SceneGraphBuffers* bufferIndices );
+
+  /**
+   * Dispatch a message to create an empty texture and add it to the texture cache.
+   * May be called from Update thread
+   * @param[in] id Resource Id of the texture
+   * @param[in] width Width of the texture
+   * @param[in] height Height of the texture
+   * @param[in] pixelFormat Pixel format of the texture
+   * @param[in] clearPixels True if the data should be cleared to 0 on creation
+   */
+  virtual void DispatchCreateTexture( ResourceId        id,
+                                      unsigned int      width,
+                                      unsigned int      height,
+                                      Pixel::Format     pixelFormat,
+                                      bool              clearPixels ) = 0;
+
+  /**
+   * Dispatch a message to add a texture for bitmap.
+   * May be called from Update thread
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] bitmap The bitmap
+   */
+  virtual void DispatchCreateTextureForBitmap( ResourceId id, Integration::Bitmap* bitmap ) = 0;
+
+  /**
+   * Dispatch a message to add a native image to the texture cache
+   * May be called from Update thread
+   * @param[in] id Resource Id of the native image
+   * @param[in] nativeImage The native image
+   */
+  virtual void DispatchCreateTextureForNativeImage( ResourceId id, NativeImageInterfacePtr nativeImage ) = 0;
+
+  /**
+   * Dispatch a message to create a framebuffer texture and add it to the texture cache
+   * May be called from Update thread
+   * @param[in] id Resource Id of the framebuffer
+   * @param[in] width Width of the framebuffer
+   * @param[in] height Height of the framebuffer
+   * @param[in] pixelFormat Pixel format of the framebuffer
+   */
+  virtual void DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat ) = 0;
+
+  /**
+   * Dispatch a message to create a framebuffer texture and add it to the texture cache
+   * May be called from Update thread
+   * @param[in] id Resource Id of the framebuffer
+   * @param[in] nativeImage The NativeImage
+   */
+  virtual void DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage ) = 0;
+
+  /**
+   * @brief Create GL texture for native image resource.
+   * @param[in] id The resource id.
+   */
+  virtual void DispatchCreateGlTexture( ResourceId id ) = 0;
+
+  /**
+   * Dispatch a message to update the texture.
+   * May be called from Update thread
+   * @param[in] id Resource Id of the texture
+   * @param[in] bitmap The updated bitmap
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap ) = 0;
+
+  /**
+   * Dispatch a message to update the part of a texture with the bitmap data.
+   * May be called from Update thread
+   * @param[in] destId The ID of the texture to update
+   * @param[in] bitmap The pointer pointing to the source bitmap data.
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+  /**
+   * Dispatch a message to update the part of a texture with a newly loaded bitmap
+   * May be called from Update thread
+   * @param[in] destId The ID of the texture to update
+   * @param[in] srcId The resource ID of the source bitmap
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset ) = 0;
+
+  /**
+   * Dispatch a message to update the texture area
+   * May be called from the Update thread
+   * @param[in] id Resource Id of the texture
+   * @param[in] area The area of the bitmap that has changed
+   */
+  virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area ) = 0;
+
+  /**
+   * Dispatch a message to discard a texture
+   * May be called from Update thread
+   * @param[in] id Resource Id of the texture
+   */
+  virtual void DispatchDiscardTexture( ResourceId id ) = 0;
+
+protected:
+
+  RenderQueue&             mRenderQueue;
+  const SceneGraphBuffers* mSceneGraphBuffers;
+};
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_CACHE_DISPATCHER_H__
diff --git a/dali/internal/render/common/uv-rect.h b/dali/internal/render/common/uv-rect.h
new file mode 100644 (file)
index 0000000..d3a619f
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef __DALI_INTERNAL_UV_RECT_H__
+#define __DALI_INTERNAL_UV_RECT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * UV co-ordinates for a rectangle
+ */
+struct UvRect
+  {
+    float     u0;         ///< u texture coordinate (x) -bottom left
+    float     v0;         ///< v texture coordinate (y) -bottom left
+    float     u2;         ///< u texture coordinate (x) -top right
+    float     v2;         ///< v texture coordinate (y) -top right
+
+    /**
+     * Constructor.
+     */
+    UvRect()
+    : u0(0.0f), v0(0.0f),
+      u2(1.0f), v2(1.0f)
+    {
+    }
+
+    /**
+     * Reset the UV coordinates to default values
+     */
+    void Reset()
+    {
+       u0 = 0.0f;
+       v0 = 0.0f;
+       u2 = 1.0f;
+       v2 = 1.0f;
+     }
+
+    /**
+     * Assignment operator
+     */
+    UvRect& operator= (const UvRect& rhs)
+    {
+      if (this != &rhs)
+      {
+        u0 = rhs.u0;
+        v0 = rhs.v0;
+        u2 = rhs.u2;
+        v2 = rhs.v2;
+      }
+      return *this;
+    }
+
+    /**
+     * Adjusts the uv coordinates, relative to the atlas uv coordinates.
+     * Use for displaying part of a bitmap, which is held in an atlas.
+     * For example:
+     * \code
+     *
+     * (0,0)
+     * |-----------------------------|
+     * | Atlas                       |
+     * |                             |
+     * |  /----------------------\   |
+     * |  |  Bitmap              |   |
+     * |  |                      |   |
+     * |  |  /---------\         |   |
+     * |  |  |         |         |   |
+     * |  |  | Area to |         |   |
+     * |  |  | display |         |   |
+     * |  |  \---------/         |   |
+     * |  \______________________/   |
+     * |                             |
+     * |_____________________________|
+     *                               (1,1)
+     *
+     * \endcode
+     */
+    void AdjustToAtlasUV(const UvRect &atlasUV)
+    {
+      // this = Area To Display
+      // atlasUV = UV coordinates of bitmap in the atlas.
+
+      // 1. calculate the bitmap uv width / height in the atlas
+      float parentWidth = atlasUV.u2 - atlasUV.u0;
+      float parentHeight =  atlasUV.v2 - atlasUV.v0;
+
+      // algorithm = bitmap.start + displayArea.position * bitmap.width or height
+
+      u0 = atlasUV.u0 + u0 * parentWidth;
+      v0 = atlasUV.v0 + v0 * parentHeight;
+      u2 = atlasUV.u0 + u2 * parentWidth;
+      v2 = atlasUV.v0 + v2 * parentHeight;
+
+    }
+
+  }; // struct UV
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_UV_H__
diff --git a/dali/internal/render/common/vertex.h b/dali/internal/render/common/vertex.h
new file mode 100644 (file)
index 0000000..c4c408a
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTERNAL_VERTEX_H__
+#define __DALI_INTERNAL_VERTEX_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+struct Vertex2D
+{
+  float mX;
+  float mY;
+  float mU;
+  float mV;
+};
+
+struct Vertex3D
+{
+  float mX;
+  float mY;
+  float mZ;
+  float mU;
+  float mV;
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_VERTEX_H__
diff --git a/dali/internal/render/data-providers/geometry-data-provider.h b/dali/internal/render/data-providers/geometry-data-provider.h
new file mode 100644 (file)
index 0000000..8b58b33
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_DATA_PROVIDER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_DATA_PROVIDER_H__
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/render/data-providers/property-buffer-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class PropertyBuffer;
+
+/**
+ * An interface to provide geometry properties to the render thread.
+ */
+class GeometryDataProvider
+{
+public:
+  typedef Dali::Geometry::GeometryType GeometryType;
+
+  /**
+   * Constructor. Nothing to do as a pure interface.
+   */
+  GeometryDataProvider() { }
+
+public: // GeometryDataProvider
+  /**
+   * Get the type of geometry to draw
+   */
+  virtual GeometryType GetGeometryType( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * @todo MESH_REWORK - Should only use this in Update Sorting algorithm
+   * Returns true if this geometry requires depth testing, e.g. if it is
+   * a set of vertices with differing z values.
+   */
+  virtual bool GetRequiresDepthTesting( BufferIndex bufferIndex ) const = 0;
+
+protected:
+
+  /**
+   * Virtual destructor, this is an interface, no deletion through this interface
+   */
+  virtual ~GeometryDataProvider() { }
+};
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_DATA_PROVIDER_H__
diff --git a/dali/internal/render/data-providers/material-data-provider.h b/dali/internal/render/data-providers/material-data-provider.h
new file mode 100644 (file)
index 0000000..2f40f90
--- /dev/null
@@ -0,0 +1,94 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_MATERIAL_DATA_PROVIDER_H
+#define DALI_INTERNAL_SCENE_GRAPH_MATERIAL_DATA_PROVIDER_H
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/actors/blending.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * Interface to provide data of the material to the renderer.
+ * This interface must not be used to pass object pointers.
+ */
+class MaterialDataProvider
+{
+public:
+  /**
+   * Construtor
+   */
+  MaterialDataProvider()
+  {
+  }
+
+  virtual const Vector4& GetBlendColor( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the RGB source factor
+   * @return the RGB source factor
+   */
+  virtual BlendingFactor::Type GetBlendSrcFactorRgb( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the Alpha source factor
+   * @return the Alpha source factor
+   */
+  virtual BlendingFactor::Type GetBlendSrcFactorAlpha( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the RGB destination factor
+   * @return the RGB destination factor
+   */
+  virtual BlendingFactor::Type GetBlendDestFactorRgb( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the Alpha destination factor
+   * @return the Alpha destination factor
+   */
+  virtual BlendingFactor::Type GetBlendDestFactorAlpha( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the RGB blending equation
+   * @return the RGB blending equation
+   */
+  virtual BlendingEquation::Type GetBlendEquationRgb( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the Alpha blending equation
+   * @return the Alpha blending equation
+   */
+  virtual BlendingEquation::Type GetBlendEquationAlpha( BufferIndex bufferIndex ) const = 0;
+
+protected:
+  /**
+   * Destructor. No deletion through this interface
+   */
+  virtual ~MaterialDataProvider()
+  {
+  }
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_MATERIAL_DATA_PROVIDER_H
diff --git a/dali/internal/render/data-providers/node-data-provider.h b/dali/internal/render/data-providers/node-data-provider.h
new file mode 100644 (file)
index 0000000..3a016b5
--- /dev/null
@@ -0,0 +1,72 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_DATA_PROVIDER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_DATA_PROVIDER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+struct Vector4;
+class Matrix;
+
+namespace Internal
+{
+namespace SceneGraph
+{
+
+/**
+ * An interface to provide data for a Renderer
+ */
+class NodeDataProvider
+{
+public:
+
+  /**
+   * Constructor. Nothing to do as a pure interface.
+   */
+  NodeDataProvider() { }
+
+  /**
+   * @param bufferId to use
+   * @return a reference to the model matrix
+   */
+  virtual const Matrix& GetModelMatrix( unsigned int bufferId ) = 0;
+
+  /**
+   * @param bufferId to use
+   * @return a reference to the color
+   */
+  virtual const Vector4& GetRenderColor( unsigned int bufferId ) = 0;
+
+  /**
+   * @param[in] bufferIndex The buffer index to use
+   * @return the actor size
+   */
+  virtual const Vector3& GetRenderSize( unsigned int bufferIndex ) = 0;
+
+protected:
+  /**
+   * Virtual destructor, this is an interface, no deletion through this interface
+   */
+  virtual ~NodeDataProvider() { }
+};
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_DATA_PROVIDER_H__
diff --git a/dali/internal/render/data-providers/property-buffer-data-provider.h b/dali/internal/render/data-providers/property-buffer-data-provider.h
new file mode 100644 (file)
index 0000000..61e1e30
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_DATA_PROVIDER_H
+#define DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_DATA_PROVIDER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+class PropertyBufferDataProvider
+{
+public:
+
+  /**
+   * Type for the data contained in the buffer
+   */
+  typedef Dali::Vector< char > BufferType;
+
+public:
+  /**
+   * Constructor
+   */
+  PropertyBufferDataProvider()
+  {
+  }
+
+  /**
+   * Get the number of attributes
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the number of attributes
+   */
+  virtual unsigned int GetAttributeCount( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the name of an attribute
+   * @param[in] bufferIndex Index to access double buffered values
+   * @param[in] index Index of the attribute
+   * @return the name of the attribute
+   */
+  virtual const std::string& GetAttributeName( BufferIndex bufferIndex, unsigned int index ) const = 0;
+
+  /**
+   * Get the byte size of an attribute
+   * @param[in] bufferIndex Index to access double buffered values
+   * @param[in] index Index of the attribute
+   * @return the byte size of the attribute
+   */
+  virtual size_t GetAttributeSize( BufferIndex bufferIndex, unsigned int index ) const = 0;
+
+  /**
+   * Get the type of an attribute
+   * @param[in] bufferIndex Index to access double buffered values
+   * @param[in] index Index of the attribute
+   * @return the type of the attribute
+   */
+  virtual Property::Type GetAttributeType( BufferIndex bufferIndex, unsigned int index ) const = 0;
+
+  /**
+   * Get the byte offset of an attribute
+   * @param[in] bufferIndex Index to access double buffered values
+   * @param[in] index Index of the attribute
+   * @return the byte offset of the attribute
+   */
+  virtual size_t GetAttributeOffset( BufferIndex bufferIndex, unsigned int index ) const = 0;
+
+  /**
+   * Get the property buffer data
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the property buffer's data array
+   */
+  virtual const BufferType& GetData( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the size of the property buffer in bytes
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the size in bytes
+   */
+  virtual size_t GetDataSize( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the size of an element of the buffer in bytes
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the element size in bytes
+   */
+  virtual size_t GetElementSize( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the number of elements
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the number of elements
+   */
+  virtual unsigned int GetElementCount( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get Id of the GPU buffer associated with this propertyBuffer
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return the Id
+   */
+  virtual unsigned int GetGpuBufferId( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Checks if data in the PropertyBuffer has changed repect previous frame
+   * @param[in] bufferIndex Index to access double buffered values
+   * @return true if data has changed, false otherwise
+   */
+  virtual bool HasDataChanged( BufferIndex bufferIndex ) const = 0;
+
+protected:
+  /**
+   * No deletion through this interface
+   */
+  virtual ~PropertyBufferDataProvider()
+  {
+  }
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_DATA_PROVIDER_H
diff --git a/dali/internal/render/data-providers/render-data-provider.cpp b/dali/internal/render/data-providers/render-data-provider.cpp
new file mode 100644 (file)
index 0000000..f78af39
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "render-data-provider.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+RenderDataProvider::RenderDataProvider()
+: mMaterialDataProvider( NULL ),
+  mUniformMapDataProvider( NULL ),
+  mShader( NULL )
+{
+}
+
+RenderDataProvider::~RenderDataProvider()
+{
+}
+
+void RenderDataProvider::SetMaterial( const MaterialDataProvider& materialDataProvider )
+{
+  mMaterialDataProvider = &materialDataProvider;
+}
+
+const MaterialDataProvider& RenderDataProvider::GetMaterial() const
+{
+  return *mMaterialDataProvider;
+}
+
+void RenderDataProvider::SetUniformMap(const UniformMapDataProvider& uniformMapDataProvider)
+{
+  mUniformMapDataProvider = &uniformMapDataProvider;
+}
+
+const UniformMapDataProvider& RenderDataProvider::GetUniformMap() const
+{
+  return *mUniformMapDataProvider;
+}
+
+void RenderDataProvider::SetShader( Shader& shader )
+{
+  mShader = &shader;
+}
+
+Shader& RenderDataProvider::GetShader() const
+{
+  return *mShader;
+}
+
+void RenderDataProvider::SetSamplers( const RenderDataProvider::Samplers& samplers )
+{
+  mSamplers = samplers;
+}
+
+const RenderDataProvider::Samplers& RenderDataProvider::GetSamplers() const
+{
+  return mSamplers;
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/data-providers/render-data-provider.h b/dali/internal/render/data-providers/render-data-provider.h
new file mode 100644 (file)
index 0000000..cf3aeb6
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_DATA_PROVIDER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_DATA_PROVIDER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/render/data-providers/geometry-data-provider.h>
+#include <dali/internal/render/data-providers/material-data-provider.h>
+#include <dali/internal/render/data-providers/node-data-provider.h>
+#include <dali/internal/render/data-providers/sampler-data-provider.h>
+#include <dali/internal/render/data-providers/property-buffer-data-provider.h>
+#include <dali/internal/render/data-providers/uniform-map-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class PropertyBuffer;
+class Shader;
+
+/**
+ * Wraps all the data providers for the renderer. This allows the
+ * individual providers to change connections in the update thread without affecting
+ * the current render. It essentially provides double buffering of the
+ * provider accessor through the message system. It does not take ownership
+ * of any objects.
+ *
+ * @todo - Add set of bools to state what changed (For improving performance)
+ */
+class RenderDataProvider
+{
+public:
+  typedef Dali::Vector< const PropertyBufferDataProvider* > VertexBuffers;
+  typedef Dali::Vector< const SamplerDataProvider* > Samplers;
+
+  /**
+   * Constructor.
+   * The RendererAttachment that creates this object will initialize the members
+   * directly.
+   */
+  RenderDataProvider();
+
+  /**
+   * Destructor
+   */
+  ~RenderDataProvider();
+
+public:
+
+  /**
+   * Set the material data provider
+   * @param[in] materialDataProvider The material data provider
+   */
+  void SetMaterial( const MaterialDataProvider& materialDataProvider );
+
+  /**
+   * Get the material data provider
+   * @return the material data provider
+   */
+  const MaterialDataProvider& GetMaterial() const;
+
+  /**
+   * Set the uniform map data provider
+   * @param[in] uniformMapDataProvider The uniform map data provider
+   */
+  void SetUniformMap(const UniformMapDataProvider& uniformMapDataProvider);
+
+  /**
+   * Get the uniform map data provider
+   */
+  const UniformMapDataProvider& GetUniformMap() const;
+
+  /**
+   * Set the shader data provider
+   * @param[in] shader The shader data provider
+   */
+  void SetShader( Shader& shader );
+
+  /**
+   * Returns the shader
+   * @return The shader
+   */
+  Shader& GetShader() const;
+
+  /**
+   * Set the sampler data providers
+   * @param[in] samplers The sampler data providers
+   */
+  void SetSamplers( const Samplers& samplers );
+
+  /**
+   * Returns the list of sampler data providers
+   * @return The list of samplers
+   */
+  const Samplers& GetSamplers() const;
+
+private:
+  const MaterialDataProvider*   mMaterialDataProvider;
+  const UniformMapDataProvider* mUniformMapDataProvider;
+  Shader*                       mShader;
+  Samplers                      mSamplers;
+
+// Give RendererAttachment access to our private data to reduce copying vectors on construction.
+  friend class RendererAttachment;
+};
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_DATA_PROVIDER_H__
diff --git a/dali/internal/render/data-providers/sampler-data-provider.h b/dali/internal/render/data-providers/sampler-data-provider.h
new file mode 100644 (file)
index 0000000..ba00955
--- /dev/null
@@ -0,0 +1,98 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_SAMPLER_DATA_PROVIDER_H
+#define DALI_INTERNAL_SCENE_GRAPH_SAMPLER_DATA_PROVIDER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+class SamplerDataProvider
+{
+public:
+  typedef Dali::Sampler::FilterMode FilterMode;
+  typedef Dali::Sampler::WrapMode   WrapMode;
+  typedef Dali::Integration::ResourceId ResourceId;
+
+  /**
+   * Constructor
+   */
+  SamplerDataProvider()
+  {
+  }
+
+  /**
+   * Get the sampler's texture unit uniform name
+   * @return The texture unit uniform name
+   */
+  virtual const std::string& GetTextureUnitUniformName() const = 0;
+
+  /**
+   * Get the texture identity associated with the sampler
+   * @return The texture identity
+   */
+  virtual ResourceId GetTextureId( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the filter mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The minify filter mode
+   */
+  virtual FilterMode GetMinifyFilterMode( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the filter mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The magnify filter mode
+   */
+  virtual FilterMode GetMagnifyFilterMode( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the horizontal wrap mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The horizontal wrap mode
+   */
+  virtual WrapMode GetUWrapMode( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the vertical wrap mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The vertical wrap mode
+   */
+  virtual WrapMode GetVWrapMode( BufferIndex bufferIndex ) const = 0;
+
+protected:
+  /**
+   * No deletion through this interface
+   */
+  virtual ~SamplerDataProvider()
+  {
+  }
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_SAMPLER_DATA_PROVIDER_H
diff --git a/dali/internal/render/data-providers/uniform-map-data-provider.h b/dali/internal/render/data-providers/uniform-map-data-provider.h
new file mode 100644 (file)
index 0000000..97bcd39
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_DATA_PROVIDER_H
+#define DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_DATA_PROVIDER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class UniformMap;
+class UniformPropertyMapping;
+
+typedef Dali::Vector< const UniformPropertyMapping* > CollectedUniformMap;
+
+/**
+ * This class maps uniform names to property value pointers.
+ */
+class UniformMapDataProvider
+{
+public:
+  /**
+   * Constructor
+   */
+  UniformMapDataProvider()
+  {
+  }
+
+  /**
+   * Return true if the uniform map has been changed this frame
+   * Note, this only informs if the uniform mappings have changed,
+   * not if any actual property value has changed.
+   *
+   * @param[in] bufferIndex The buffer index
+   * @return true if the uniform map has changed
+   */
+  virtual bool GetUniformMapChanged( BufferIndex bufferIndex ) const = 0;
+
+  /**
+   * Get the complete map of uniforms to property value addresses
+   * (The map is double buffered - it can be retrieved through this interface)
+   *
+   * @param[in] bufferIndex The bufferIndex
+   * @return the uniform map
+   */
+  virtual const CollectedUniformMap& GetUniformMap( BufferIndex bufferIndex ) const = 0;
+
+protected:
+  /**
+   * No deletion through this interface
+   */
+  virtual ~UniformMapDataProvider()
+  {
+  }
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_DATA_PROVIDER_H
diff --git a/dali/internal/render/gl-resources/bitmap-texture.cpp b/dali/internal/render/gl-resources/bitmap-texture.cpp
new file mode 100644 (file)
index 0000000..d325162
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/bitmap-texture.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+BitmapTexture::BitmapTexture(
+  Integration::Bitmap* const bitmap,
+  const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile,
+  Context& context,
+  ResourcePolicy::Discardable policy)
+: Texture( context,
+           bitmapPackedPixelsProfile->GetBufferWidth(),
+           bitmapPackedPixelsProfile->GetBufferHeight(),
+           bitmap->GetImageWidth(),
+           bitmap->GetImageHeight()),
+  mBitmap(bitmap),
+  mClearPixels(false),
+  mDiscardPolicy(policy),
+  mPixelFormat(bitmap->GetPixelFormat())
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
+}
+
+BitmapTexture::BitmapTexture(
+  unsigned int width,
+  unsigned int height,
+  Pixel::Format pixelFormat,
+  bool clearPixels,
+  Context& context,
+  ResourcePolicy::Discardable policy)
+: Texture( context,
+           width, height,
+           width, height),
+  mBitmap(NULL),
+  mClearPixels(clearPixels),
+  mDiscardPolicy(policy),
+  mPixelFormat( pixelFormat )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+}
+
+BitmapTexture::~BitmapTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+bool BitmapTexture::HasAlphaChannel() const
+{
+  return Pixel::HasAlpha(mPixelFormat);
+}
+
+bool BitmapTexture::IsFullyOpaque() const
+{
+  if( mBitmap )
+  {
+    return mBitmap->IsFullyOpaque();
+  }
+  else
+  {
+    return ! HasAlphaChannel(); // Todo: amalgamate updated bitmap's IsFullyOpaque()
+  }
+}
+
+// Bitmap buffer has been changed. Upload changes to GPU.
+void BitmapTexture::AreaUpdated( const RectArea& updateArea, const unsigned char* pixels )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::Verbose, "BitmapTexture::AreaUpdated()\n");
+
+  GLenum pixelFormat   = GL_RGBA;
+  GLenum pixelDataType = GL_UNSIGNED_BYTE;
+  Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
+
+  mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+
+  mContext.Bind2dTexture(mId);
+
+  if( ! updateArea.IsEmpty() )
+  {
+    mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
+    DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "Update x:%d y:%d w:%d h:%d\n",
+                   updateArea.x, updateArea.y, updateArea.width ,updateArea.height );
+
+    const unsigned int pitchPixels = mWidth;
+    const unsigned int pixelDepth = GetBytesPerPixel( mPixelFormat );
+
+    // If the width of the source update area is the same as the pitch, then can
+    // copy the contents in a single contiguous TexSubImage call.
+    if(updateArea.x == 0 && updateArea.width == pitchPixels)
+    {
+      pixels += updateArea.y * pitchPixels * pixelDepth;
+      mContext.TexSubImage2D( GL_TEXTURE_2D,0, updateArea.x, updateArea.y,
+                              updateArea.width, updateArea.height,
+                              pixelFormat, pixelDataType, pixels );
+    }
+    else
+    {
+      // Otherwise the source buffer needs to be copied line at a time, as OpenGL ES
+      // does not support source strides. (no GL_UNPACK_ROW_LENGTH supported)
+      unsigned int yBottom = updateArea.y + updateArea.height;
+      pixels += (updateArea.y * pitchPixels + updateArea.x) * pixelDepth;
+
+      for(unsigned int y = updateArea.y; y < yBottom; y++)
+      {
+        mContext.TexSubImage2D( GL_TEXTURE_2D,0, updateArea.x, y,
+                                updateArea.width, 1,
+                                pixelFormat, pixelDataType, pixels );
+        pixels += pitchPixels * pixelDepth;
+      }
+    }
+
+    INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED,
+                 updateArea.Area()* GetBytesPerPixel( mPixelFormat ));
+  }
+}
+
+void BitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* pixels )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::Verbose, "BitmapTexture::AssignBitmap()\n");
+
+  GLenum pixelFormat = GL_RGBA;
+  GLenum pixelDataType = GL_UNSIGNED_BYTE;
+
+  if( generateTexture )
+  {
+    mContext.GenTextures(1, &mId);
+  }
+  DALI_ASSERT_DEBUG( mId != 0 );
+
+  mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+  mContext.Bind2dTexture(mId);
+  Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
+
+  mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
+  mContext.TexImage2D(GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, pixels);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  if( pixels != NULL )
+  {
+    INCREASE_BY( PerformanceMonitor::TEXTURE_DATA_UPLOADED, GetBytesPerPixel(mPixelFormat) * mWidth * mHeight );
+  }
+}
+
+void BitmapTexture::Update( Integration::Bitmap* bitmap )
+{
+  DALI_LOG_INFO( Debug::Filter::gGLResource, Debug::General, "BitmapTexture::Update(bitmap:%p )\n", bitmap );
+  DALI_ASSERT_DEBUG( bitmap != 0 );
+  if( !bitmap )
+  {
+    DALI_LOG_ERROR( "Passed a null bitmap to update this bitmap texture." );
+    return;
+  }
+
+  // Only Packed-pixel bitmaps are ever associated with BitmapTextures, so we should never be passed any other kind:
+  const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixels = bitmap->GetPackedPixelsProfile();
+  DALI_ASSERT_DEBUG(bitmapPackedPixels);
+  if( !bitmapPackedPixels )
+  {
+    ///! This should never happen.
+    DALI_LOG_ERROR("Passed an incompatible bitmap type to update this bitmap texture.");
+    return;
+  }
+  mBitmap = bitmap;
+
+  const unsigned char* pixels = mBitmap->GetBuffer();
+
+  // We should never have null pixel data here - resource manager has deliberately loaded/reloaded data
+
+  DALI_ASSERT_DEBUG( pixels != NULL );
+
+  if( NULL == pixels )
+  {
+    DALI_LOG_ERROR("BitmapTexture::Upload() - Bitmap has no pixel data.\n");
+  }
+  else if( mId != 0 )
+  {
+    if( mImageWidth == mBitmap->GetImageWidth() &&
+        mImageHeight == mBitmap->GetImageHeight() &&
+        mWidth  == bitmapPackedPixels->GetBufferWidth() &&
+        mHeight == bitmapPackedPixels->GetBufferHeight() &&
+        mPixelFormat == mBitmap->GetPixelFormat() ) // and size hasn't changed
+    {
+      RectArea area(0, 0, mImageWidth, mImageHeight);  // just update whole texture
+      AreaUpdated( area, pixels );
+      DiscardBitmapBuffer();
+    }
+    else // Otherwise, reload the pixel data
+    {
+      mImageWidth  = mBitmap->GetImageWidth();
+      mImageHeight = mBitmap->GetImageHeight();
+      mWidth       = bitmapPackedPixels->GetBufferWidth();
+      mHeight      = bitmapPackedPixels->GetBufferHeight();
+      mPixelFormat = mBitmap->GetPixelFormat();
+
+      AssignBitmap( false, pixels );
+    }
+  }
+}
+
+void BitmapTexture::Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  if( NULL != srcBitmap )
+  {
+    GLenum pixelFormat   = GL_RGBA;
+    GLenum pixelDataType = GL_UNSIGNED_BYTE;
+    Integration::ConvertToGlFormat( mPixelFormat, pixelDataType, pixelFormat );
+
+    if( !mId )
+    {
+      mContext.GenTextures( 1, &mId );
+
+      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+      mContext.Bind2dTexture( mId );
+      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+
+      mContext.TexImage2D( GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL );
+      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+      mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+    }
+    else
+    {
+      mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+      mContext.Bind2dTexture( mId );
+      mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 );
+    }
+
+    mContext.TexSubImage2D( GL_TEXTURE_2D, 0,
+                            xOffset, yOffset,
+                            srcBitmap->GetImageWidth(), srcBitmap->GetImageHeight(),
+                            pixelFormat, pixelDataType, srcBitmap->GetBuffer() );
+  }
+}
+
+void BitmapTexture::UpdateArea( const RectArea& updateArea )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "BitmapTexture::UpdateArea()\n");
+
+  if( mBitmap != 0 )
+  {
+    const unsigned char* pixels = mBitmap->GetBuffer();
+
+    // Pixel data could be null if we've uploaded to GL and discarded the data.
+
+    if( NULL != pixels )
+    {
+      if( mId ) // If the texture is already bound
+      {
+        if( updateArea.IsEmpty() )
+        {
+          RectArea area;
+          area.x = 0;
+          area.y = 0;
+          area.width = mImageWidth;
+          area.height = mImageHeight;
+          AreaUpdated( area, pixels );
+        }
+        else
+        {
+          AreaUpdated( updateArea, pixels );
+        }
+      }
+    }
+  }
+}
+
+bool BitmapTexture::UpdateOnCreate()
+{
+  return true;
+}
+
+bool BitmapTexture::CreateGlTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "BitmapTexture::CreateGlTexture() Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
+
+  if( mBitmap )
+  {
+    const unsigned char* pixels = mBitmap->GetBuffer();
+
+    // pixel data could be NULL here if we've had a context loss and we previously discarded
+    // the pixel data on the previous upload. If it is null, then we shouldn't generate a
+    // new GL Texture; leaving mId as zero. Eventually, the bitmap will get reloaded,
+    // and pixels will become non-null.
+
+    if( NULL != pixels )
+    {
+      AssignBitmap( true, pixels );
+      DiscardBitmapBuffer();
+    }
+  }
+  else
+  {
+    const unsigned char* pixels = NULL;
+    Dali::Vector<unsigned char> pixelData; // Okay to create outside branch as empty vector has no heap allocation.
+    if( true == mClearPixels )
+    {
+      unsigned int size = mWidth * mHeight * Pixel::GetBytesPerPixel( mPixelFormat );
+      pixelData.Resize( size, 0 );
+      pixels = &pixelData[0];
+    }
+    AssignBitmap( true, pixels );
+  }
+
+  return mId != 0;
+}
+
+bool BitmapTexture::Init()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  // mBitmap should be initialized by now
+  return (mBitmap != 0);
+}
+
+unsigned int BitmapTexture::GetWidth() const
+{
+  unsigned int width = mWidth;
+  if( mBitmap )
+  {
+    width = mBitmap->GetImageWidth();
+  }
+  return width;
+}
+
+unsigned int BitmapTexture::GetHeight() const
+{
+  unsigned int height = mHeight;
+  if( mBitmap )
+  {
+    height = mBitmap->GetImageHeight();
+  }
+  return height;
+}
+
+void BitmapTexture::DiscardBitmapBuffer()
+{
+  DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "BitmapTexture::DiscardBitmapBuffer() DiscardPolicy: %s\n", mDiscardPolicy == ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN");
+
+  if( ResourcePolicy::OWNED_DISCARD == mDiscardPolicy )
+  {
+    DALI_LOG_INFO(Debug::Filter::gImage, Debug::General, "  Discarding bitmap\n");
+    mBitmap->DiscardBuffer();
+  }
+}
+
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/bitmap-texture.h b/dali/internal/render/gl-resources/bitmap-texture.h
new file mode 100644 (file)
index 0000000..c0ef35a
--- /dev/null
@@ -0,0 +1,180 @@
+#ifndef __DALI_INTERNAL_BITMAP_TEXTURE_H__
+#define __DALI_INTERNAL_BITMAP_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h> // for uint32_t
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class BitmapTexture;
+typedef IntrusivePtr<BitmapTexture> BitmapTexturePointer;
+
+/**
+ *
+ * Texture class.
+ * If you want to load a file to a BitmapTexture use
+ * TextureManager::GetTexture()
+ *
+ */
+class BitmapTexture : public Texture
+{
+public:
+  /**
+   * Constructor
+   * Creates a new texture object from a Bitmap
+   * @param[in] bitmap The Bitmap
+   * @param[in] bitmapPackedPixelsProfile The Bitmap features related to an addressable array of raw pixel data
+   * @param     context The GL context
+   */
+  BitmapTexture(Integration::Bitmap* const bitmap, const Integration::Bitmap::PackedPixelsProfile * const bitmapPackedPixelsProfile, Context& context, ResourcePolicy::Discardable discardPolicy);
+
+  /**
+   * Constructor
+   * Creates a new texture object
+   * @param[in] width width in pixels
+   * @param[in] height height in pixels
+   * @param[in] pixelFormat pixel format
+   * @param[in] clearPixels True if the pixel data should be cleared before gl texture creation
+   * @param[in] context Dali context
+   */
+  BitmapTexture( unsigned int width, unsigned int height, Pixel::Format pixelFormat,
+                 bool clearPixels, Context& context, ResourcePolicy::Discardable discardPolicy );
+
+  /**
+   * Destructor.
+   */
+  virtual ~BitmapTexture();
+
+  /**
+   * Retrieve the bitmap
+   * @return The bitmap or NULL if already discarded
+   */
+  Integration::Bitmap* GetBitmap() { return mBitmap.Get(); }
+
+public:
+
+  /**
+   * @copydoc Texture::Init
+   */
+  virtual bool Init();
+
+  /**
+   * @copydoc Texture::GetWidth
+   */
+  virtual unsigned int GetWidth() const;
+
+  /**
+   * @copydoc Texture::GetHeight
+   */
+  virtual unsigned int GetHeight() const;
+
+  /**
+   * @copydoc Texture::HasAlphaChannel
+   */
+  virtual bool HasAlphaChannel() const;
+
+  /**
+   * @copydoc Texture::IsFullyOpaque
+   */
+  virtual bool IsFullyOpaque() const;
+
+  /**
+   * Replace current bitmap with a fresh one, for instance after a Bitmap has
+   * been reloaded.
+   * @param[in] bitmap The new bitmap
+   */
+  virtual void Update( Integration::Bitmap* bitmap );
+
+  /**
+   * Update part of the texture with a different bitmap
+   * @param[in] srcBitmap The bitmap to copy from
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Bitmap area has been modified - update the texture appropriately.
+   * @pre The bitmap hasn't been discarded (should be external type)
+   * @param[in] area The updated area
+   */
+  virtual void UpdateArea( const RectArea& area );
+
+  /**
+   * @return Return true if the texture should be updated on GL texture creation.
+   */
+  virtual bool UpdateOnCreate();
+
+protected:
+  /**
+   * @copydoc Texture::CreateGlTexture
+   */
+  virtual bool CreateGlTexture();
+
+private:
+
+  /**
+   * Uploads changes to GPU after Bitmap buffer has changed.
+   * @param [in] updateArea area which changed
+   * @param[in] pixels The pixel data
+   */
+  void AreaUpdated( const RectArea& updateArea, const unsigned char* pixels );
+
+  /**
+   * Assigns the bitmap data to an OpenGL texture
+   * Creates a new texture object and copies
+   * the image data held in the pixels parameter
+   * @pre The texture has to have a width/height that is a power of 2.
+   * @param[in] generateTexture True if we should generate a GL texture id
+   * @param[in] pixels The pixel data
+   */
+  void AssignBitmap( bool generateTexture, const unsigned char* pixels );
+
+  /**
+   * If the discard policy is not RETAIN, then discards the bitmap's pixel buffer
+   */
+  void DiscardBitmapBuffer();
+
+private:
+  Integration::BitmapPtr mBitmap;      ///< The Bitmap the Texture was created from (may be NULL)
+  bool                   mClearPixels; ///< true if initial texture should be cleared on creation
+  ResourcePolicy::Discardable mDiscardPolicy; ///< The bitmap discard policy
+  Pixel::Format            mPixelFormat;
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+}  //namespace Internal
+
+} //namespace Dali
+
+#endif //__DALI_INTERNAL_BITMAP_TEXTURE_H__
diff --git a/dali/internal/render/gl-resources/compressed-bitmap-texture.cpp b/dali/internal/render/gl-resources/compressed-bitmap-texture.cpp
new file mode 100644 (file)
index 0000000..1830d43
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/compressed-bitmap-texture.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CompressedBitmapTexture::CompressedBitmapTexture(Internal::BitmapCompressed* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy)
+: Texture(context,
+          bitmap->GetImageWidth(),
+          bitmap->GetImageHeight(),
+          bitmap->GetImageWidth(),
+          bitmap->GetImageHeight()),
+  mBitmap(bitmap),
+  mDiscardPolicy(discardPolicy),
+  mPixelFormat( bitmap->GetPixelFormat() )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_SET_OBJECT_STRING(this, DALI_LOG_GET_OBJECT_STRING(bitmap));
+}
+
+CompressedBitmapTexture::~CompressedBitmapTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+bool CompressedBitmapTexture::HasAlphaChannel() const
+{
+  return Pixel::HasAlpha(mPixelFormat);
+}
+
+bool CompressedBitmapTexture::IsFullyOpaque() const
+{
+  if( mBitmap )
+  {
+    return mBitmap->IsFullyOpaque();
+  }
+  else
+  {
+    return ! HasAlphaChannel(); // Todo: amalgamate updated bitmap's IsFullyOpaque()
+  }
+}
+
+
+void CompressedBitmapTexture::AssignBitmap( bool generateTexture, const unsigned char* const pixels, const size_t bufferSize )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::Verbose, "CompressedBitmapTexture::AssignBitmap()\n");
+
+  if( generateTexture )
+  {
+    mContext.GenTextures(1, &mId);
+  }
+  DALI_ASSERT_DEBUG( mId != 0 );
+
+  mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );
+  mContext.Bind2dTexture(mId);
+
+  GLenum pixelFormat = GL_RGBA;
+  GLenum pixelDataType = GL_UNSIGNED_BYTE;
+  Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
+
+  mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
+  mContext.CompressedTexImage2D(GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, bufferSize, pixels);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+}
+
+void CompressedBitmapTexture::Update( Integration::Bitmap* bitmap )
+{
+  DALI_ASSERT_DEBUG(bitmap);
+  DALI_ASSERT_DEBUG(mImageWidth == mWidth && mImageHeight == mHeight);
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "CompressedBitmapTexture::Update(bitmap:%p )\n", bitmap);
+
+  if( !bitmap )
+  {
+    DALI_LOG_ERROR( "Passed a null bitmap to update this compressed bitmap texture." );
+    return;
+  }
+
+  Internal::BitmapCompressed * const compressedBitmap = dynamic_cast<Dali::Internal::BitmapCompressed*>( bitmap );
+  if( compressedBitmap == 0 )
+  {
+    DALI_LOG_ERROR("CompressedBitmapTexture was passed a non-compressed bitmap to update with.\n");
+    return;
+  }
+  mBitmap = compressedBitmap;
+
+  const unsigned char * const pixels = mBitmap->GetBuffer();
+
+  DALI_ASSERT_DEBUG(pixels != NULL);
+
+  if ( NULL == pixels )
+  {
+    DALI_LOG_ERROR("Bitmap has no data\n");
+  }
+  else
+  {
+    mImageWidth  = mBitmap->GetImageWidth();
+    mImageHeight = mBitmap->GetImageHeight();
+    mWidth       = mImageWidth;
+    mHeight      = mImageHeight;
+    mPixelFormat = mBitmap->GetPixelFormat();
+
+    if ( mId ) // If the texture is already bound
+    {
+      AssignBitmap( false, pixels, mBitmap->GetBufferSize() );
+
+      if( mDiscardPolicy == ResourcePolicy::OWNED_DISCARD )
+      {
+        mBitmap->DiscardBuffer();
+      }
+    }
+  }
+}
+
+bool CompressedBitmapTexture::UpdateOnCreate()
+{
+  return true;
+}
+
+bool CompressedBitmapTexture::CreateGlTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  DALI_LOG_INFO(Debug::Filter::gImage, Debug::Verbose, "Bitmap: %s\n", DALI_LOG_GET_OBJECT_C_STR(this));
+
+  if( mBitmap )
+  {
+    const unsigned char* pixels = mBitmap->GetBuffer();
+
+    DALI_ASSERT_DEBUG(pixels != NULL);
+
+    if( NULL != pixels )
+    {
+      AssignBitmap( true, pixels, mBitmap->GetBufferSize() );
+      mBitmap->DiscardBuffer();
+    }
+  }
+  else
+  {
+    AssignBitmap( true, NULL, 0 );
+  }
+
+  return mId != 0;
+}
+
+bool CompressedBitmapTexture::Init()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  // mBitmap should be initialized by now
+  return (mBitmap != 0);
+}
+
+unsigned int CompressedBitmapTexture::GetWidth() const
+{
+  unsigned int width = mWidth;
+  if( mBitmap )
+  {
+    width = mBitmap->GetImageWidth();
+  }
+  return width;
+}
+
+unsigned int CompressedBitmapTexture::GetHeight() const
+{
+  unsigned int height = mHeight;
+  if( mBitmap )
+  {
+    height = mBitmap->GetImageHeight();
+  }
+  return height;
+}
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/compressed-bitmap-texture.h b/dali/internal/render/gl-resources/compressed-bitmap-texture.h
new file mode 100644 (file)
index 0000000..47f4009
--- /dev/null
@@ -0,0 +1,134 @@
+#ifndef __DALI_INTERNAL_COMPRESSED_BITMAP_TEXTURE_H__
+#define __DALI_INTERNAL_COMPRESSED_BITMAP_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/internal/event/images/bitmap-compressed.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class CompressedBitmapTexture;
+typedef IntrusivePtr<CompressedBitmapTexture> CompressedBitmapTexturePointer;
+
+/**
+ * Compressed Texture class.
+ * If you want to load a file to a CompressedBitmapTexture use
+ * TextureManager::GetTexture()
+ * Compressed textures differ from ordinary ones in that their in-memory
+ * representation cannot be inspected at a pixel level by simple pointer
+ * arithmetic and in that they cannot be partially updated.
+ */
+class CompressedBitmapTexture : public Texture
+{
+public:
+  /**
+   * Constructor
+   * Creates a new texture object from a Bitmap
+   * @param[in] bitmap The Bitmap
+   * @param[in] context The GL context
+   * @param[in] discardPolicy The discard policy
+   */
+  CompressedBitmapTexture( Internal::BitmapCompressed* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy );
+
+  /**
+   * Destructor.
+   */
+  virtual ~CompressedBitmapTexture();
+
+public:
+  /**
+   * @copydoc Texture::Init
+   */
+  virtual bool Init();
+
+  /**
+   * @copydoc Texture::GetWidth
+   */
+  virtual unsigned int GetWidth() const;
+
+  /**
+   * @copydoc Texture::GetHeight
+   */
+  virtual unsigned int GetHeight() const;
+
+  /**
+   * @copydoc Texture::HasAlphaChannel
+   */
+  virtual bool HasAlphaChannel() const;
+
+  /**
+   * @copydoc Texture::IsFullyOpaque
+   * Always returns false as we can't know what is going on inside the encoded pixel data. ///!Todo: Revise this decision: Paul, didn't you want the opposite assumption?
+   */
+  virtual bool IsFullyOpaque() const;
+
+  /**
+   * Bitmap has been reloaded - update the texture appropriately.
+   * @param[in] bitmap The new bitmap
+   */
+  virtual void Update( Integration::Bitmap* bitmap );
+
+  /**
+   * @return Return true if the texture should be updated on GL texture creation.
+   */
+  virtual bool UpdateOnCreate();
+
+protected:
+  /**
+   * @copydoc Texture::CreateGlTexture
+   */
+  virtual bool CreateGlTexture();
+
+private:
+
+  /**
+   * Assigns the bitmap data to an OpenGL texture
+   * Creates a new texture object and copies
+   * the image data held in the pixels parameter
+   * @param[in] generateTexture True if we should generate a GL texture id
+   * @param[in] pixels The pixel data
+   */
+  void AssignBitmap( bool generateTexture, const unsigned char* pixels, const size_t bufferSize );
+
+private:
+  Internal::BitmapCompressedPtr mBitmap;      ///< The Bitmap the Texture was created from (may be NULL)
+  ResourcePolicy::Discardable mDiscardPolicy;
+  Pixel::Format  mPixelFormat;
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+} //namespace Internal
+} //namespace Dali
+
+#endif //__DALI_INTERNAL_COMPRESSED_BITMAP_TEXTURE_H__
diff --git a/dali/internal/render/gl-resources/context.cpp b/dali/internal/render/gl-resources/context.cpp
new file mode 100644 (file)
index 0000000..f97b0a4
--- /dev/null
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/context.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/compile-time-assert.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+DALI_COMPILE_TIME_ASSERT( TEXTURE_UNIT_LAST <= Context::MAX_TEXTURE_UNITS );
+
+/**
+ * GL error strings
+ */
+struct errorStrings
+{
+  const GLenum errorCode;
+  const char* errorString;
+};
+errorStrings errors[] =
+{
+   { GL_NO_ERROR,           "GL_NO_ERROR" },
+   { GL_INVALID_ENUM,       "GL_INVALID_ENUM" },
+   { GL_INVALID_VALUE,      "GL_INVALID_VALUE" },
+   { GL_INVALID_OPERATION,  "GL_INVALID_OPERATION" },
+   { GL_OUT_OF_MEMORY,      "GL_OUT_OF_MEMORY" }
+};
+
+} // unnamed namespace
+
+#ifdef DEBUG_ENABLED
+Debug::Filter* gContextLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT_STATE");
+#endif
+
+Context::Context(Integration::GlAbstraction& glAbstraction)
+: mGlAbstraction(glAbstraction),
+  mGlContextCreated(false),
+  mColorMask(true),
+  mStencilMask(0xFF),
+  mBlendEnabled(false),
+  mDepthBufferEnabled(false),
+  mDepthMaskEnabled(false),
+  mDitherEnabled(true), // This the only GL capability which defaults to true
+  mPolygonOffsetFillEnabled(false),
+  mSampleAlphaToCoverageEnabled(false),
+  mSampleCoverageEnabled(false),
+  mScissorTestEnabled(false),
+  mStencilBufferEnabled(false),
+  mClearColorSet(false),
+  mUsingDefaultBlendColor(true),
+  mBoundArrayBufferId(0),
+  mBoundElementArrayBufferId(0),
+  mBoundTransformFeedbackBufferId(0),
+  mActiveTextureUnit( TEXTURE_UNIT_LAST ),
+  mBlendColor(Color::TRANSPARENT),
+  mBlendFuncSeparateSrcRGB(GL_ONE),
+  mBlendFuncSeparateDstRGB(GL_ZERO),
+  mBlendFuncSeparateSrcAlpha(GL_ONE),
+  mBlendFuncSeparateDstAlpha(GL_ZERO),
+  mBlendEquationSeparateModeRGB( GL_FUNC_ADD ),
+  mBlendEquationSeparateModeAlpha( GL_FUNC_ADD ),
+  mMaxTextureSize(0),
+  mClearColor(Color::WHITE),    // initial color, never used until it's been set by the user
+  mCullFaceMode(CullNone),
+  mViewPort( 0, 0, 0, 0 ),
+  mFrameCount( 0 ),
+  mCulledCount( 0 ),
+  mRendererCount( 0 ),
+  mIsPixmapYInverted( true )
+{
+}
+
+Context::~Context()
+{
+}
+
+void Context::GlContextCreated()
+{
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextCreated()\n");
+
+  DALI_ASSERT_DEBUG(!mGlContextCreated);
+
+  mGlContextCreated = true;
+
+  // Set the initial GL state, and check it.
+  ResetGlState();
+
+#ifdef DEBUG_ENABLED
+  PrintCurrentState();
+#endif
+}
+
+void Context::GlContextDestroyed()
+{
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::GlContextDestroyed()\n");
+  mGlContextCreated = false;
+}
+
+const char* Context::ErrorToString( GLenum errorCode )
+{
+  for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
+  {
+    if (errorCode == errors[i].errorCode)
+    {
+      return errors[i].errorString;
+    }
+  }
+  return "Unknown Open GLES error";
+}
+
+const Rect< int >& Context::GetViewport()
+{
+  return mViewPort;
+}
+
+void Context::FlushVertexAttributeLocations()
+{
+  for( unsigned int i = 0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
+  {
+    // see if our cached state is different to the actual state
+    if (mVertexAttributeCurrentState[ i ] != mVertexAttributeCachedState[ i ] )
+    {
+      // it's different so make the change to the driver
+      // and update the cached state
+      mVertexAttributeCurrentState[ i ] = mVertexAttributeCachedState[ i ];
+
+      if (mVertexAttributeCurrentState[ i ] )
+      {
+        LOG_GL("EnableVertexAttribArray %d\n", i);
+        CHECK_GL( mGlAbstraction, mGlAbstraction.EnableVertexAttribArray( i ) );
+      }
+      else
+      {
+        LOG_GL("DisableVertexAttribArray %d\n", i);
+        CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( i ) );
+      }
+    }
+  }
+
+}
+
+void Context::SetVertexAttributeLocation(unsigned int location, bool state)
+{
+
+  if( location >= MAX_ATTRIBUTE_CACHE_SIZE )
+  {
+    // not cached, make the gl call through context
+    if ( state )
+    {
+       LOG_GL("EnableVertexAttribArray %d\n", location);
+       CHECK_GL( mGlAbstraction, mGlAbstraction.EnableVertexAttribArray( location ) );
+    }
+    else
+    {
+      LOG_GL("DisableVertexAttribArray %d\n", location);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( location ) );
+    }
+  }
+  else
+  {
+    // set the cached state, it will be set at the next draw call
+    // if it's different from the current driver state
+    mVertexAttributeCachedState[ location ] = state;
+  }
+}
+
+void Context::ResetVertexAttributeState()
+{
+  // reset attribute cache
+  for( unsigned int i=0; i < MAX_ATTRIBUTE_CACHE_SIZE; ++i )
+  {
+    mVertexAttributeCachedState[ i ] = false;
+    mVertexAttributeCurrentState[ i ] = false;
+
+    LOG_GL("DisableVertexAttribArray %d\n", i);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DisableVertexAttribArray( i ) );
+  }
+}
+
+void Context::ResetGlState()
+{
+  DALI_LOG_INFO(gContextLogFilter, Debug::Verbose, "Context::ResetGlState()\n");
+  DALI_ASSERT_DEBUG(mGlContextCreated);
+
+  mClearColorSet = false;
+  // Render manager will call clear in next render
+
+  // Reset internal state and Synchronize it with real OpenGL context.
+  // This may seem like overkill, but the GL context is not owned by dali-core,
+  // and no assumptions should be made about the initial state.
+  mColorMask = true;
+  mGlAbstraction.ColorMask( true, true, true, true );
+
+  mStencilMask = 0xFF;
+  mGlAbstraction.StencilMask( 0xFF );
+
+  mBlendEnabled = false;
+  mGlAbstraction.Disable(GL_BLEND);
+
+  mDepthBufferEnabled = false;
+  mGlAbstraction.Disable(GL_DEPTH_TEST);
+
+  mDepthMaskEnabled = false;
+  mGlAbstraction.DepthMask(GL_FALSE);
+
+  mDitherEnabled = false; // This the only GL capability which defaults to true
+  mGlAbstraction.Disable(GL_DITHER);
+
+  mPolygonOffsetFillEnabled = false;
+  mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL);
+
+  mSampleAlphaToCoverageEnabled = false;
+  mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+
+  mSampleCoverageEnabled = false;
+  mGlAbstraction.Disable(GL_SAMPLE_COVERAGE);
+
+  mScissorTestEnabled = false;
+  mGlAbstraction.Disable(GL_SCISSOR_TEST);
+
+  mStencilBufferEnabled = false;
+  mGlAbstraction.Disable(GL_STENCIL_TEST);
+
+  mBoundArrayBufferId = 0;
+  LOG_GL("BindBuffer GL_ARRAY_BUFFER 0\n");
+  mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, mBoundArrayBufferId);
+
+  mBoundElementArrayBufferId = 0;
+  LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER 0\n");
+  mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, mBoundElementArrayBufferId);
+
+#ifndef EMSCRIPTEN // not in WebGL
+  mBoundTransformFeedbackBufferId = 0;
+  LOG_GL("BindBuffer GL_TRANSFORM_FEEDBACK_BUFFER 0\n");
+  mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, mBoundTransformFeedbackBufferId);
+#endif
+
+  mActiveTextureUnit = TEXTURE_UNIT_LAST;
+
+  mUsingDefaultBlendColor = true;
+  mGlAbstraction.BlendColor( 0.0f, 0.0f, 0.0f, 0.0f );
+
+  mBlendFuncSeparateSrcRGB = GL_ONE;
+  mBlendFuncSeparateDstRGB = GL_ZERO;
+  mBlendFuncSeparateSrcAlpha = GL_ONE;
+  mBlendFuncSeparateDstAlpha = GL_ZERO;
+  mGlAbstraction.BlendFuncSeparate( mBlendFuncSeparateSrcRGB, mBlendFuncSeparateDstRGB,
+                                    mBlendFuncSeparateSrcAlpha, mBlendFuncSeparateDstAlpha );
+
+  // initial state is GL_FUNC_ADD for both RGB and Alpha blend modes
+  mBlendEquationSeparateModeRGB = GL_FUNC_ADD;
+  mBlendEquationSeparateModeAlpha = GL_FUNC_ADD;
+  mGlAbstraction.BlendEquationSeparate( mBlendEquationSeparateModeRGB, mBlendEquationSeparateModeAlpha);
+
+  mCullFaceMode = CullNone;
+  mGlAbstraction.Disable(GL_CULL_FACE);
+  mGlAbstraction.FrontFace(GL_CCW);
+  mGlAbstraction.CullFace(GL_BACK);
+
+  // rebind texture units to 0
+  for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
+  {
+    mBound2dTextureId[ i ] = 0;
+    // set active texture
+    mGlAbstraction.ActiveTexture( GL_TEXTURE0 + i );
+    mGlAbstraction.BindTexture(GL_TEXTURE_2D, mBound2dTextureId[ i ] );
+  }
+
+  // get maximum texture size
+  mGlAbstraction.GetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
+
+  // reset viewport, this will be set to something useful when rendering
+  mViewPort.x = mViewPort.y = mViewPort.width = mViewPort.height = 0;
+
+  ResetVertexAttributeState();
+
+  mFrameBufferStateCache.Reset();
+}
+
+#ifdef DEBUG_ENABLED
+
+void Context::PrintCurrentState()
+{
+  const char* cullFaceModes[] = { "CullNone", "CullFront", "CullBack", "CullFrontAndBack" };
+  DALI_LOG_INFO( gContextLogFilter, Debug::General,
+                "\n----------------- Context State BEGIN -----------------\n"
+                "Blend = %s\n"
+                "Cull Face = %s\n"
+                "Depth Test = %s\n"
+                "Depth Mask = %s\n"
+                "Dither = %s\n"
+                "Polygon Offset Fill = %s\n"
+                "Sample Alpha To Coverage = %s\n"
+                "Sample Coverage = %s\n"
+                "Scissor Test = %s\n"
+                "Stencil Test = %s\n"
+                "----------------- Context State END -----------------\n",
+                mBlendEnabled ? "Enabled" : "Disabled",
+                cullFaceModes[ mCullFaceMode ],
+                mDepthBufferEnabled ? "Enabled" : "Disabled",
+                mDepthMaskEnabled ? "Enabled" : "Disabled",
+                mDitherEnabled ? "Enabled" : "Disabled",
+                mPolygonOffsetFillEnabled ? "Enabled" : "Disabled",
+                mSampleAlphaToCoverageEnabled ? "Enabled" : "Disabled",
+                mSampleCoverageEnabled ? "Enabled" : "Disabled",
+                mScissorTestEnabled ? "Enabled" : "Disabled",
+                mStencilBufferEnabled ? "Enabled" : "Disabled");
+}
+
+#endif // DALI_CONTEXT_LOGGING
+
+void Context::SetPixmapYInverted( bool yInverted )
+{
+  mIsPixmapYInverted = yInverted;
+}
+
+bool Context::IsPixmapYInverted() const
+{
+  return mIsPixmapYInverted;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/gl-resources/context.h b/dali/internal/render/gl-resources/context.h
new file mode 100644 (file)
index 0000000..ad7de94
--- /dev/null
@@ -0,0 +1,1829 @@
+#ifndef __DALI_INTERNAL_CONTEXT_H__
+#define __DALI_INTERNAL_CONTEXT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/devel-api/rendering/cull-face.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/internal/render/gl-resources/frame-buffer-state-cache.h>
+#include <dali/internal/render/gl-resources/gl-call-debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Context records the current GL state, and provides access to the OpenGL ES 2.0 API.
+ * Context avoids duplicate GL calls, if the same setting etc. is requested repeatedly.
+ */
+class Context
+{
+public:
+
+  /**
+   * FrameBuffer Clear mode
+   */
+  enum ClearMode
+  {
+    FORCE_CLEAR,        ///< always perform the glClear regardless of current state
+    CHECK_CACHED_VALUES ///< check the Frame buffers cached state to see if a clear is required
+  };
+
+  /**
+   * Size of the VertexAttributeArray enables
+   * GLES specification states that there's minimum of 8
+   */
+  static const unsigned int MAX_ATTRIBUTE_CACHE_SIZE = 8;
+
+  static const unsigned int MAX_TEXTURE_UNITS = 8; // for GLES 2.0 8 is guaranteed, which is more than DALi uses anyways
+
+  /**
+   * Creates the Dali Context object.
+   * This method does not create an OpenGL context i.e. that is done from outside dali-core.
+   * @pre Context has not been created.
+   * @exception Context already created.
+   * @param glAbstraction the gl abstraction.
+   */
+  Context( Integration::GlAbstraction& glAbstraction );
+
+  /**
+   * Destructor
+   */
+  ~Context();
+
+  /**
+   * Called when the GL context has been created.
+   */
+  void GlContextCreated();
+
+  /**
+   * Called when the GL context has been destroyed.
+   */
+  void GlContextDestroyed();
+
+  /**
+   * Query whether the OpenGL context has been created.
+   * @return True if the OpenGL context has been created.
+   */
+  bool IsGlContextCreated() { return mGlContextCreated; }
+
+  /**
+   * @return the GLAbstraction
+   */
+  Integration::GlAbstraction& GetAbstraction() { return mGlAbstraction; }
+
+#ifdef DEBUG_ENABLED
+
+  /**
+   * Debug helper which prints the currently cached GL state.
+   */
+  void PrintCurrentState();
+
+#endif
+
+  /**
+   * Helper to convert GL error code to string
+   * @param errorCode to convert
+   * @return C string
+   */
+  const char* ErrorToString( GLenum errorCode );
+
+  /**
+   * Helper to print GL string to debug log
+   */
+  void PrintGlString(const char* stringName, GLenum stringId)
+  {
+    DALI_LOG_INFO(Debug::Filter::gRender, Debug::General, "GL %s = %s\n", stringName, (const char *)GetString( stringId ) );
+  }
+
+  /****************************************************************************************
+   * The following methods are forwarded to Dali::Integration::GlAbstraction.
+   * In some cases the GL state is recorded, to avoid duplicate calls with the same state.
+   * All Shader, Program, Uniform and Attribute related calls are not here, Program class
+   * handles them and optimizes any program related state changes
+   ****************************************************************************************/
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glActiveTexture()
+   */
+  void ActiveTexture( TextureUnit textureUnit )
+  {
+    if ( textureUnit != mActiveTextureUnit )
+    {
+      mActiveTextureUnit = textureUnit;
+      LOG_GL("ActiveTexture %x\n", textureUnit);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ActiveTexture(TextureUnitAsGLenum(textureUnit)) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBeginQuery()
+   */
+  void BeginQuery(GLenum target, GLuint id)
+  {
+    LOG_GL("BeginQuery %d %d\n", target, id);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BeginQuery(target, id) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBeginTransformFeedback()
+   */
+  void BeginTransformFeedback(GLenum primitiveMode)
+  {
+    LOG_GL("BeginTransformFeedback %x\n", primitiveMode);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BeginTransformFeedback(primitiveMode) );
+  }
+
+  /**
+   * The wrapper for OpenGL ES 2.0 glBindBuffer() has been replaced by BindArrayBuffer & BindElementArrayBuffer & BindTransformFeedbackBuffer.
+   */
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBindBuffer(GL_ARRAY_BUFFER, ...)
+   */
+  void BindArrayBuffer(GLuint buffer)
+  {
+    // Avoid unecessary calls to BindBuffer
+    if (mBoundArrayBufferId != buffer)
+    {
+      mBoundArrayBufferId = buffer;
+
+      LOG_GL("BindBuffer GL_ARRAY_BUFFER %d\n", buffer);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_ARRAY_BUFFER, buffer) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ...)
+   */
+  void BindElementArrayBuffer(GLuint buffer)
+  {
+    // Avoid unecessary calls to BindBuffer
+    if (mBoundElementArrayBufferId!= buffer)
+    {
+      mBoundElementArrayBufferId = buffer;
+
+      LOG_GL("BindBuffer GL_ELEMENT_ARRAY_BUFFER %d\n", buffer);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, ...)
+   */
+  void BindTransformFeedbackBuffer(GLuint buffer)
+  {
+    // Avoid unecessary calls to BindBuffer
+    if (mBoundTransformFeedbackBufferId != buffer)
+    {
+      mBoundTransformFeedbackBufferId = buffer;
+
+      LOG_GL("BindBuffer GL_TRANSFORM_FEEDBACK_BUFFER %d\n", buffer);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER , buffer) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, ...)
+   */
+  void BindTransformFeedbackBufferBase(GLuint index, GLuint buffer)
+  {
+    // Avoid unecessary calls to BindBufferBase
+    if (mBoundTransformFeedbackBufferId != buffer)
+    {
+      mBoundTransformFeedbackBufferId = buffer;
+
+      LOG_GL("BindBufferBase GL_TRANSFORM_FEEDBACK_BUFFER %d %d\n", index, buffer);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index, buffer) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBindFramebuffer()
+   */
+  void BindFramebuffer(GLenum target, GLuint framebuffer)
+  {
+    mFrameBufferStateCache.SetCurrentFrameBuffer( framebuffer );
+
+    LOG_GL("BindFramebuffer %d %d\n", target, framebuffer);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindFramebuffer(target, framebuffer) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBindRenderbuffer()
+   */
+  void BindRenderbuffer(GLenum target, GLuint renderbuffer)
+  {
+    LOG_GL("BindRenderbuffer %d %d\n", target, renderbuffer);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindRenderbuffer(target, renderbuffer) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBindTransformFeedback()
+   */
+  void BindTransformFeedback(GLenum target, GLuint id)
+  {
+    LOG_GL("BindTransformFeedback %d %d\n", target, id);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BindTransformFeedback(target, id) );
+  }
+
+  /**
+   * Helper to bind texture for rendering. If given texture is
+   * already bound in the given textureunit, this method does nothing.
+   * Otherwise changes the active texture unit and binds the texture.
+   * Note! after this call active texture unit may not necessarily be the one
+   * passed in as argument so you cannot change texture unit state!!
+   * @param textureunit to bind to
+   * @param texture to bind
+   */
+  void BindTextureForUnit( TextureUnit textureunit, GLuint texture )
+  {
+    if( mBound2dTextureId[ textureunit ] != texture )
+    {
+      ActiveTexture( textureunit );
+      Bind2dTexture( texture );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBindTexture(GL_TEXTURE_2D)
+   */
+  void Bind2dTexture( GLuint texture )
+  {
+    if (mBound2dTextureId[ mActiveTextureUnit ] != texture)
+    {
+      mBound2dTextureId[ mActiveTextureUnit ] = texture;
+
+      LOG_GL("BindTexture GL_TEXTURE_2D %d\n", texture);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BindTexture(GL_TEXTURE_2D, texture) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendColor()
+   */
+  void SetDefaultBlendColor()
+  {
+    if( ! mUsingDefaultBlendColor )
+    {
+      SetCustomBlendColor( Color::TRANSPARENT );
+      mUsingDefaultBlendColor = true;
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendColor()
+   */
+  void SetCustomBlendColor( const Vector4& color )
+  {
+    if( mUsingDefaultBlendColor || mBlendColor != color )
+    {
+      LOG_GL( "BlendColor %f %f %f %f\n", color.r, color.g, color.b, color.a );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendColor( color.r, color.g, color.b, color.a ) );
+      mUsingDefaultBlendColor = false;
+      mBlendColor = color;
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendEquation()
+   */
+  void BlendEquation(GLenum mode)
+  {
+    // use BlendEquationSeparate to set the rgb and alpha modes the same
+    BlendEquationSeparate( mode, mode );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendEquationSeparate()
+   */
+  void BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+  {
+    if( ( modeRGB != mBlendEquationSeparateModeRGB ) ||
+        ( modeAlpha != mBlendEquationSeparateModeAlpha ) )
+    {
+      mBlendEquationSeparateModeRGB = modeRGB;
+      mBlendEquationSeparateModeAlpha = modeAlpha;
+      LOG_GL("BlendEquationSeparate %d %d\n", modeRGB, modeAlpha);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendEquationSeparate(modeRGB, modeAlpha) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendFunc()
+   */
+  void BlendFunc(GLenum sfactor, GLenum dfactor)
+  {
+    // reuse the BlendFuncSeparate as thats what the DDK does anyways
+    BlendFuncSeparate( sfactor, dfactor, sfactor, dfactor );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBlendFuncSeparate()
+   */
+  void BlendFuncSeparate( GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha )
+  {
+    if( ( mBlendFuncSeparateSrcRGB != srcRGB )||( mBlendFuncSeparateDstRGB != dstRGB )||
+        ( mBlendFuncSeparateSrcAlpha != srcAlpha )||( mBlendFuncSeparateDstAlpha != dstAlpha ) )
+    {
+      mBlendFuncSeparateSrcRGB = srcRGB;
+      mBlendFuncSeparateDstRGB = dstRGB;
+      mBlendFuncSeparateSrcAlpha = srcAlpha;
+      mBlendFuncSeparateDstAlpha = dstAlpha;
+
+      LOG_GL( "BlendFuncSeparate %d %d %d %d\n", srcRGB, dstRGB, srcAlpha, dstAlpha );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.BlendFuncSeparate( srcRGB, dstRGB, srcAlpha, dstAlpha ) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glBlitFramebuffer()
+   */
+  void BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+  {
+    LOG_GL( "BlitFramebuffer %d %d %d %d %d %d %d %d %x %d\n", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BlitFramebuffer( srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter ) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBufferData()
+   */
+  void BufferData(GLenum target, GLsizeiptr size, const void* data, GLenum usage)
+  {
+    LOG_GL("BufferData %d %d %p %d\n", target, size, data, usage);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BufferData(target, size, data, usage) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glBufferSubData()
+   */
+  void BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void* data)
+  {
+    LOG_GL("BufferSubData %d %d %d %p\n", target, offset, size, data);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.BufferSubData(target, offset, size, data) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0  glCheckFramebufferStatus()
+   */
+  GLenum CheckFramebufferStatus(GLenum target)
+  {
+    LOG_GL("CheckFramebufferStatus %d\n", target);
+    GLenum value = CHECK_GL( mGlAbstraction, mGlAbstraction.CheckFramebufferStatus(target) );
+    return value;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glClear()
+   */
+  void Clear(GLbitfield mask, ClearMode mode )
+  {
+    bool forceClear = (mode == FORCE_CLEAR );
+    mask = mFrameBufferStateCache.GetClearMask( mask, forceClear , mScissorTestEnabled );
+
+    if( mask > 0 )
+    {
+      LOG_GL("Clear %d\n", mask);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Clear( mask ) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glClearColor()
+   */
+  void ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+  {
+    Vector4 newCol(red,green,blue,alpha);
+
+    if (!mClearColorSet || mClearColor !=newCol )
+    {
+      LOG_GL("ClearColor %f %f %f %f\n", red, green, blue, alpha);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ClearColor(red, green, blue, alpha) );
+
+      mClearColorSet = true;
+      mClearColor = newCol;
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glClearDepthf()
+   */
+  void ClearDepthf(GLclampf depth)
+  {
+    LOG_GL("ClearDepthf %f\n", depth);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ClearDepthf(depth) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glClearStencil()
+   */
+  void ClearStencil(GLint s)
+  {
+    LOG_GL("ClearStencil %d\n", s);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ClearStencil(s) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glColorMask()
+   * @note This has been optimized to a single boolean value (masking individual channels is not required)
+   */
+  void ColorMask( bool flag )
+  {
+    // only change state if needed
+    if( flag != mColorMask )
+    {
+      mColorMask = flag;
+      LOG_GL("ColorMask %s %s %s %s\n", flag ? "True" : "False", flag ? "True" : "False", flag ? "True" : "False", flag ? "True" : "False");
+      CHECK_GL( mGlAbstraction, mGlAbstraction.ColorMask(flag, flag, flag, flag) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glCompressedTexImage2D()
+   */
+  void CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+                            GLint border, GLsizei imageSize, const void* data)
+  {
+    LOG_GL("CompressedTexImage2D %d %d %x %d %d %d %d %p\n", target, level, internalformat, width, height, border, imageSize, data);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glCompressedTexImage3D()
+   */
+  void CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
+                            GLint border, GLsizei imageSize, const void* data)
+  {
+    LOG_GL("CompressedTexImage3D %d %d %x %d %d %d %d %d %p\n", target, level, internalformat, width, height, depth, border, imageSize, data);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glCompressedTexSubImage2D()
+   */
+  void CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                               GLenum format, GLsizei imageSize, const void* data)
+  {
+    LOG_GL("CompressedTexSubImage2D %x %d %d %d %d %d %x %d %p\n", target, level, xoffset, yoffset, width, height, format, imageSize, data);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glCompressedTexSubImage3D()
+   */
+  void CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                               GLsizei width, GLsizei height, GLsizei depth,
+                               GLenum format, GLsizei imageSize, const void* data)
+  {
+    LOG_GL("CompressedTexSubImage3D %x %d %d %d %d %d %d %d %x %d %p\n", target, level, xoffset, yoffset, xoffset, width, height, depth, format, imageSize, data);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glCopyTexImage2D()
+   */
+  void CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+  {
+    LOG_GL("CopyTexImage2D %x %d %x %d %d %d %d %d\n", target, level, internalformat, x, y, width, height, border);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexImage2D(target, level, internalformat, x, y, width, height, border) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glCopyTexSubImage2D()
+   */
+  void CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+    LOG_GL("CopyTexSubImage2D %x %d %d %d %d %d %d %d\n", target, level, xoffset, yoffset, x, y, width, height);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glCopyTexSubImage3D()
+   */
+  void CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+    LOG_GL("CopyTexSubImage3D %x %d %d %d %d %d %d %d %d\n", target, level, xoffset, yoffset, zoffset, x, y, width, height);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glCullFace()
+   * enables GL_CULL_FACE if in any of the face culling modes
+   * otherwise disables GL_CULL_FACE
+   */
+  void CullFace(CullFaceMode mode)
+  {
+    // Avoid unnecessary calls to gl
+    if(mCullFaceMode != mode)
+    {
+      mCullFaceMode = mode;
+      switch(mode)
+      {
+        case CullNone:
+        {
+          LOG_GL("Disable GL_CULL_FACE\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_CULL_FACE) );
+          break;
+        }
+
+        case CullFront:
+        {
+          LOG_GL("Enable GL_CULL_FACE\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
+          LOG_GL("Enable GL_FRONT\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_FRONT) );
+          break;
+        }
+
+        case CullBack:
+        {
+          LOG_GL("Enable GL_CULL_FACE\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
+          LOG_GL("Enable GL_BACK\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_BACK) );
+          break;
+        }
+
+        case CullFrontAndBack:
+        {
+          LOG_GL("Enable GL_CULL_FACE\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_CULL_FACE) );
+          LOG_GL("Enable GL_FRONT_AND_BACK\n");
+          CHECK_GL( mGlAbstraction, mGlAbstraction.CullFace(GL_FRONT_AND_BACK) );
+          break;
+        }
+
+        default:
+          break;
+      }
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDeleteBuffers()
+   */
+  void DeleteBuffers(GLsizei n, const GLuint* buffers)
+  {
+    // @todo: this is to prevent mesh destructor from doing GL calls when DALi core is being deleted
+    // can be taken out once render manages either knows about meshes or gpubuffers and can tell them directly that context is lost
+    if( this->IsGlContextCreated() )
+    {
+      LOG_GL("DeleteBuffers %d %p\n", n, buffers);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteBuffers(n, buffers) );
+    }
+    // reset the cached buffer id's
+    // fixes problem where some drivers will a generate a buffer with the
+    // same id, as the last deleted buffer id.
+    mBoundArrayBufferId = 0;
+    mBoundElementArrayBufferId = 0;
+    mBoundTransformFeedbackBufferId = 0;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDeleteFramebuffers()
+   */
+  void DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+  {
+    mFrameBufferStateCache.FrameBuffersDeleted( n, framebuffers );
+
+    LOG_GL("DeleteFramebuffers %d %p\n", n, framebuffers);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteFramebuffers(n, framebuffers) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDeleteQueries()
+   */
+  void DeleteQueries(GLsizei n, GLuint* ids)
+  {
+    LOG_GL("DeleteQueries %d %p\n", n, ids);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteQueries(n, ids) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDeleteRenderbuffers()
+   */
+  void DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+  {
+    LOG_GL("DeleteRenderbuffers %d %p\n", n, renderbuffers);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteRenderbuffers(n, renderbuffers) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDeleteTextures()
+   */
+  void DeleteTextures(GLsizei n, const GLuint* textures)
+  {
+    LOG_GL("DeleteTextures %d %p\n", n, textures);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteTextures(n, textures) );
+
+    // reset the cached texture id's incase the driver re-uses them
+    // when creating new textures
+    for( unsigned int i=0; i < MAX_TEXTURE_UNITS; ++i )
+    {
+       mBound2dTextureId[ i ] = 0;
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDeleteTransformFeedbacks()
+   */
+  void DeleteTransformFeedbacks(GLsizei n, GLuint* ids)
+  {
+    LOG_GL("DeleteTransformFeedbacks %d %p\n", n, ids);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteTransformFeedbacks(n, ids) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDepthFunc()
+   */
+  void DepthFunc(GLenum func)
+  {
+    LOG_GL("DepthFunc %x\n", func);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DepthFunc(func) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDepthMask()
+   */
+  void DepthMask(GLboolean flag)
+  {
+    // only change state if needed
+    if( flag != mDepthMaskEnabled )
+    {
+      mDepthMaskEnabled = flag;
+      LOG_GL("DepthMask %s\n", flag ? "True" : "False");
+      CHECK_GL( mGlAbstraction, mGlAbstraction.DepthMask( mDepthMaskEnabled ) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDepthRangef()
+   */
+  void DepthRangef(GLclampf zNear, GLclampf zFar)
+  {
+    LOG_GL("DepthRangef %f %f\n", zNear, zFar);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DepthRangef(zNear, zFar) );
+  }
+
+  /**
+   * The wrapper for OpenGL ES 2.0 glDisable() has been replaced by SetBlend, SetCullFace, SetDepthTest,
+   * SetDither, SetPolygonOffsetFill, SetSampleAlphaToCoverage, SetSampleCoverage, SetScissorTest & SetStencilTest.
+   */
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDrawArrays()
+   */
+  void DrawArrays(GLenum mode, GLint first, GLsizei count)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+    FlushVertexAttributeLocations();
+
+    LOG_GL("DrawArrays %x %d %d\n", mode, first, count);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawArrays(mode, first, count) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDrawArraysInstanced()
+   */
+  void DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+    FlushVertexAttributeLocations();
+
+    LOG_GL("DrawArraysInstanced %x %d %d %d\n", mode, first, count, instanceCount);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawArraysInstanced(mode, first, count,instanceCount) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDrawBuffers()
+   */
+  void DrawBuffers(GLsizei n, const GLenum* bufs)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+    LOG_GL("DrawBuffers %d %p\n", n, bufs);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawBuffers(n, bufs) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glDrawElements()
+   */
+  void DrawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+
+    FlushVertexAttributeLocations();
+
+    LOG_GL("DrawElements %x %d %d %p\n", mode, count, type, indices);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawElements(mode, count, type, indices) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDrawElementsInstanced()
+   */
+  void DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const void* indices, GLsizei instanceCount)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+
+    FlushVertexAttributeLocations();
+
+    LOG_GL("DrawElementsInstanced %x %d %d %p %d\n", mode, count, type, indices, instanceCount);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawElementsInstanced(mode, count, type, indices, instanceCount) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glDrawRangeElements()
+   */
+  void DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void* indices)
+  {
+    mFrameBufferStateCache.DrawOperation( mColorMask, DepthBufferWriteEnabled(), StencilBufferWriteEnabled() );
+    FlushVertexAttributeLocations();
+
+    LOG_GL("DrawRangeElements %x %u %u %d %d %p\n", mode, start, end, count, type, indices);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DrawRangeElements(mode, start, end, count, type, indices) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glGenQuerieS()
+   */
+  void GenQueries(GLsizei n, GLuint* ids)
+  {
+    LOG_GL("GenQueries %d %p\n", n, ids);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenQueries(n, ids) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glGenTransformFeedbacks()
+   */
+  void GenTransformFeedbacks(GLsizei n, GLuint* ids)
+  {
+    LOG_GL("GenTransformFeedbacks %d %p\n", n, ids);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenTransformFeedbacks(n, ids) );
+  }
+
+  /**
+   * @return the current buffer bound for a given target
+   */
+  GLuint GetCurrentBoundArrayBuffer(GLenum target)
+  {
+    GLuint result(0);
+    switch(target)
+    {
+      case GL_ARRAY_BUFFER:
+      {
+        result = mBoundArrayBufferId;
+        break;
+      }
+      case GL_ELEMENT_ARRAY_BUFFER:
+      {
+        result = mBoundElementArrayBufferId;
+        break;
+      }
+      case GL_TRANSFORM_FEEDBACK_BUFFER:
+      {
+        result = mBoundTransformFeedbackBufferId;
+        break;
+      }
+      default:
+      {
+        DALI_ASSERT_DEBUG(0 && "target buffer type not supported");
+      }
+    }
+    return result;
+  }
+
+  void EnableVertexAttributeArray( GLuint location )
+  {
+    SetVertexAttributeLocation( location, true);
+  }
+
+  void DisableVertexAttributeArray( GLuint location )
+  {
+    SetVertexAttributeLocation( location, false);
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glVertexAttribDivisor()
+   */
+  void VertexAttribDivisor ( GLuint index, GLuint divisor )
+  {
+    LOG_GL("VertexAttribDivisor(%d, %d)\n", index, divisor );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.VertexAttribDivisor( index, divisor ) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glVertexAttribPointer()
+   */
+  void VertexAttribPointer( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr )
+  {
+    LOG_GL("VertexAttribPointer(%d, %d, %d, %d, %d, %x)\n", index, size, type, normalized, stride, ptr );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.VertexAttribPointer( index, size, type, normalized, stride, ptr ) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glInvalidateFramebuffer()
+   */
+  void InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum *attachments)
+  {
+    LOG_GL("InvalidateFramebuffer\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.InvalidateFramebuffer(target, numAttachments, attachments) );
+  }
+
+  /**
+   * The wrapper for OpenGL ES 2.0 glEnable() has been replaced by SetBlend, SetCullFace, SetDepthTest,
+   * SetDither, SetPolygonOffsetFill, SetSampleAlphaToCoverage, SetSampleCoverage, SetScissorTest & SetStencilTest.
+   */
+
+  /**
+   * This method replaces glEnable(GL_BLEND) and glDisable(GL_BLEND).
+   * @param[in] enable True if GL_BLEND should be enabled.
+   */
+  void SetBlend(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mBlendEnabled)
+    {
+      mBlendEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_BLEND\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_BLEND) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_BLEND\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_BLEND) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_DEPTH_TEST) and glDisable(GL_DEPTH_TEST).
+   * Note GL_DEPTH_TEST means enable the depth buffer for writing and or testing.
+   * glDepthMask is used to enable / disable writing to depth buffer.
+   * glDepthFunc us used to control if testing is enabled and how it is performed ( default GL_LESS)
+   *
+   * @param[in] enable True if GL_DEPTH_TEST should be enabled.
+   */
+  void EnableDepthBuffer( bool enable )
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if( enable != mDepthBufferEnabled )
+    {
+      mDepthBufferEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_DEPTH_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_DEPTH_TEST) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_DEPTH_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_DEPTH_TEST) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_DITHER) and glDisable(GL_DITHER).
+   * @param[in] enable True if GL_DITHER should be enabled.
+   */
+  void SetDither(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mDitherEnabled)
+    {
+      mDitherEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_DITHER\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_DITHER) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_DITHER\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_DITHER) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_POLYGON_OFFSET_FILL) and glDisable(GL_POLYGON_OFFSET_FILL).
+   * @param[in] enable True if GL_POLYGON_OFFSET_FILL should be enabled.
+   */
+  void SetPolygonOffsetFill(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mPolygonOffsetFillEnabled)
+    {
+      mPolygonOffsetFillEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_POLYGON_OFFSET_FILL\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_POLYGON_OFFSET_FILL) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_POLYGON_OFFSET_FILL\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_POLYGON_OFFSET_FILL) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE) and glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE).
+   * @param[in] enable True if GL_SAMPLE_ALPHA_TO_COVERAGE should be enabled.
+   */
+  void SetSampleAlphaToCoverage(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mSampleAlphaToCoverageEnabled)
+    {
+      mSampleAlphaToCoverageEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_SAMPLE_ALPHA_TO_COVERAGE\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_SAMPLE_ALPHA_TO_COVERAGE\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SAMPLE_ALPHA_TO_COVERAGE) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_SAMPLE_COVERAGE) and glDisable(GL_SAMPLE_COVERAGE).
+   * @param[in] enable True if GL_SAMPLE_COVERAGE should be enabled.
+   */
+  void SetSampleCoverage(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mSampleCoverageEnabled)
+    {
+      mSampleCoverageEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_SAMPLE_COVERAGE\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SAMPLE_COVERAGE) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_SAMPLE_COVERAGE\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SAMPLE_COVERAGE) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_SCISSOR_TEST) and glDisable(GL_SCISSOR_TEST).
+   * @param[in] enable True if GL_SCISSOR_TEST should be enabled.
+   */
+  void SetScissorTest(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if (enable != mScissorTestEnabled)
+    {
+      mScissorTestEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_SCISSOR_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_SCISSOR_TEST) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_SCISSOR_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_SCISSOR_TEST) );
+      }
+    }
+  }
+
+  /**
+   * This method replaces glEnable(GL_STENCIL_TEST) and glDisable(GL_STENCIL_TEST).
+   * Note GL_STENCIL_TEST means enable the stencil buffer for writing and or testing.
+   * glStencilMask is used to control how bits are written to the stencil buffer.
+   * glStencilFunc is used to control if testing is enabled and how it is performed ( default GL_ALWAYS )
+   * @param[in] enable True if GL_STENCIL_TEST should be enabled.
+   */
+  void EnableStencilBuffer(bool enable)
+  {
+    // Avoid unecessary calls to glEnable/glDisable
+    if( enable != mStencilBufferEnabled )
+    {
+      mStencilBufferEnabled = enable;
+
+      if (enable)
+      {
+        LOG_GL("Enable GL_STENCIL_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Enable(GL_STENCIL_TEST) );
+      }
+      else
+      {
+        LOG_GL("Disable GL_STENCIL_TEST\n");
+        CHECK_GL( mGlAbstraction, mGlAbstraction.Disable(GL_STENCIL_TEST) );
+      }
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glEndQuery()
+   */
+  void EndQuery(GLenum target)
+  {
+    LOG_GL("EndQuery %d\n", target);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.EndQuery(target) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glEndTransformFeedback()
+   */
+  void EndTransformFeedback()
+  {
+    LOG_GL("EndTransformFeedback\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.EndTransformFeedback() );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glFinish()
+   */
+  void Finish(void)
+  {
+    LOG_GL("Finish\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Finish() );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glFlush()
+   */
+  void Flush(void)
+  {
+    LOG_GL("Flush\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Flush() );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glFramebufferRenderbuffer()
+   */
+  void FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+  {
+    LOG_GL("FramebufferRenderbuffer %x %x %x %d\n", target, attachment, renderbuffertarget, renderbuffer);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glFramebufferTexture2D()
+   */
+  void FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+  {
+    LOG_GL("FramebufferTexture2D %x %x %x %d %d\n", target, attachment, textarget, texture, level);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferTexture2D(target, attachment, textarget, texture, level) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glFramebufferTextureLayer()
+   */
+  void FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+  {
+    LOG_GL("FramebufferTextureLayer %x %x %d %d %d\n", target, attachment, texture, level, layer);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FramebufferTextureLayer(target, attachment, texture, level, layer) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glFrontFace()
+   */
+  void FrontFace(GLenum mode)
+  {
+    LOG_GL("FrontFace %x\n", mode);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.FrontFace(mode) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGenBuffers()
+   */
+  void GenBuffers(GLsizei n, GLuint* buffers)
+  {
+    LOG_GL("GenBuffers %d\n", n, buffers);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenBuffers(n, buffers) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGenerateMipmap()
+   */
+  void GenerateMipmap(GLenum target)
+  {
+    LOG_GL("GenerateMipmap %x\n", target);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenerateMipmap(target) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGenFramebuffers()
+   */
+  void GenFramebuffers(GLsizei n, GLuint* framebuffers)
+  {
+    LOG_GL("GenFramebuffers %d %p\n", n, framebuffers);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenFramebuffers(n, framebuffers) );
+
+    mFrameBufferStateCache.FrameBuffersCreated( n, framebuffers );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGenRenderbuffers()
+   */
+  void GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+  {
+    LOG_GL("GenRenderbuffers %d %p\n", n, renderbuffers);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenRenderbuffers(n, renderbuffers) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGenTextures()
+   */
+  void GenTextures(GLsizei n, GLuint* textures)
+  {
+    LOG_GL("GenTextures %d %p\n", n, textures);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GenTextures(n, textures) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetBooleanv()
+   */
+  void GetBooleanv(GLenum pname, GLboolean* params)
+  {
+    LOG_GL("GetBooleanv %x\n", pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBooleanv(pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetBufferParameteriv()
+   */
+  void GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+    LOG_GL("GetBufferParameteriv %x %x %p\n", target, pname, params);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBufferParameteriv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glGetBufferPointer()
+   */
+  void GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+  {
+    LOG_GL("GetBufferPointerv %x %x %p\n", target, pname, params);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetBufferPointerv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetError()
+   */
+  GLenum GetError(void)
+  {
+    // Not worth logging here
+    return mGlAbstraction.GetError();
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetFloatv()
+   */
+  void GetFloatv(GLenum pname, GLfloat* params)
+  {
+    LOG_GL("GetFloatv %x\n", pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetFloatv(pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetFramebufferAttachmentParameteriv()
+   */
+  void GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+  {
+    LOG_GL("GetFramebufferAttachmentParameteriv %x %x %x\n", target, attachment, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetFramebufferAttachmentParameteriv(target, attachment, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetIntegerv()
+   */
+  void GetIntegerv(GLenum pname, GLint* params)
+  {
+    LOG_GL("GetIntegerv %x\n", pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetIntegerv(pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glGetQueryiv()
+   */
+  void GetQueryiv(GLenum target, GLenum pname, GLint* params)
+  {
+    LOG_GL("GetQueryiv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetQueryiv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glGetQueryObjectuiv()
+   */
+  void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+  {
+    LOG_GL("GetQueryObjectuiv %u %x %p\n", id, pname, params);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetQueryObjectuiv(id, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetRenderbufferParameteriv()
+   */
+  void GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+    LOG_GL("GetRenderbufferParameteriv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetRenderbufferParameteriv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetString()
+   */
+  const GLubyte* GetString(GLenum name)
+  {
+    LOG_GL("GetString %x\n", name);
+    const GLubyte* str = CHECK_GL( mGlAbstraction, mGlAbstraction.GetString(name) );
+    return str;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetTexParameterfv()
+   */
+  void GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+  {
+    LOG_GL("GetTexParameterfv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetTexParameterfv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glGetTexParameteriv()
+   */
+  void GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+  {
+    LOG_GL("GetTexParameteriv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetTexParameteriv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glHint()
+   */
+  void Hint(GLenum target, GLenum mode)
+  {
+    LOG_GL("Hint %x %x\n", target, mode);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Hint(target, mode) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glIsBuffer()
+   */
+  GLboolean IsBuffer(GLuint buffer)
+  {
+    LOG_GL("IsBuffer %d\n", buffer);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsBuffer(buffer) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glIsEnabled()
+   */
+  GLboolean IsEnabled(GLenum cap)
+  {
+    LOG_GL("IsEnabled %x\n", cap);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsEnabled(cap) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glIsFramebuffer()
+   */
+  GLboolean IsFramebuffer(GLuint framebuffer)
+  {
+    LOG_GL("IsFramebuffer %d\n", framebuffer);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsFramebuffer(framebuffer) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glIsQuery()
+   */
+  GLboolean IsQuery(GLuint id)
+  {
+    LOG_GL("IsQuery %u\n", id);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsQuery(id) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glIsRenderbuffer()
+   */
+  GLboolean IsRenderbuffer(GLuint renderbuffer)
+  {
+    LOG_GL("IsRenderbuffer %d\n", renderbuffer);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsRenderbuffer(renderbuffer) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glIsTexture()
+   */
+  GLboolean IsTexture(GLuint texture)
+  {
+    LOG_GL("IsTexture %d\n", texture);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsTexture(texture) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glIsTransformFeedback()
+   */
+  GLboolean IsTransformFeedback(GLuint id)
+  {
+    LOG_GL("IsTransformFeedback %u\n", id);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.IsTransformFeedback(id) );
+    return val;
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glLineWidth()
+   */
+  void LineWidth(GLfloat width)
+  {
+    LOG_GL("LineWidth %f\n", width);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.LineWidth(width) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glPauseTransformFeedback()
+   */
+  void PauseTransformFeedback()
+  {
+    LOG_GL("PauseTransformFeedback\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PauseTransformFeedback() );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glPixelStorei()
+   */
+  void PixelStorei(GLenum pname, GLint param)
+  {
+    LOG_GL("PixelStorei %x %d\n", pname, param);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PixelStorei(pname, param) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glPolygonOffset()
+   */
+  void PolygonOffset(GLfloat factor, GLfloat units)
+  {
+    LOG_GL("PolygonOffset %f %f\n", factor, units);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.PolygonOffset(factor, units) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glReadPixels()
+   */
+  void ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
+  {
+    LOG_GL("ReadPixels %d %d %d %d %x %x\n", x, y, width, height, format, type);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ReadPixels(x, y, width, height, format, type, pixels) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glRenderbufferStorage()
+   */
+  void RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+  {
+    LOG_GL("RenderbufferStorage %x %x %d %d\n", target, internalformat, width, height);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.RenderbufferStorage(target, internalformat, width, height) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glRenderbufferStorageMultisample()
+   */
+  void RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+  {
+    LOG_GL("RenderbufferStorageMultisample %x %u %x %d %d\n", target, samples, internalformat, width, height);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.RenderbufferStorageMultisample(target, samples, internalformat, width, height) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glResumeTransformFeedback()
+   */
+  void ResumeTransformFeedback()
+  {
+    LOG_GL("ResumeTransformFeedback\n");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ResumeTransformFeedback() );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glSampleCoverage()
+   */
+  void SampleCoverage(GLclampf value, GLboolean invert)
+  {
+    LOG_GL("SampleCoverage %f %s\n", value, invert ? "True" : "False");
+    CHECK_GL( mGlAbstraction, mGlAbstraction.SampleCoverage(value, invert) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glScissor()
+   */
+  void Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+    LOG_GL("Scissor %d %d %d %d\n", x, y, width, height);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Scissor(x, y, width, height) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilFunc()
+   */
+  void StencilFunc(GLenum func, GLint ref, GLuint mask)
+  {
+
+
+    LOG_GL("StencilFunc %x %d %d\n", func, ref, mask);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFunc(func, ref, mask) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilFuncSeparate()
+   */
+  void StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+  {
+    LOG_GL("StencilFuncSeparate %x %x %d %d\n", face, func, ref, mask);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilFuncSeparate(face, func, ref, mask) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilMask()
+   */
+  void StencilMask(GLuint mask)
+  {
+    if( mask != mStencilMask )
+    {
+      mStencilMask = mask;
+
+      LOG_GL("StencilMask %d\n", mask);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.StencilMask(mask) );
+    }
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilMaskSeparate()
+   */
+  void StencilMaskSeparate(GLenum face, GLuint mask)
+  {
+    LOG_GL("StencilMaskSeparate %x %d\n", face, mask);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilMaskSeparate(face, mask) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilOp()
+   */
+  void StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+  {
+    LOG_GL("StencilOp %x %x %x\n", fail, zfail, zpass);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOp(fail, zfail, zpass) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glStencilOpSeparate()
+   */
+  void StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+  {
+    LOG_GL("StencilOpSeparate %x %x %x %x\n", face, fail, zfail, zpass);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.StencilOpSeparate(face, fail, zfail, zpass) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexImage2D()
+   */
+  void TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
+                  GLint border, GLenum format, GLenum type, const void* pixels)
+  {
+    LOG_GL("TexImage2D %x %d %d %dx%d %d %x %x %p\n", target, level, internalformat, width, height, border, format, type, pixels);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexImage2D(target, level, internalformat, width, height, border, format, type, pixels) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glTexImage3D()
+   */
+  void TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth,
+                  GLint border, GLenum format, GLenum type, const void* pixels)
+  {
+    LOG_GL("TexImage3D %x %d %d %dx%dx%d %d %x %x %p\n", target, level, internalformat, width, height, depth, border, format, type, pixels);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexParameterf()
+   */
+  void TexParameterf(GLenum target, GLenum pname, GLfloat param)
+  {
+    LOG_GL("TexParameterf %x %x %f\n", target, pname, param);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameterf(target, pname, param) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexParameterfv()
+   */
+  void TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+  {
+    LOG_GL("TexParameterfv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameterfv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexParameteri()
+   */
+  void TexParameteri(GLenum target, GLenum pname, GLint param)
+  {
+    LOG_GL("TexParameteri %x %x %d\n", target, pname, param);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameteri(target, pname, param) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexParameteriv()
+   */
+  void TexParameteriv(GLenum target, GLenum pname, const GLint* params)
+  {
+    LOG_GL("TexParameteriv %x %x\n", target, pname);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexParameteriv(target, pname, params) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 2.0 glTexSubImage2D()
+   */
+  void TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+                     GLenum format, GLenum type, const void* pixels)
+  {
+    LOG_GL("TexSubImage2D %x %d %d %d %d %d %x %x %p\n", target, level, xoffset, yoffset, width, height, format, type, pixels);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glTexSubImage3D()
+   */
+  void TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
+                     GLsizei width, GLsizei height, GLsizei depth,
+                     GLenum format, GLenum type, const void* pixels)
+  {
+    LOG_GL("TexSubImage3D %x %d %d %d %d %d %d %d %x %x %p\n", target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+    CHECK_GL( mGlAbstraction, mGlAbstraction.TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) );
+  }
+
+  /**
+   * Wrapper for OpenGL ES 3.0 glUnmapBubffer()
+   */
+  GLboolean UnmapBuffer(GLenum target)
+  {
+    LOG_GL("UnmapBuffer %x \n", target);
+    GLboolean val = CHECK_GL( mGlAbstraction, mGlAbstraction.UnmapBuffer(target) );
+    return val;
+  }
+  /**
+   * Wrapper for OpenGL ES 2.0 glViewport()
+   */
+  void Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+  {
+    // check if its same as already set
+    Rect<int> newViewport( x, y, width, height );
+    if( mViewPort != newViewport )
+    {
+      // set new one
+      LOG_GL("Viewport %d %d %d %d\n", x, y, width, height);
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Viewport(x, y, width, height) );
+      mViewPort = newViewport; // remember new one
+    }
+  }
+
+  /**
+   * Get the implementation defined MAX_TEXTURE_SIZE. This values is cached when the context is created
+   * @return The implementation defined MAX_TEXTURE_SIZE
+   */
+  GLint CachedMaxTextureSize() const
+  {
+    return mMaxTextureSize;
+  }
+
+  /**
+   * Get the current viewport.
+   * @return Viewport rectangle.
+   */
+  const Rect< int >& GetViewport();
+
+  /**
+   * Set the frame count of render thread
+   */
+  inline void SetFrameCount(unsigned int frameCount)
+  {
+    mFrameCount = frameCount;
+  }
+
+  /**
+   * Get the frame count
+   */
+  inline unsigned int GetFrameCount()
+  {
+    return mFrameCount;
+  }
+
+  /**
+   * Increment the count of culled renderers
+   */
+  inline void IncrementCulledCount()
+  {
+    mCulledCount++;
+  }
+
+  /**
+   * Clear the count of culled renderers
+   */
+  inline void ClearCulledCount()
+  {
+    mCulledCount = 0;
+  }
+
+  /**
+   * Get the count of culled renderers in this frame
+   */
+  inline unsigned int GetCulledCount()
+  {
+    return mCulledCount;
+  }
+
+  /**
+   * Increment the count of culled renderers
+   */
+  inline void IncrementRendererCount()
+  {
+    mRendererCount++;
+  }
+
+  /**
+   * Clear the count of image renderers
+   */
+  inline void ClearRendererCount()
+  {
+    mRendererCount = 0;
+  }
+
+  /**
+   * Get the count of image renderers in this frame
+   */
+  inline unsigned int GetRendererCount()
+  {
+    return mRendererCount;
+  }
+
+  /**
+   * Set true if an pixmap image is y-inverted
+   */
+  void SetPixmapYInverted( bool yInverted );
+
+  /**
+   * Query whether an pixmap image is y-inverted
+   * @return true if a pixmap is y-inverted, otherwise false
+   */
+  bool IsPixmapYInverted() const;
+
+private: // Implementation
+
+  /**
+   * @return true if next draw operation will write to depth buffer
+   */
+  bool DepthBufferWriteEnabled() const
+  {
+    return mDepthBufferEnabled && mDepthMaskEnabled;
+  }
+
+  /**
+   * @return true if next draw operation will write to stencil buffer
+   */
+  bool StencilBufferWriteEnabled() const
+  {
+    return mStencilBufferEnabled && ( mStencilMask > 0 );
+  }
+
+  /**
+   * Flushes vertex attribute location changes to the driver
+   */
+  void FlushVertexAttributeLocations();
+
+  /**
+   * Reset the cached internal vertex attribute state
+   */
+  void ResetVertexAttributeState();
+
+  /**
+   * Either enables or disables a vertex attribute location in the cache
+   * The cahnges won't take affect until FlushVertexAttributeLocations is called
+   * @param location attribute location
+   * @param state attribute state
+   */
+  void SetVertexAttributeLocation(unsigned int location, bool state);
+
+  /**
+   * Sets the initial GL state.
+   */
+  void ResetGlState();
+
+private: // Data
+
+  Integration::GlAbstraction& mGlAbstraction;
+
+  bool mGlContextCreated; ///< True if the OpenGL context has been created
+
+  // glEnable/glDisable states
+  bool mColorMask;
+  GLuint mStencilMask;
+  bool mBlendEnabled;
+  bool mDepthBufferEnabled;
+  bool mDepthMaskEnabled;
+  bool mDitherEnabled;
+  bool mPolygonOffsetFillEnabled;
+  bool mSampleAlphaToCoverageEnabled;
+  bool mSampleCoverageEnabled;
+  bool mScissorTestEnabled;
+  bool mStencilBufferEnabled;
+  bool mClearColorSet;
+  bool mUsingDefaultBlendColor;
+
+  // glBindBuffer() state
+  GLuint mBoundArrayBufferId;        ///< The ID passed to glBindBuffer(GL_ARRAY_BUFFER)
+  GLuint mBoundElementArrayBufferId; ///< The ID passed to glBindBuffer(GL_ELEMENT_ARRAY_BUFFER)
+  GLuint mBoundTransformFeedbackBufferId; ///< The ID passed to glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER)
+
+  // glBindTexture() state
+  TextureUnit mActiveTextureUnit;
+  GLuint mBound2dTextureId[ MAX_TEXTURE_UNITS ];  ///< The ID passed to glBindTexture(GL_TEXTURE_2D)
+
+  // glBlendColor() state
+  Vector4 mBlendColor; ///< Blend color
+
+  // glBlendFuncSeparate() state
+  GLenum mBlendFuncSeparateSrcRGB;   ///< The srcRGB parameter passed to glBlendFuncSeparate()
+  GLenum mBlendFuncSeparateDstRGB;   ///< The dstRGB parameter passed to glBlendFuncSeparate()
+  GLenum mBlendFuncSeparateSrcAlpha; ///< The srcAlpha parameter passed to glBlendFuncSeparate()
+  GLenum mBlendFuncSeparateDstAlpha; ///< The dstAlpha parameter passed to glBlendFuncSeparate()
+
+  // glBlendEquationSeparate state
+  GLenum mBlendEquationSeparateModeRGB;    ///< Controls RGB blend mode
+  GLenum mBlendEquationSeparateModeAlpha;  ///< Controls Alpha blend mode
+
+  GLint mMaxTextureSize;      ///< return value from GetIntegerv(GL_MAX_TEXTURE_SIZE)
+  Vector4 mClearColor;        ///< clear color
+
+  // Face culling mode
+  CullFaceMode mCullFaceMode;
+
+  // cached viewport size
+  Rect< int > mViewPort;
+
+  // Vertex Attribute Buffer enable caching
+  bool mVertexAttributeCachedState[ MAX_ATTRIBUTE_CACHE_SIZE ];    ///< Value cache for Enable Vertex Attribute
+  bool mVertexAttributeCurrentState[ MAX_ATTRIBUTE_CACHE_SIZE ];   ///< Current state on the driver for Enable Vertex Attribute
+
+  unsigned int mFrameCount;       ///< Number of render frames
+  unsigned int mCulledCount;      ///< Number of culled renderers per frame
+  unsigned int mRendererCount;    ///< Number of image renderers per frame
+  FrameBufferStateCache mFrameBufferStateCache;   ///< frame buffer state cache
+
+  bool mIsPixmapYInverted;        ///< Flag to whether a pixmap is y-inverted
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONTEXT_H__
diff --git a/dali/internal/render/gl-resources/frame-buffer-state-cache.cpp b/dali/internal/render/gl-resources/frame-buffer-state-cache.cpp
new file mode 100644 (file)
index 0000000..0ba565f
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "frame-buffer-state-cache.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/gl-defines.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+FrameBufferStateCache::FrameBufferStateCache()
+:mCurrentFrameBufferId(0)
+{
+}
+
+FrameBufferStateCache::~FrameBufferStateCache()
+{
+}
+
+GLbitfield FrameBufferStateCache::GetClearMask( GLbitfield mask, bool forceClear, bool scissorTestEnabled )
+{
+  if( scissorTestEnabled )
+  {
+    // don't do anything if scissor test is enabled, in the future we could
+    // potentially keep track of frame buffer size vs scissor test size to see if the entire
+    // buffer is cleared or not.
+    return mask;
+  }
+  FrameBufferState* state = GetFrameBufferState( mCurrentFrameBufferId );
+  if( !state )
+  {
+    DALI_LOG_ERROR("FrameBuffer not found %d \n", mCurrentFrameBufferId);
+    return mask;
+  }
+
+  // if we are forcing the clear operation, then just update the internal cached values
+  if( forceClear )
+  {
+    SetClearState( state, mask );
+    return mask;
+  }
+
+  // use the cached values
+  if( mask & GL_COLOR_BUFFER_BIT)
+  {
+    // check if color buffer is currently clean
+    if( state->mState & COLOR_BUFFER_CLEAN )
+    {
+      // remove clear color buffer flag from bitmask, no need to clear twice
+      mask&= ~GL_COLOR_BUFFER_BIT;
+    }
+  }
+  if( mask & GL_DEPTH_BUFFER_BIT)
+  {
+    // check if depth buffer is currently clean
+    if( state->mState & DEPTH_BUFFER_CLEAN )
+    {
+      // remove clear depth buffer flag from bitmask, no need to clear twice
+      mask&= ~GL_DEPTH_BUFFER_BIT;
+    }
+  }
+  if( mask & GL_STENCIL_BUFFER_BIT)
+  {
+    // check if stencil buffer is currently clean
+    if( state->mState & STENCIL_BUFFER_CLEAN )
+    {
+      // remove clear stencil buffer flag from bitmask, no need to clear twice
+
+      mask&= ~GL_STENCIL_BUFFER_BIT;
+    }
+  }
+
+  // set the clear state based, what's about to be cleared
+  SetClearState( state, mask );
+
+  return mask;
+}
+
+void FrameBufferStateCache::SetCurrentFrameBuffer( GLuint frameBufferId )
+{
+  mCurrentFrameBufferId = frameBufferId;
+}
+
+void FrameBufferStateCache::FrameBuffersDeleted( GLsizei count, const GLuint* const frameBuffers )
+{
+  for( GLsizei i = 0; i < count; ++i )
+  {
+    DeleteFrameBuffer( frameBuffers[i] );
+  }
+}
+void FrameBufferStateCache::FrameBuffersCreated( GLsizei count, const GLuint* const frameBuffers )
+{
+  for( GLsizei i = 0; i < count; ++i )
+  {
+    // check the frame buffer doesn't exist already
+    GLuint id = frameBuffers[i];
+
+    FrameBufferState* state =  GetFrameBufferState( id );
+    if( state )
+    {
+      DALI_LOG_ERROR("FrameBuffer already exists%d \n", id );
+      // reset its state
+      state->mState = GetInitialFrameBufferState();
+      continue;
+    }
+
+    FrameBufferState newFrameBuffer( frameBuffers[i], GetInitialFrameBufferState() );
+    mFrameBufferStates.PushBack( newFrameBuffer );
+  }
+}
+
+void FrameBufferStateCache::DrawOperation( bool colorBuffer, bool depthBuffer, bool stencilBuffer )
+{
+  FrameBufferState* state = GetFrameBufferState( mCurrentFrameBufferId );
+  if( !state )
+  {
+    // an error will have already been logged by the clear operation
+    return;
+  }
+
+  if( colorBuffer )
+  {
+    // un-set the clean bit
+    state->mState &= ~COLOR_BUFFER_CLEAN;
+  }
+  if( depthBuffer )
+  {
+    // un-set the clean bit
+    state->mState &= ~DEPTH_BUFFER_CLEAN;
+  }
+  if( stencilBuffer )
+  {
+    // un-set the clean bit
+    state->mState &= ~STENCIL_BUFFER_CLEAN;
+  }
+
+}
+
+void FrameBufferStateCache::Reset()
+{
+  mFrameBufferStates.Clear();
+
+  // create the default frame buffer
+  GLuint id = 0; // 0 == default frame buffer id
+  FrameBuffersCreated( 1, &id );
+}
+
+void FrameBufferStateCache::SetClearState( FrameBufferState* state, GLbitfield mask )
+{
+  if( mask & GL_COLOR_BUFFER_BIT)
+  {
+    // set the color buffer to clean
+    state->mState |= COLOR_BUFFER_CLEAN;
+  }
+  if( mask & GL_DEPTH_BUFFER_BIT)
+  {
+    // set the depth buffer to clean
+    state->mState |= DEPTH_BUFFER_CLEAN;
+  }
+  if( mask & GL_STENCIL_BUFFER_BIT)
+  {
+    // set the stencil buffer to clean
+    state->mState |= STENCIL_BUFFER_CLEAN;
+  }
+}
+
+FrameBufferStateCache::FrameBufferState* FrameBufferStateCache::GetFrameBufferState(  GLuint frameBufferId )
+{
+  for( FrameBufferStateVector::SizeType i = 0; i < mFrameBufferStates.Count(); ++i )
+  {
+    FrameBufferState& state = mFrameBufferStates[i];
+    if( state.mId == frameBufferId )
+    {
+      return &state;
+    }
+  }
+  return NULL;
+}
+
+void FrameBufferStateCache::DeleteFrameBuffer( GLuint frameBufferId )
+{
+  FrameBufferStateVector::Iterator iter = mFrameBufferStates.Begin();
+  FrameBufferStateVector::Iterator endIter = mFrameBufferStates.End();
+
+  for( ; iter != endIter ; ++iter )
+  {
+   if( (*iter).mId == frameBufferId )
+   {
+     mFrameBufferStates.Erase( iter);
+     return;
+   }
+ }
+ DALI_LOG_ERROR("FrameBuffer not found %d \n", frameBufferId);
+}
+
+unsigned int FrameBufferStateCache::GetInitialFrameBufferState()
+{
+  return COLOR_BUFFER_CLEAN | DEPTH_BUFFER_CLEAN | STENCIL_BUFFER_CLEAN;
+}
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/gl-resources/frame-buffer-state-cache.h b/dali/internal/render/gl-resources/frame-buffer-state-cache.h
new file mode 100644 (file)
index 0000000..2594aa9
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef __DALI_INTERNAL_CONTEXT_FRAME_BUFFER_STATE_CACHE_H__
+#define __DALI_INTERNAL_CONTEXT_FRAME_BUFFER_STATE_CACHE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * @brief Keeps track of color, depth and stencil buffer state within each frame buffer.
+ * Used to avoid redundant glClear calls.
+ *
+ */
+class FrameBufferStateCache
+{
+public:
+
+
+  /**
+   * @brief Constructor
+   */
+  FrameBufferStateCache();
+
+  /**
+   * @brief  non-virtual destructor
+   */
+  ~FrameBufferStateCache();
+
+  /**
+   * @brief Get the bitmask to pass to glClear based on the mask requested
+   * and the current state of the frame buffer
+   * @param[in] mask glClear bit mask
+   * @param[in] forceClear whether to force the clear ( ignore cached state)
+   * @param[in] scissorTestEnabled whether scissor test is enabled
+   * @return new bitmask to pass to glClear
+   */
+  GLbitfield GetClearMask( GLbitfield mask, bool forceClear, bool scissorTestEnabled );
+
+  /**
+   * @brief Set the current bound frame buffer
+   * @param[in] frameBufferId frame buffer id
+   */
+  void SetCurrentFrameBuffer( GLuint frameBufferId );
+
+  /**
+   * @brief Called when frame buffers are deleted
+   * @param[in] count number of frame buffers
+   * @param[in] framebuffers array of frame buffer ids
+   */
+  void FrameBuffersDeleted( GLsizei count, const GLuint* const frameBuffers );
+
+  /**
+   * @brief Called when frame buffers are created
+   * @param[in] count number of frame buffers
+   * @param[in] framebuffers array of frame buffer ids
+   */
+  void FrameBuffersCreated( GLsizei count, const GLuint* const frameBuffers );
+
+  /**
+   * @brief Draw operation performed on the current frame buffer
+   * @param[in] colorBufferUsed whether the color buffer is being written to (glColorMask )
+   * @param[in] depthBufferUsed whether the depth buffer is being written to (glDepthMask )
+   * @param[in] stencilBufferUsed whether the stencil buffer is being written to (glStencilMask )
+   */
+  void DrawOperation( bool colorBufferUsed, bool depthBufferUsed, bool stencilBufferUsed );
+
+  /**
+   * Reset the cache
+   */
+  void Reset();
+
+private:
+
+  /**
+   * Current status of the frame buffer
+   */
+  enum FrameBufferStatus
+  {
+    COLOR_BUFFER_CLEAN      = 1 << 0, ///< color buffer clean
+    DEPTH_BUFFER_CLEAN      = 1 << 1, ///< depth buffer clean
+    STENCIL_BUFFER_CLEAN    = 1 << 2, ///< stencil buffer clean
+  };
+
+  /**
+   * POD to store the status of frame buffer regarding color,depth and stencil buffers
+   */
+  struct FrameBufferState
+  {
+    /**
+     * Constructor
+     */
+    FrameBufferState( GLuint id, unsigned int state)
+    :mId( id ),
+    mState( state )
+    {
+    }
+    GLuint mId;           ///< Frame buffer id
+    unsigned int mState;  ///< State, bitmask of FrameBufferStatus flags
+  };
+
+  typedef Dali::Vector< FrameBufferState > FrameBufferStateVector;
+
+  /**
+   * @brief Set the clear state
+   * @param[in] pointer to frame buffer state object
+   * @param[in] mask clear mask
+   */
+  void SetClearState( FrameBufferState* state, GLbitfield mask );
+
+  /**
+   * @brief Helper
+   * @param[in] frameBufferId frame buffer id
+   * @return pointer to  frame buffer state object ( NULL if it doesn't exist)
+   */
+  FrameBufferState* GetFrameBufferState( GLuint frameBufferId );
+
+  /**
+   * @brief Helper to delete a frame buffer state object
+   * @param[in] frameBufferId frame buffer id
+   */
+  void DeleteFrameBuffer( GLuint frameBufferId );
+
+  /**
+   * @brief Get the default state of a frame buffer, before it's used
+   * @return initial state
+   */
+  unsigned int GetInitialFrameBufferState();
+
+  FrameBufferStateCache( const FrameBufferStateCache& );            ///< undefined copy constructor
+
+  FrameBufferStateCache& operator=( const FrameBufferStateCache& ); ///< undefined assignment operator
+
+private: // data
+
+  FrameBufferStateVector    mFrameBufferStates;     ///< state of the frame buffers
+  GLuint                    mCurrentFrameBufferId;  ///< currently bound frame buffer
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CONTEXT_FRAME_BUFFER_STATE_CACHE_H__
diff --git a/dali/internal/render/gl-resources/frame-buffer-texture.cpp b/dali/internal/render/gl-resources/frame-buffer-texture.cpp
new file mode 100644 (file)
index 0000000..f0b2246
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/frame-buffer-texture.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+FrameBufferTexture::FrameBufferTexture(unsigned int width, unsigned int height, Context& context)
+: Texture( context,
+           width, height,
+           width, height ),
+  mFrameBufferName(0),
+  mRenderBufferName(0),
+  mStencilBufferName(0),
+  mPixelFormat(Pixel::RGBA8888),
+  mBufferFormat(RenderBuffer::COLOR)
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+}
+
+FrameBufferTexture::FrameBufferTexture(unsigned int width, unsigned int height, Pixel::Format pixelFormat, Context& context)
+: Texture( context,
+           width, height,
+           width, height ),
+  mFrameBufferName(0),
+  mRenderBufferName(0),
+  mStencilBufferName(0),
+  mPixelFormat( pixelFormat ),
+  mBufferFormat(RenderBuffer::COLOR)
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+}
+
+FrameBufferTexture::FrameBufferTexture(unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat, Context& context)
+: Texture( context,
+           width, height,
+           width, height ),
+  mFrameBufferName(0),
+  mRenderBufferName(0),
+  mStencilBufferName(0),
+  mPixelFormat( pixelFormat ),
+  mBufferFormat( bufferFormat )
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+}
+
+FrameBufferTexture::~FrameBufferTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+bool FrameBufferTexture::IsFullyOpaque() const
+{
+  return true;
+}
+
+bool FrameBufferTexture::HasAlphaChannel() const
+{
+  return false;
+}
+
+bool FrameBufferTexture::Init()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+  return true;
+}
+
+bool FrameBufferTexture::Prepare()
+{
+  // bind texture
+  Bind( GL_TEXTURE_2D, TEXTURE_UNIT_FRAMEBUFFER );
+
+  if( 0 != mId )
+  {
+    // bind frame buffer
+    mContext.BindFramebuffer(GL_FRAMEBUFFER, mFrameBufferName);
+
+    return true;
+  }
+
+  // Texture could not be bound
+  return false;
+}
+
+bool FrameBufferTexture::CreateGlTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  mContext.GenTextures(1, &mId);
+  mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );  // bind in unused unit so rebind works the first time
+  mContext.Bind2dTexture(mId);
+
+  // set texture parameters
+  mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+  mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+  // Assign memory for texture in GL memory space
+  GLenum pixelFormat = GL_RGBA;
+  GLenum pixelDataType = GL_UNSIGNED_BYTE;
+  Integration::ConvertToGlFormat(mPixelFormat, pixelDataType, pixelFormat);
+
+  mContext.TexImage2D(GL_TEXTURE_2D, 0, pixelFormat, mWidth, mHeight, 0, pixelFormat, pixelDataType, NULL);
+
+  // generate frame and render buffer names
+  mContext.GenFramebuffers(1, &mFrameBufferName);
+
+  /* WE ALWAYS HAVE COLOR COMPONENT */
+
+  // bind frame buffer
+  mContext.BindFramebuffer(GL_FRAMEBUFFER, mFrameBufferName);
+  // attach texture to the color attachment point
+  mContext.FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mId, 0);
+
+  if (mBufferFormat == RenderBuffer::COLOR_DEPTH_STENCIL)
+  {
+    mContext.GenRenderbuffers(1, &mRenderBufferName);
+    mContext.GenRenderbuffers(1, &mStencilBufferName);
+
+    // Bind render buffer and create 16 depth buffer
+    mContext.BindRenderbuffer(GL_RENDERBUFFER, mRenderBufferName);
+    mContext.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mWidth, mHeight);
+
+    // Bind render buffer and create 8 stencil buffer
+    mContext.BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferName);
+    mContext.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mWidth, mHeight);
+
+    // attach render buffer to the depth buffer attachment point
+    mContext.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderBufferName);
+    // attach render buffer to the stencil buffer attachment point
+    mContext.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mStencilBufferName);
+  }
+  else if (mBufferFormat == RenderBuffer::COLOR_DEPTH)
+  {
+    mContext.GenRenderbuffers(1, &mRenderBufferName);
+
+    // Bind render buffer and create 8 stencil buffer
+    mContext.BindRenderbuffer(GL_RENDERBUFFER, mRenderBufferName);
+    mContext.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mWidth, mHeight);
+
+    // attach render buffer to the depth buffer attachment point
+    mContext.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, mRenderBufferName);
+  }
+  else if (mBufferFormat == RenderBuffer::COLOR_STENCIL)
+  {
+    mContext.GenRenderbuffers(1, &mStencilBufferName);
+
+    // Bind render buffer and create 8 stencil buffer
+    mContext.BindRenderbuffer(GL_RENDERBUFFER, mStencilBufferName);
+    mContext.RenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, mWidth, mHeight);
+
+    // attach render buffer to the depth buffer attachment point
+    mContext.FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mStencilBufferName);
+  }
+
+  int status = mContext.CheckFramebufferStatus(GL_FRAMEBUFFER);
+  if ( GL_FRAMEBUFFER_COMPLETE != status )
+  {
+    DALI_LOG_ERROR( "status (0x%x), glError (0x%x)\n", status, mContext.GetError() );
+    DALI_ASSERT_ALWAYS( false && "Frame buffer is not complete!" );
+  }
+
+  return mId != 0;
+}
+
+void FrameBufferTexture::GlCleanup()
+{
+  Texture::GlCleanup();
+
+  if (mFrameBufferName != 0)
+  {
+    mContext.DeleteFramebuffers(1, &mFrameBufferName );
+    mFrameBufferName = 0;
+  }
+
+  if (mRenderBufferName != 0)
+  {
+    mContext.DeleteRenderbuffers(1, &mRenderBufferName );
+    mRenderBufferName = 0;
+  }
+
+  if (mStencilBufferName != 0)
+  {
+    mContext.DeleteRenderbuffers(1, &mStencilBufferName );
+    mStencilBufferName = 0;
+  }
+}
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/frame-buffer-texture.h b/dali/internal/render/gl-resources/frame-buffer-texture.h
new file mode 100644 (file)
index 0000000..e3d8ec4
--- /dev/null
@@ -0,0 +1,120 @@
+#ifndef __DALI_INTERNAL_FRAME_BUFFER_TEXTURE_H__
+#define __DALI_INTERNAL_FRAME_BUFFER_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Texture class.
+ * Used as a frame buffer for RenderTask
+ */
+class FrameBufferTexture : public Texture
+{
+public:
+
+  /**
+   * Creates a new texture object
+   * @param[in] width       The width (pixels)
+   * @param[in] height      The height (pixels)
+   * @param[in] context The GL context
+   */
+  FrameBufferTexture(unsigned int width, unsigned int height, Context& context);
+
+  /**
+   * Creates a new texture object
+   * @param[in] width       The width (pixels)
+   * @param[in] height      The height (pixels)
+   * @param[in] pixelFormat The pixel format
+   * @param[in] context The GL context
+   */
+  FrameBufferTexture(unsigned int width, unsigned int height, Pixel::Format pixelFormat, Context& context);
+
+  /**
+   * Creates a new texture object
+   * @param[in] width         The width (pixels)
+   * @param[in] height        The height (pixels)
+   * @param[in] pixelFormat   The pixel format
+   * @param[in] bufferFormat  The buffer formats to be attached in the FBO
+   * @param[in] context The GL context
+   */
+  FrameBufferTexture(unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat, Context& context);
+
+  /**
+   * Destructor.
+   */
+  virtual ~FrameBufferTexture();
+
+  /**
+   * @copydoc Texture::IsFullyOpaque
+   */
+  virtual bool IsFullyOpaque() const;
+
+  /**
+   * @copydoc Texture::HasAlphaChannel
+   */
+  virtual bool HasAlphaChannel() const;
+
+  /**
+   * @copydoc Texture::Init
+   */
+  virtual bool Init();
+
+  /**
+   * Prepare FBO for rendering.
+   * @return true if the FBO is prepared and its status is GL_FRAMEBUFFER_COMPLETE, otherwise false.
+   */
+  virtual bool Prepare();
+
+protected:
+  unsigned int mFrameBufferName;
+  unsigned int mRenderBufferName;
+  unsigned int mStencilBufferName;
+  Pixel::Format mPixelFormat;
+  RenderBuffer::Format mBufferFormat;
+
+  /**
+   * @copydoc Texture::CreateGlTexture
+   */
+  virtual bool CreateGlTexture();
+
+  /**
+   * @copydoc Texture::GlCleanup
+   */
+  virtual void GlCleanup();
+
+}; // class FrameBufferTexture
+
+}  //namespace Internal
+
+} //namespace Dali
+#endif //__DALI_INTERNAL_FRAME_BUFFER_TEXTURE_H__
+
diff --git a/dali/internal/render/gl-resources/gl-call-debug.cpp b/dali/internal/render/gl-resources/gl-call-debug.cpp
new file mode 100644 (file)
index 0000000..3e06c16
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include <dali/internal/render/gl-resources/gl-call-debug.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/integration-api/gl-defines.h>
+
+namespace
+{
+/**
+ * GL error strings
+ */
+struct errorStrings
+{
+  const Dali::GLenum errorCode;
+  const char* errorString;
+};
+errorStrings errors[] =
+{
+   { GL_NO_ERROR,           "GL_NO_ERROR" },
+   { GL_INVALID_ENUM,       "GL_INVALID_ENUM" },
+   { GL_INVALID_VALUE,      "GL_INVALID_VALUE" },
+   { GL_INVALID_OPERATION,  "GL_INVALID_OPERATION" },
+   { GL_OUT_OF_MEMORY,      "GL_OUT_OF_MEMORY" }
+};
+
+const char* ErrorToString( Dali::GLenum errorCode )
+{
+  for( unsigned int i = 0; i < sizeof(errors) / sizeof(errors[0]); ++i)
+  {
+    if (errorCode == errors[i].errorCode)
+    {
+      return errors[i].errorString;
+    }
+  }
+  return "Unknown Open GLES error";
+}
+
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+#ifdef DEBUG_ENABLED
+/// Switch debug level to Concise to disable, General to enable. Note, enabling snapshot logging will do this on the fly.
+Debug::Filter* gGlLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_CONTEXT");
+#endif // DEBUG_ENABLED
+
+void CheckGlError( Integration::GlAbstraction& glAbstraction, const char* operation )
+{
+  for( GLint error = glAbstraction.GetError(); error; error = glAbstraction.GetError() )
+  {
+    DALI_LOG_ERROR( "glError (0x%x) %s - after %s\n",  error, ErrorToString(error), operation );
+    DALI_ASSERT_ALWAYS( !error && "GL ERROR"); // if errors are being checked we should assert
+  }
+}
+
+}
+
+}
diff --git a/dali/internal/render/gl-resources/gl-call-debug.h b/dali/internal/render/gl-resources/gl-call-debug.h
new file mode 100644 (file)
index 0000000..402a759
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef __DALI_INTERNAL_GL_CALL_DEBUG_H__
+#define __DALI_INTERNAL_GL_CALL_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Integration
+{
+class GlAbstraction;
+}
+
+namespace Internal
+{
+
+/**
+ * Helper to check GL errors
+ * @param glAbstraction to use for error check
+ * @param operation to be logged
+ */
+void CheckGlError( Integration::GlAbstraction& glAbstraction, const char* operation );
+
+// wrap gl calls with CHECK_GL e.g. "CHECK_GL( mGlAbstraction, mGlAbstraction.UseProgram(mProgramId) );"
+// will LOG any glErrors eg "glError (0x0501) GL_INVALID_VALUE - glBindTexture(textureId)"
+// only enable if specifically enabled as it can slow down GL a lot!
+#ifdef DALI_GL_ERROR_CHECK
+#define CHECK_GL(c,a)  (a); CheckGlError(c,#a)
+#else
+#define CHECK_GL(c,a)  (a)
+#endif
+
+#ifdef DEBUG_ENABLED
+/// Switch debug level to Concise to disable, General to enable. Note, enabling snapshot logging will do this on the fly.
+extern Debug::Filter* gGlLogFilter;
+#endif // DEBUG_ENABLED
+
+// Don't put guards around here (LOG_INFO has it's own guards)
+#define LOG_GL(format, args...) \
+  DALI_LOG_INFO(gGlLogFilter, Debug::General, format, ## args)
+
+}
+
+}
+
+#endif // __DALI_INTERNAL_GL_CALL_DEBUG_H__
+
diff --git a/dali/internal/render/gl-resources/gl-resource-owner.h b/dali/internal/render/gl-resources/gl-resource-owner.h
new file mode 100644 (file)
index 0000000..59cef51
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef __DALI_INTERNAL_GL_RESOURCE_OWNER_H__
+#define __DALI_INTERNAL_GL_RESOURCE_OWNER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Abstract interface for objects which own GL resources.
+ * These objects must release their GL resources in the render-thread.
+ */
+class GlResourceOwner
+{
+public:
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~GlResourceOwner()
+  { }
+
+  /**
+   * Reset all GL resources.
+   * This method is called when context is or has been deleted.
+   * Context cannot be called from this method.
+   * @pre This method can only be called from the render-thread.
+   */
+  virtual void GlContextDestroyed() = 0;
+
+  /**
+   * Release all GL resources.
+   * This means releasing buffer objects, textures. etc
+   * Context can be used, unless GlContextDestroyed has been called
+   * @pre This method can only be called from the render-thread.
+   */
+  virtual void GlCleanup() = 0;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_GL_RESOURCE_OWNER_H__
diff --git a/dali/internal/render/gl-resources/gpu-buffer.cpp b/dali/internal/render/gl-resources/gpu-buffer.cpp
new file mode 100644 (file)
index 0000000..f7bcad5
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+/**
+ * Helper to get our type enum as GL enum
+ * @param type to convert
+ * @return the corresponding GL enum or -1
+ */
+inline GLenum TypeAsGlEnum( GpuBuffer::Target type )
+{
+  GLenum retval( -1 );
+  switch( type )
+  {
+    case GpuBuffer::ARRAY_BUFFER :
+    {
+      retval = GL_ARRAY_BUFFER;
+      break;
+    }
+    case GpuBuffer::ELEMENT_ARRAY_BUFFER :
+    {
+      retval = GL_ELEMENT_ARRAY_BUFFER;
+      break;
+    }
+    case GpuBuffer::TRANSFORM_FEEDBACK_BUFFER :
+    {
+      retval = GL_TRANSFORM_FEEDBACK_BUFFER;
+      break;
+    }
+  }
+  return retval;
+}
+
+/**
+ * Helper to get our drawmode enum as GL enum
+ * @param type to convert
+ * @return the corresponding GL enum or -1
+ */
+inline GLenum ModeAsGlEnum( GpuBuffer::Usage type )
+{
+  GLenum retval( -1 );
+  switch( type )
+  {
+    case GpuBuffer::STREAM_DRAW :
+    {
+      retval = GL_STREAM_DRAW;
+      break;
+    }
+    case GpuBuffer::STATIC_DRAW :
+    {
+      retval = GL_STATIC_DRAW;
+      break;
+    }
+    case GpuBuffer::DYNAMIC_DRAW :
+    {
+      retval = GL_DYNAMIC_DRAW;
+      break;
+    }
+  }
+  return retval;
+}
+
+}
+
+GpuBuffer::GpuBuffer( Context& context, Target target, Usage usage )
+: mContext( context ),
+  mCapacity( 0 ),
+  mSize( 0 ),
+  mBufferId( 0 ),
+  mTarget( target ),
+  mUsage( usage ),
+  mBufferCreated( false )
+{
+}
+
+GpuBuffer::~GpuBuffer()
+{
+  // If we have a buffer then delete it.
+  if (mBufferId)
+  {
+    // If a buffer object that is currently bound is deleted, the binding reverts to 0
+    // (the absence of any buffer object, which reverts to client memory usage)
+    mContext.DeleteBuffers(1,&mBufferId);
+  }
+}
+
+/*
+ * Creates or updates the buffer data depending on whether it
+ * already exists or not.
+ */
+void GpuBuffer::UpdateDataBuffer(GLsizeiptr size,const GLvoid *data)
+{
+  DALI_ASSERT_DEBUG( size > 0 );
+  mSize = size;
+  // make sure we have a buffer name/id before uploading
+  if (mBufferId == 0)
+  {
+    mContext.GenBuffers(1,&mBufferId);
+    DALI_ASSERT_DEBUG(mBufferId);
+  }
+
+  // make sure the buffer is bound, don't perform any checks because size may be zero
+  BindNoChecks(mBufferId);
+
+  // if the buffer has already been created, just update the data providing it fits
+  if (mBufferCreated )
+  {
+    // if the data will fit in the existing buffer, just update it
+    if (size <= mCapacity )
+    {
+      mContext.BufferSubData( TypeAsGlEnum(mTarget), 0, size, data );
+    }
+    else
+    {
+      // create a new buffer of the larger size,
+      // gl should automatically deallocate the old buffer
+      mContext.BufferData( TypeAsGlEnum(mTarget), size, data, ModeAsGlEnum( mUsage ) );
+      mCapacity = size;
+    }
+  }
+  else
+  {
+    // create the buffer
+    mContext.BufferData( TypeAsGlEnum(mTarget), size, data, ModeAsGlEnum( mUsage ) );
+    mBufferCreated = true;
+    mCapacity = size;
+  }
+
+  switch (mTarget)
+  {
+    case ARRAY_BUFFER:
+    {
+      mContext.BindArrayBuffer(0);
+      break;
+    }
+    case ELEMENT_ARRAY_BUFFER:
+    {
+      mContext.BindElementArrayBuffer(0);
+      break;
+    }
+    case TRANSFORM_FEEDBACK_BUFFER:
+    {
+      mContext.BindTransformFeedbackBuffer(0);
+      break;
+    }
+  }
+}
+
+void GpuBuffer::Bind() const
+{
+  DALI_ASSERT_DEBUG(mCapacity);
+
+  BindNoChecks(mBufferId);
+}
+
+bool GpuBuffer::BufferIsValid() const
+{
+  return mBufferCreated && (0 != mCapacity );
+}
+
+void GpuBuffer::GlContextDestroyed()
+{
+  // If the context is destroyed, GL would have released the buffer.
+  mCapacity = 0;
+  mSize = 0;
+  mBufferId = 0;
+  mBufferCreated = false;
+}
+
+void GpuBuffer::BindNoChecks(GLuint bufferId) const
+{
+  // context currently only supports two targets, element and array
+  // and it caches both of them (as in it won't bind them if the
+  // buffer id is already bound).
+
+  if (mTarget == ARRAY_BUFFER)
+  {
+    mContext.BindArrayBuffer(bufferId);
+  }
+  else
+  {
+    mContext.BindElementArrayBuffer(bufferId);
+  }
+}
+
+
+} // namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/gpu-buffer.h b/dali/internal/render/gl-resources/gpu-buffer.h
new file mode 100644 (file)
index 0000000..04b24f4
--- /dev/null
@@ -0,0 +1,148 @@
+#ifndef __DALI_INTERNAL_GPU_BUFFER_H__
+#define __DALI_INTERNAL_GPU_BUFFER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/context.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Used to create and update a GPU memory buffer.
+ *
+ * The buffer can be used for storing vertex data, index arrays (indices)
+ * or pixel data (PBO).
+ *
+ * The buffer allows data to be stored in high-performance
+ * graphics memory on the server side and
+ * promotes efficient data transfer.
+ */
+class GpuBuffer
+{
+public:
+
+  /**
+   * Enum to encapsulate the GL buffer type. This is to avoid having to store a whole int for type
+   */
+  enum Target
+  {
+    ARRAY_BUFFER,             ///< GL_ARRAY_BUFFER
+    ELEMENT_ARRAY_BUFFER,     ///< GL_ELEMENT_ARRAY_BUFFER
+    TRANSFORM_FEEDBACK_BUFFER ///< GL_TRANSFORM_FEEDBACK_BUFFER
+  };
+
+  /**
+   * Enum to encapsulate the GL draw mode. This is to avoid having to store a whole int for mode
+   */
+  enum Usage
+  {
+    STREAM_DRAW,  ///< GL_STREAM_DRAW
+    STATIC_DRAW,  ///< GL_STATIC_DRAW
+    DYNAMIC_DRAW, ///< GL_DYNAMIC_DRAW
+  };
+
+public:
+
+  /**
+   * constructor
+   * @param context drawing context
+   * @param target the type of buffer to create @see Type
+   * @param usage how the buffer will be used @see DrawMode
+   */
+  GpuBuffer( Context& context, Target target, Usage usage );
+
+  /**
+   * Destructor, non virtual as no virtual methods or inheritance
+   */
+  ~GpuBuffer();
+
+  /**
+   *
+   * Creates or updates a buffer object and binds it to the target.
+   * @param size Specifies the size in bytes of the buffer object's new data store.
+   * @param data pointer to the data to load
+   */
+  void UpdateDataBuffer(GLsizeiptr size, const GLvoid *data);
+
+  /**
+   * Bind the buffer object to the target
+   * Will assert if the buffer size is zero
+   */
+  void Bind() const;
+
+  /**
+   * @return true if the GPU buffer is valid, i.e. its created and not empty
+   */
+  bool BufferIsValid() const;
+
+  /**
+   * Get the size of the buffer
+   * @return size
+   */
+  GLsizeiptr GetBufferSize() const
+  {
+    return mSize;
+  }
+
+  void SetStride( GLuint stride )
+  {
+    mStride = stride;
+  }
+
+  GLuint GetStride()
+  {
+    return mStride;
+  }
+
+  /**
+   * Needs to be called when GL context is destroyed
+   */
+  void GlContextDestroyed();
+
+private:
+
+  /**
+   * Perfoms a bind without checking the size of the buffer
+   * @param bufferId to bind
+   */
+  void BindNoChecks(GLuint bufferId) const;
+
+private: // Data
+
+  Context&           mContext;             ///< dali drawing context
+  GLsizeiptr         mCapacity;            ///< buffer capacity
+  GLsizeiptr         mSize;                ///< buffer size
+  GLuint             mBufferId;            ///< buffer object name(id)
+  GLuint             mStride;              ///< stride of data in buffer object
+
+  Target             mTarget:2;            ///< type of buffer (array/element), 2 bits are enough
+  Usage              mUsage:2;             ///< how the buffer is used (read, read/write etc), 2 bits are enough
+  bool               mBufferCreated:1;     ///< whether buffer has been created
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_GPU_BUFFER_H__
diff --git a/dali/internal/render/gl-resources/native-frame-buffer-texture.cpp b/dali/internal/render/gl-resources/native-frame-buffer-texture.cpp
new file mode 100644 (file)
index 0000000..7899963
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/native-frame-buffer-texture.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+NativeFrameBufferTexture::NativeFrameBufferTexture( NativeImageInterfacePtr nativeImage, Context& context)
+  : FrameBufferTexture(nativeImage->GetWidth(),
+                       nativeImage->GetHeight(),
+                       context),
+    mNativeImage(nativeImage)
+{
+  DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "NativeFrameBufferTexture created 0x%x\n", &nativeImage );
+}
+
+NativeFrameBufferTexture::~NativeFrameBufferTexture()
+{
+  DALI_LOG_INFO (Debug::Filter::gImage, Debug::General, "NativeFrameBufferTexture destroyed\n");
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+bool NativeFrameBufferTexture::IsFullyOpaque() const
+{
+  return !HasAlphaChannel();
+}
+
+bool NativeFrameBufferTexture::HasAlphaChannel() const
+{
+  return mNativeImage->RequiresBlending();
+}
+
+bool NativeFrameBufferTexture::Init()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  bool status( true ); // assume success
+  if( mFrameBufferName == 0 )
+  {
+    status = CreateGlTexture();
+  }
+
+  return status;
+}
+
+bool NativeFrameBufferTexture::CreateGlTexture()
+{
+  DALI_LOG_TRACE_METHOD(Debug::Filter::gImage);
+
+  if( mNativeImage->GlExtensionCreate() )
+  {
+    mContext.GenTextures(1, &mId);
+    mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );  // bind in unused unit so rebind works the first time
+    mContext.Bind2dTexture(mId);
+
+    mContext.PixelStorei(GL_UNPACK_ALIGNMENT, 1); // We always use tightly packed data
+
+    mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    mContext.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+    // platform specific implementation decides on what GL extension to use
+    mNativeImage->TargetTexture();
+
+    // generate frame and render buffer names
+    mContext.GenFramebuffers(1, &mFrameBufferName);
+    mContext.GenRenderbuffers(1, &mRenderBufferName);
+
+    // Bind render buffer and create 16 depth buffer
+    mContext.BindRenderbuffer(GL_RENDERBUFFER, mRenderBufferName);
+    mContext.RenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, mWidth, mHeight);
+  }
+  else
+  {
+    DALI_LOG_ERROR( "Error creating native image!" );
+  }
+
+  return mId != 0;
+}
+
+void NativeFrameBufferTexture::GlCleanup()
+{
+  Texture::GlCleanup();
+
+  if (mFrameBufferName != 0)
+  {
+    mContext.DeleteFramebuffers(1, &mFrameBufferName );
+    mFrameBufferName = 0;
+  }
+
+  if (mRenderBufferName != 0)
+  {
+    mContext.DeleteRenderbuffers(1, &mRenderBufferName );
+    mRenderBufferName = 0;
+  }
+
+  mNativeImage->GlExtensionDestroy();
+
+  mNativeImage.Reset();
+}
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/native-frame-buffer-texture.h b/dali/internal/render/gl-resources/native-frame-buffer-texture.h
new file mode 100644 (file)
index 0000000..0d7cee6
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_FRAME_BUFFER_NATIVE_IMAGE_TEXTURE_H__
+#define __DALI_INTERNAL_FRAME_BUFFER_NATIVE_IMAGE_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/frame-buffer-texture.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * Frame Buffer Texture created from NativeImage.
+ * Used as a frame buffer for RenderTask
+ */
+class NativeFrameBufferTexture : public FrameBufferTexture
+{
+public:
+  /**
+   * Creates a new texture object
+   * @param[in] nativeImage The NativeImage
+   * @param     context The GL context
+   */
+  NativeFrameBufferTexture( NativeImageInterfacePtr nativeImage, Context& context);
+
+  /**
+   * Destructor.
+   */
+  virtual ~NativeFrameBufferTexture();
+
+  /**
+   * @copydoc Texture::IsFullyOpaque
+   */
+  virtual bool IsFullyOpaque() const;
+
+  /**
+   * @copydoc Texture::HasAlphaChannel
+   */
+  virtual bool HasAlphaChannel() const;
+
+  /**
+   * @copydoc Texture::Init
+   */
+  virtual bool Init();
+
+protected:
+  /**
+   * @copydoc Texture::CreateGlTexture
+   */
+  virtual bool CreateGlTexture();
+
+  /**
+   * @copydoc Texture::GlCleanup
+   */
+  virtual void GlCleanup();
+
+private:
+  NativeImageInterfacePtr mNativeImage; ///< reference to NativeImage the Texture was created from
+
+}; // class NativeFrameBufferTexture
+
+}  //namespace Internal
+
+} //namespace Dali
+
+#endif // header
+
diff --git a/dali/internal/render/gl-resources/native-texture.cpp b/dali/internal/render/gl-resources/native-texture.cpp
new file mode 100644 (file)
index 0000000..4ec358d
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/native-texture.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+NativeTexture::NativeTexture(NativeImageInterface* nativeImg, Context& context)
+: Texture(context,
+          nativeImg->GetWidth(),
+          nativeImg->GetHeight(),
+          nativeImg->GetWidth(),
+          nativeImg->GetHeight()),
+          mNativeImage(nativeImg)
+{
+  mYInverted = context.IsPixmapYInverted();
+
+  DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "NativeTexture created 0x%x\n", &nativeImg );
+}
+
+NativeTexture::~NativeTexture()
+{
+  DALI_LOG_INFO (Debug::Filter::gImage, Debug::General, "NativeTexture destroyed\n");
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+bool NativeTexture::Bind(GLenum target, TextureUnit textureunit )
+{
+  bool created = false;
+
+  if( mId==0 )
+  {
+    CreateGlTexture();
+    created = true;
+  }
+
+  // Bind the texture id
+  mContext.ActiveTexture( textureunit );
+  mContext.Bind2dTexture( mId );
+
+  mNativeImage->PrepareTexture();
+
+  return created;
+}
+
+bool NativeTexture::IsFullyOpaque() const
+{
+  return !HasAlphaChannel();
+}
+
+bool NativeTexture::HasAlphaChannel() const
+{
+  return mNativeImage->RequiresBlending();
+}
+
+bool NativeTexture::CreateGlTexture()
+{
+  if ( mId != 0 )
+  {
+    DALI_LOG_INFO( Debug::Filter::gImage, Debug::General, "GL texture creation duplicate for GL id: %d\n", &mId );
+    return true;
+  }
+
+  if( mNativeImage->GlExtensionCreate() )
+  {
+    mContext.GenTextures( 1, &mId );
+    mContext.ActiveTexture( TEXTURE_UNIT_UPLOAD );  // bind in unused unit so rebind works the first time
+    mContext.Bind2dTexture( mId );
+
+    mContext.PixelStorei( GL_UNPACK_ALIGNMENT, 1 ); // We always use tightly packed data
+
+    mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
+    mContext.TexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
+
+    // platform specific implementation decides on what GL extension to use
+    mNativeImage->TargetTexture();
+  }
+  else
+  {
+    DALI_LOG_ERROR( "Error creating native image!" );
+  }
+
+  return mId != 0;
+}
+
+void NativeTexture::GlCleanup()
+{
+  Texture::GlCleanup();
+
+  DALI_ASSERT_DEBUG( mNativeImage );
+
+  mNativeImage->GlExtensionDestroy();
+  mNativeImage.Reset();
+}
+
+bool NativeTexture::Init()
+{
+  return true;
+}
+
+} //namespace Internal
+
+} //namespace Dali
diff --git a/dali/internal/render/gl-resources/native-texture.h b/dali/internal/render/gl-resources/native-texture.h
new file mode 100644 (file)
index 0000000..0076934
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef __DALI_INTERNAL_NATIVE_TEXTURE_H__
+#define __DALI_INTERNAL_NATIVE_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-defines.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/internal/render/gl-resources/texture.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Texture;
+
+/**
+ *
+ * Native texture class.
+ * Used for handing already loaded image data to Dali.
+ *
+ */
+class NativeTexture : public Texture
+{
+public:
+  /**
+   * Constructor.
+   * @pre nativeImg has to be initialized. (GLTexture is already created)
+   * @param nativeImg         the NativeImage to be used
+   * @param context           the GL context
+   */
+  NativeTexture(NativeImageInterface* nativeImg, Context& context);
+
+  /**
+   * Destructor.
+   */
+  virtual ~NativeTexture();
+
+  /**
+   * @copydoc Texture::Bind
+   */
+  virtual bool Bind( GLenum target, TextureUnit textureunit );
+
+  /**
+   * @copydoc Texture::IsFullyOpaque
+   */
+  virtual bool IsFullyOpaque() const;
+
+  /**
+   * @copydoc Texture::HasAlphaChannel
+   */
+  virtual bool HasAlphaChannel() const;
+
+  /**
+   * @copydoc Texture::Init
+   */
+  virtual bool Init();
+
+protected:
+  /**
+   * @copydoc Texture::CreateGlTexture
+   */
+  virtual bool CreateGlTexture();
+
+  /**
+   * @copydoc Texture::GlCleanup
+   */
+  virtual void GlCleanup();
+
+
+private:
+
+  NativeImageInterfacePtr mNativeImage; ///< reference to NativeImage the Texture was created from
+};
+
+}  //namespace Internal
+
+}  //namespace Dali
+
+#endif //__DALI_INTERNAL_NATIVE_TEXTURE_H__
diff --git a/dali/internal/render/gl-resources/texture-cache.cpp b/dali/internal/render/gl-resources/texture-cache.cpp
new file mode 100644 (file)
index 0000000..d11fac0
--- /dev/null
@@ -0,0 +1,607 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/render/gl-resources/texture-cache.h>
+
+#include <dali/integration-api/bitmap.h>
+
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/common/post-process-resource-dispatcher.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-factory.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-observer.h>
+#include <dali/internal/render/gl-resources/bitmap-texture.h>
+#include <dali/internal/render/gl-resources/native-texture.h>
+#include <dali/internal/render/gl-resources/frame-buffer-texture.h>
+
+#include <dali/integration-api/debug.h>
+
+using Dali::Internal::Texture;
+using Dali::Internal::FrameBufferTexture;
+using Dali::Integration::Bitmap;
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gTextureCacheFilter = Debug::Filter::New(Debug::Concise, false, "LOG_TEXTURE_CACHE");
+#endif
+}
+
+
+namespace Dali
+{
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< Pixel::Format > : public BasicType< Pixel::Format > {};
+template <> struct ParameterType< RenderBuffer::Format > : public BasicType< RenderBuffer::Format > {};
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+/**
+ * @brief Forward to all textures in container the news that the GL Context is down.
+ */
+void GlContextDestroyed( TextureContainer& textures )
+{
+  TextureIter end = textures.end();
+  TextureIter iter = textures.begin();
+  for( ; iter != end; ++iter )
+  {
+    (*iter->second).GlContextDestroyed();
+  }
+}
+
+}
+
+TextureCache::TextureCache( RenderQueue& renderQueue,
+                            PostProcessResourceDispatcher& postProcessResourceDispatcher,
+                            Context& context)
+: TextureCacheDispatcher(renderQueue),
+  mPostProcessResourceDispatcher(postProcessResourceDispatcher),
+  mContext(context),
+  mDiscardBitmapsPolicy(ResourcePolicy::OWNED_DISCARD)
+{
+}
+
+TextureCache::~TextureCache()
+{
+}
+
+void TextureCache::CreateTexture( ResourceId        id,
+                                  unsigned int      width,
+                                  unsigned int      height,
+                                  Pixel::Format     pixelFormat,
+                                  bool              clearPixels )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::CreateTexture(id=%i width:%u height:%u)\n", id, width, height);
+
+  Texture* texture = TextureFactory::NewBitmapTexture(width, height, pixelFormat, clearPixels, mContext, GetDiscardBitmapsPolicy() );
+  mTextures.insert(TexturePair(id, texture));
+}
+
+void TextureCache::AddBitmap(ResourceId id, Integration::BitmapPtr bitmap)
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddBitmap(id=%i Bitmap:%p)\n", id, bitmap.Get());
+
+  Texture* texture = TextureFactory::NewBitmapTexture(bitmap.Get(), mContext, GetDiscardBitmapsPolicy());
+  mTextures.insert(TexturePair(id, texture));
+}
+
+void TextureCache::AddNativeImage(ResourceId id, NativeImageInterfacePtr nativeImage)
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddNativeImage(id=%i NativeImg:%p)\n", id, nativeImage.Get());
+
+  /// TODO - currently a new Texture is created even if we reuse the same NativeImage
+  Texture* texture = TextureFactory::NewNativeImageTexture(*nativeImage, mContext);
+  mTextures.insert(TexturePair(id, texture));
+}
+
+void TextureCache::AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, width, height);
+
+  // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
+  // as soon as possible.
+  Texture* texture = TextureFactory::NewFrameBufferTexture( width, height, pixelFormat, bufferFormat, mContext );
+  mFramebufferTextures.insert(TexturePair(id, texture));
+}
+
+void TextureCache::AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::AddFrameBuffer(id=%i width:%u height:%u)\n", id, nativeImage->GetWidth(), nativeImage->GetHeight());
+
+  // Note: Do not throttle framebuffer generation - a request for a framebuffer should always be honoured
+  // as soon as possible.
+  Texture* texture = TextureFactory::NewFrameBufferTexture( nativeImage, mContext );
+  mFramebufferTextures.insert(TexturePair(id, texture));
+}
+
+void TextureCache::CreateGlTexture( ResourceId id )
+{
+  TextureIter textureIter = mTextures.find(id);
+  // If we found a non-null texture object pointer for the resource id, force it
+  // to eagerly allocate a backing GL texture:
+  if( textureIter != mTextures.end() )
+  {
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->CreateGlTexture();
+    }
+  }
+}
+
+void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
+
+  TextureIter textureIter = mTextures.find(id);
+  if( textureIter != mTextures.end() )
+  {
+    // we have reloaded the image from file, update texture
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->Update( bitmap.Get() );
+
+      ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+      mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+    }
+  }
+}
+
+void TextureCache::UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(id=%i bitmap:%p )\n", id, bitmap.Get());
+
+  TextureIter textureIter = mTextures.find(id);
+  if( textureIter != mTextures.end() )
+  {
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->Update( bitmap.Get(), xOffset, yOffset );
+
+      ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+      mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+    }
+  }
+}
+
+void TextureCache::UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTexture(destId=%i srcId=%i )\n", destId, srcId );
+
+  BitmapTexture* srcTexture = TextureCache::GetBitmapTexture( srcId );
+  Integration::BitmapPtr srcBitmap = ( srcTexture != NULL ) ? srcTexture->GetBitmap() : NULL;
+
+  if( srcBitmap )
+  {
+    UpdateTexture( destId, srcBitmap, xOffset, yOffset );
+  }
+}
+
+void TextureCache::UpdateTextureArea( ResourceId id, const Dali::RectArea& area )
+{
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::UpdateTextureArea(id=%i)\n", id );
+
+  TextureIter textureIter = mTextures.find(id);
+  if( textureIter != mTextures.end() )
+  {
+    TexturePointer texturePtr = textureIter->second;
+    if( texturePtr )
+    {
+      texturePtr->UpdateArea( area );
+
+      ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+      mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+    }
+  }
+}
+
+void TextureCache::DiscardTexture( ResourceId id )
+{
+  bool deleted = false;
+
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::DiscardTexture(id:%u)\n", id);
+
+  if( mTextures.size() > 0)
+  {
+    TextureIter iter = mTextures.find(id);
+    if( iter != mTextures.end() )
+    {
+      TexturePointer texturePtr = iter->second;
+      if( texturePtr )
+      {
+        // if valid texture pointer, cleanup GL resources
+        texturePtr->GlCleanup();
+      }
+      mTextures.erase(iter);
+      deleted = true;
+    }
+  }
+
+  if( mFramebufferTextures.size() > 0)
+  {
+    TextureIter iter = mFramebufferTextures.find(id);
+    if( iter != mFramebufferTextures.end() )
+    {
+      TexturePointer texturePtr = iter->second;
+      if( texturePtr )
+      {
+        // if valid texture pointer, cleanup GL resources
+        texturePtr->GlCleanup();
+      }
+      mFramebufferTextures.erase(iter);
+      deleted = true;
+    }
+  }
+
+  if(deleted)
+  {
+    if( mObservers.size() > 0 )
+    {
+      TextureResourceObserversIter observersIter = mObservers.find(id);
+      if( observersIter != mObservers.end() )
+      {
+        TextureObservers observers = observersIter->second;
+        for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
+        {
+          TextureObserver* observer = *iter;
+          observer->TextureDiscarded( id );
+        }
+
+        mObservers.erase( observersIter );
+      }
+    }
+
+    // Tell resource manager
+    ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::DELETED );
+    mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+  }
+}
+
+void TextureCache::BindTexture( Texture *texture, ResourceId id, GLenum target, TextureUnit textureunit )
+{
+  bool created = texture->Bind(target, textureunit);
+  if( created && texture->UpdateOnCreate() ) // i.e. the pixel data was sent to GL
+  {
+    ResourcePostProcessRequest ppRequest( id, ResourcePostProcessRequest::UPLOADED );
+    mPostProcessResourceDispatcher.DispatchPostProcessRequest(ppRequest);
+  }
+}
+
+Texture* TextureCache::GetTexture(ResourceId id)
+{
+  Texture* texture = NULL;
+  TextureIter iter = mTextures.find(id);
+
+  if( iter != mTextures.end() )
+  {
+    TexturePointer texturePtr = iter->second;
+    if( texturePtr )
+    {
+      texture = texturePtr.Get();
+    }
+  }
+
+  if( texture == NULL )
+  {
+    TextureIter iter = mFramebufferTextures.find(id);
+    if( iter != mFramebufferTextures.end() )
+    {
+      TexturePointer texturePtr = iter->second;
+      if( texturePtr )
+      {
+        texture = texturePtr.Get();
+      }
+    }
+  }
+
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetTexture(id:%u) : %p\n", id, texture);
+
+  return texture;
+}
+
+BitmapTexture* TextureCache::GetBitmapTexture(ResourceId id)
+{
+  BitmapTexture* texture = NULL;
+  TextureIter iter = mTextures.find( id );
+
+  if( iter != mTextures.end() )
+  {
+    TexturePointer texturePtr = iter->second;
+    if( texturePtr )
+    {
+      texture = dynamic_cast< BitmapTexture* >( texturePtr.Get() );
+    }
+  }
+
+  return texture;
+}
+
+FrameBufferTexture* TextureCache::GetFramebuffer(ResourceId id)
+{
+  FrameBufferTexture* offscreen = NULL;
+  TextureIter iter = mFramebufferTextures.find(id);
+
+  DALI_ASSERT_DEBUG( iter != mFramebufferTextures.end() );
+
+  if( iter != mFramebufferTextures.end() )
+  {
+    TexturePointer texturePtr = iter->second;
+    if( texturePtr )
+    {
+      offscreen = dynamic_cast< FrameBufferTexture* >( texturePtr.Get() );
+    }
+  }
+  DALI_ASSERT_DEBUG( offscreen );
+
+  DALI_LOG_INFO(Debug::Filter::gGLResource, Debug::General, "TextureCache::GetFramebuffer(id:%u) : %p\n", id, offscreen);
+
+  return offscreen;
+}
+
+void TextureCache::AddObserver( ResourceId id, TextureObserver* observer )
+{
+  TextureResourceObserversIter observersIter = mObservers.find(id);
+  if( observersIter != mObservers.end() )
+  {
+    TextureObservers& observers = observersIter->second;
+    bool foundObserver = false;
+    for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
+    {
+      if( *iter == observer )
+      {
+        foundObserver = true;
+        break;
+      }
+    }
+    if( ! foundObserver )
+    {
+      observers.push_back(observer);
+    }
+  }
+  else
+  {
+    TextureObservers observers;
+    observers.push_back(observer);
+    mObservers.insert(std::pair<ResourceId, TextureObservers>(id, observers));
+  }
+}
+
+void TextureCache::RemoveObserver( ResourceId id, TextureObserver* observer )
+{
+  TextureResourceObserversIter observersIter = mObservers.find(id);
+  if( observersIter != mObservers.end() )
+  {
+    TextureObservers& observers = observersIter->second;
+    for( TextureObserversIter iter = observers.begin(); iter != observers.end(); ++iter )
+    {
+      if(*iter == observer)
+      {
+        observers.erase(iter);
+        break;
+      }
+    }
+  }
+}
+
+void TextureCache::GlContextDestroyed()
+{
+  SceneGraph::GlContextDestroyed( mTextures );
+  SceneGraph::GlContextDestroyed( mFramebufferTextures );
+}
+
+void TextureCache::SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy )
+{
+  DALI_LOG_INFO( gTextureCacheFilter, Debug::General, "TextureCache::SetDiscardBitmapsPolicy(%s)\n",
+                 policy==ResourcePolicy::OWNED_DISCARD?"DISCARD":"RETAIN" );
+  mDiscardBitmapsPolicy = policy;
+}
+
+ResourcePolicy::Discardable TextureCache::GetDiscardBitmapsPolicy()
+{
+  return mDiscardBitmapsPolicy;
+}
+
+
+/********************************************************************************
+ **********************  Implements TextureCacheDispatcher  *********************
+ ********************************************************************************/
+
+void TextureCache::DispatchCreateTexture( ResourceId        id,
+                                          unsigned int      width,
+                                          unsigned int      height,
+                                          Pixel::Format     pixelFormat,
+                                          bool              clearPixels )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, bool > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::CreateTexture, id, width, height, pixelFormat, clearPixels );
+  }
+}
+
+void TextureCache::DispatchCreateTextureForBitmap( ResourceId id, Bitmap* bitmap )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::AddBitmap, id, bitmap );
+  }
+}
+
+void TextureCache::DispatchCreateTextureForNativeImage( ResourceId id, NativeImageInterfacePtr nativeImage )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue2< TextureCache, ResourceId, NativeImageInterfacePtr > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::AddNativeImage, id, nativeImage );
+  }
+}
+
+void TextureCache::DispatchCreateGlTexture( ResourceId id )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue1< TextureCache, ResourceId > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::CreateGlTexture, id );
+  }
+}
+
+void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue5< TextureCache, ResourceId, unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, width, height, pixelFormat, bufferFormat );
+  }
+}
+
+void TextureCache::DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue2< TextureCache, ResourceId, NativeImageInterfacePtr > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::AddFrameBuffer, id, nativeImage );
+  }
+}
+
+void TextureCache::DispatchUpdateTexture( ResourceId id, Bitmap* bitmap )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue2< TextureCache, ResourceId, Integration::BitmapPtr > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap );
+  }
+}
+
+void TextureCache::DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap , std::size_t xOffset, std::size_t yOffset)
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue4< TextureCache, ResourceId, Integration::BitmapPtr, std::size_t, std::size_t > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTexture, id, bitmap, xOffset, yOffset );
+  }
+}
+
+void TextureCache::DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue4< TextureCache, ResourceId, ResourceId, std::size_t, std::size_t > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTexture, destId, srcId, xOffset, yOffset );
+  }
+}
+
+void TextureCache::DispatchUpdateTextureArea( ResourceId id, const Dali::RectArea& area )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue2< TextureCache, ResourceId, Dali::RectArea > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::UpdateTextureArea, id, area );
+  }
+}
+
+void TextureCache::DispatchDiscardTexture( ResourceId id )
+{
+  // NULL, means being shutdown, so ignore msgs
+  if( mSceneGraphBuffers != NULL )
+  {
+    typedef MessageValue1< TextureCache, ResourceId > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mRenderQueue.ReserveMessageSlot( mSceneGraphBuffers->GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( this, &TextureCache::DiscardTexture, id );
+  }
+}
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/render/gl-resources/texture-cache.h b/dali/internal/render/gl-resources/texture-cache.h
new file mode 100644 (file)
index 0000000..3165359
--- /dev/null
@@ -0,0 +1,332 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_TEXTURE_CACHE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_TEXTURE_CACHE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/images/native-image.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/resource-policies.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/render/common/texture-cache-dispatcher.h>
+#include <dali/internal/render/gl-resources/texture-declarations.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+
+namespace Dali
+{
+class NativeImageInterface;
+
+
+namespace Integration
+{
+class Bitmap;
+typedef IntrusivePtr<Bitmap>   BitmapPtr;
+}
+
+
+namespace Internal
+{
+class Context;
+class Texture;
+class BitmapTexture;
+class FrameBufferTexture;
+class TextureObserver;
+
+namespace SceneGraph
+{
+class RenderQueue;
+class PostProcessResourceDispatcher;
+
+typedef std::map<ResourceId, TexturePointer >   TextureContainer;
+typedef std::pair<ResourceId, TexturePointer >  TexturePair;
+typedef TextureContainer::iterator              TextureIter;
+typedef TextureContainer::const_iterator        TextureConstIter;
+
+/**
+ * Caches textures. Owned by Render Thread
+ */
+class TextureCache : public TextureCacheDispatcher
+{
+public:
+ /**
+   * Constructor
+   * @param[in] renderQueue Queue to use for dispatching messages to this object
+   * @param[in] postProcessDispatcher Dispatcher for resource post processing requests
+   * @param[in] context GL Context
+   */
+  TextureCache( RenderQueue& renderQueue,
+                PostProcessResourceDispatcher& postProcessDispatcher,
+                Context& context );
+
+  /**
+   * Destructor
+   */
+  ~TextureCache();
+
+  /**
+   * Creates a new empty texture object with the given dimensions.
+   * @param[in] width       The width (pixels)
+   * @param[in] height      The height (pixels)
+   * @param[in] pixelFormat The pixel format
+   * @param[in] clearPixels True if the pixel data should be cleared first
+   */
+  void CreateTexture( ResourceId        id,
+                      unsigned int      width,
+                      unsigned int      height,
+                      Pixel::Format     pixelFormat,
+                      bool              clearPixels );
+
+  /**
+   * Add a bitmap to the texture cache
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] bitmap The bitmap
+   */
+  void AddBitmap( ResourceId id, Integration::BitmapPtr bitmap );
+
+  /**
+   * Add a native image to the texture cache
+   * @param[in] id Resource Id of the native image
+   * @param[in] nativeImage The native image
+   */
+  void AddNativeImage( ResourceId id, NativeImageInterfacePtr nativeImage );
+
+  /**
+   * Create a framebuffer texture and add it to the texture cache
+   * @param[in] id Resource Id of the native image
+   * @param[in] width Width of the framebuffer
+   * @param[in] height Height of the framebuffer
+   * @param[in] pixelFormat Pixel format of the framebuffer
+   * @param[in] bufferFormat Renderbuffer format of the framebuffer
+   */
+  void AddFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat );
+
+  /**
+   * Create a framebuffer texture and add it to the texture cache
+   * @param[in] id Resource Id of the native image
+   * @param[in] nativeImage The NativeImage
+   */
+  void AddFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage );
+
+  /**
+   * Create GL texture eagerly right now instead of waiting for first use.
+   * @param[in] id The resource id corresponding to the texture.
+   */
+  void CreateGlTexture( ResourceId id );
+
+  /**
+   * Update the texture with a newly loaded bitmap
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] bitmap The bitmap
+   */
+  void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap );
+
+  /**
+   * Update the texture with a newly loaded bitmap
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] bitmap The bitmap
+   * @param[in] xOffset Specifies an offset in the x direction within the texture
+   * @param[in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Update the part of a texture with a newly loaded bitmap
+   * May be called from Update thread
+   * @param[in] destId The ID of the texture to update
+   * @param[in] srcId The resource ID of the source bitmap
+   * @param[in] xOffset Specifies an offset in the x direction within the texture
+   * @param[in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void UpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Update the area of the texture from the associated bitmap
+   * @param[in] id Resource Id of the bitmap
+   * @param[in] area The area of the bitmap that has changed
+   */
+  void UpdateTextureArea( ResourceId id, const RectArea& area );
+
+  /**
+   * Discard texture associated with resource ID
+   * @param[in] id Resource Id of the texture
+   */
+  void DiscardTexture( ResourceId id );
+
+  /**
+   * Bind a texture. On the first call, the texture will copy it's
+   * pixel data to an OpenGL texture.  If it's a BitmapTexture, then
+   * it will also trigger SignalUpdated to be sent on the event thread
+   * object.
+   *
+   * @param[in] texture pointer to the  texture
+   * @param[in] id Resource id of texture
+   * @param[in] target (e.g. GL_TEXTURE_2D)
+   * @param[in] textureunit to use
+   */
+  void BindTexture( Texture* texture, ResourceId id, GLenum target, TextureUnit textureunit );
+
+  /**
+   * Get the texture associated with the resource ID
+   * May be a texture or a framebuffer
+   * @param[in] id Resource Id of the texture
+   * @return NULL if the GL resource hasn't yet been created,
+   * or a valid pointer if it has.
+   */
+  Texture* GetTexture( ResourceId id );
+
+  /**
+   * Get the bitmaptexture associated with the resource ID
+   * @param[in] id Resource Id of the texture
+   * @return The texture or NULL
+   */
+  BitmapTexture* GetBitmapTexture(ResourceId id);
+
+  /**
+   * Get the framebuffer texture associated with the resource ID
+   * Used for writing to the framebuffer
+   * @param[in] id Resource Id of the framebuffer
+   * @return the framebuffer
+   */
+  FrameBufferTexture* GetFramebuffer(ResourceId id);
+
+  /**
+   * Add a texture observer. Should be called in render thread
+   * @param[in] id The resource id to watch
+   * @param[in] observer The observer to add
+   */
+  void AddObserver( ResourceId id, TextureObserver* observer );
+
+  /**
+   * Remove a texture observer. Should be called in render thread
+   * @param[in] id The resource id to stop watching
+   * @param[in] observer The observer to remove
+   */
+  void RemoveObserver( ResourceId id, TextureObserver* observer );
+
+  /**
+   * Reset all textures.
+   * This method is called when context is or has been deleted.
+   */
+  void GlContextDestroyed();
+
+  /**
+   * Set whether textures should retain or discard their bitmaps after upload to GL
+   * @param[in] policy Whether to retain or discard bitmaps
+   */
+  void SetDiscardBitmapsPolicy( ResourcePolicy::Discardable policy );
+
+  /**
+   * Get the discard policy.
+   * @return The discard policy.
+   */
+  ResourcePolicy::Discardable GetDiscardBitmapsPolicy();
+
+protected: // Implements TextureCacheDispatcher
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateTexture()
+   */
+  virtual void DispatchCreateTexture( ResourceId        id,
+                                      unsigned int      width,
+                                      unsigned int      height,
+                                      Pixel::Format     pixelFormat,
+                                      bool              clearPixels );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateTextureForBitmap()
+   */
+  virtual void DispatchCreateTextureForBitmap( ResourceId id, Integration::Bitmap* bitmap );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateTextureForNativeImage()
+   */
+  virtual void DispatchCreateTextureForNativeImage( ResourceId id, NativeImageInterfacePtr nativeImage );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateGlTexture()
+   */
+  virtual void DispatchCreateGlTexture( ResourceId id );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateTextureForFramebuffer()
+   */
+  virtual void DispatchCreateTextureForFrameBuffer( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchCreateTextureForFramebuffer()
+   */
+  virtual void DispatchCreateTextureForFrameBuffer( ResourceId id, NativeImageInterfacePtr nativeImage );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::Bitmap* bitmap );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
+  virtual void DispatchUpdateTexture( ResourceId id, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset ) ;
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTexture()
+   */
+  virtual void DispatchUpdateTexture( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchUpdateTextureArea()
+   */
+  virtual void DispatchUpdateTextureArea( ResourceId id, const RectArea& area );
+
+  /**
+   * @copydoc TextureCacheDispatcher::DispatchDiscardTexture()
+   */
+  virtual void DispatchDiscardTexture( ResourceId id );
+
+private:
+
+  PostProcessResourceDispatcher& mPostProcessResourceDispatcher;
+  Context&         mContext;
+  TextureContainer mTextures;
+  TextureContainer mFramebufferTextures;
+
+  typedef std::vector< TextureObserver* > TextureObservers;
+  typedef TextureObservers::iterator      TextureObserversIter;
+
+  typedef std::map< ResourceId, TextureObservers > TextureResourceObservers;
+  typedef TextureResourceObservers::iterator       TextureResourceObserversIter;
+
+  TextureResourceObservers mObservers;
+  ResourcePolicy::Discardable mDiscardBitmapsPolicy;
+};
+
+
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif //__DALI_INTERNAL_SCENE_GRAPH_TEXTURE_CACHE_H__
diff --git a/dali/internal/render/gl-resources/texture-declarations.h b/dali/internal/render/gl-resources/texture-declarations.h
new file mode 100644 (file)
index 0000000..26e6f56
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __DALI_INTERNAL_TEXTURE_DECLARATIONS_H__
+#define __DALI_INTERNAL_TEXTURE_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Texture;
+typedef IntrusivePtr<Texture> TexturePointer;
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_DECLARATIONS_H__
diff --git a/dali/internal/render/gl-resources/texture-factory.cpp b/dali/internal/render/gl-resources/texture-factory.cpp
new file mode 100644 (file)
index 0000000..7f1da8a
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include "texture-factory.h"
+
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/bitmap-texture.h>
+#include <dali/internal/render/gl-resources/compressed-bitmap-texture.h>
+#include <dali/internal/render/gl-resources/native-texture.h>
+#include <dali/internal/render/gl-resources/frame-buffer-texture.h>
+#include <dali/internal/render/gl-resources/native-frame-buffer-texture.h>
+
+
+namespace Dali
+{
+class NativeImageInterface;
+
+namespace Internal
+{
+
+namespace TextureFactory
+{
+
+Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap, Context& context, ResourcePolicy::Discardable discardPolicy )
+{
+  DALI_ASSERT_DEBUG( bitmap );
+  Texture * texture = 0;
+  Integration::Bitmap::PackedPixelsProfile * const  packedPixelBitmapView = bitmap->GetPackedPixelsProfile();
+  if( packedPixelBitmapView )
+  {
+    texture = new BitmapTexture( bitmap, packedPixelBitmapView, context, discardPolicy );
+  }
+  else
+  {
+    Internal::BitmapCompressed * const compressedBitmap = dynamic_cast<Dali::Internal::BitmapCompressed*>( bitmap );
+    if( compressedBitmap != 0 )
+    {
+      texture = new CompressedBitmapTexture( compressedBitmap, context, discardPolicy );
+    }
+  }
+  if( texture )
+  {
+    if( !texture->Init() )
+    {
+      delete texture;
+      return NULL;
+    }
+  }
+  return texture;
+}
+
+Internal::Texture* NewBitmapTexture( unsigned int      width,
+                                     unsigned int      height,
+                                     Pixel::Format     pixelFormat,
+                                     bool              clearPixels,
+                                     Context&          context,
+                                     ResourcePolicy::Discardable discardPolicy )
+{
+  Texture *texture=new BitmapTexture(width, height, pixelFormat, clearPixels, context, discardPolicy);
+
+  return texture;
+}
+
+
+Internal::Texture* NewNativeImageTexture( NativeImageInterface& nativeImg, Context& context )
+{
+  NativeTexture* texture = new NativeTexture(&nativeImg, context);
+  if (!texture->Init())
+  {
+    delete texture;
+    return NULL;
+  }
+  return texture;
+}
+
+Internal::Texture* NewFrameBufferTexture( unsigned int width,
+                                          unsigned int height,
+                                          Pixel::Format pixelFormat,
+                                          RenderBuffer::Format bufferFormat,
+                                          Context& context )
+{
+  FrameBufferTexture* texture = new FrameBufferTexture(width, height, pixelFormat, bufferFormat, context);
+  if (!texture->Init())
+  {
+    delete texture;
+    return NULL;
+  }
+  return texture;
+}
+
+Internal::Texture* NewFrameBufferTexture( NativeImageInterfacePtr nativeImage,
+                                          Context& context )
+{
+  NativeFrameBufferTexture* texture = new NativeFrameBufferTexture(nativeImage, context);
+  if (!texture->Init())
+  {
+    delete texture;
+    return NULL;
+  }
+  return texture;
+}
+
+
+
+} // TextureFactory
+} // Internal
+} // Dali
diff --git a/dali/internal/render/gl-resources/texture-factory.h b/dali/internal/render/gl-resources/texture-factory.h
new file mode 100644 (file)
index 0000000..a493cde
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef __DALI_INTERNAL_TEXTURE_FACTORY_H__
+#define __DALI_INTERNAL_TEXTURE_FACTORY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+
+namespace Dali
+{
+class NativeImageInterface;
+
+namespace Integration
+{
+class Bitmap;
+}
+
+namespace Internal
+{
+class Context;
+class Texture;
+
+namespace TextureFactory
+{
+/**
+ * Creates a new texture object from a Bitmap
+ * @param[in] bitmap The Bitmap
+ * @param[in] context The GL context
+ * @return A newly allocated texture
+ */
+Internal::Texture* NewBitmapTexture( Integration::Bitmap* const bitmap,
+                                     Context& context,
+                                     ResourcePolicy::Discardable discardPolicy );
+
+/**
+ * Creates a new bitmap texture object of the given dimensions.
+ * @param[in] width       The width (pixels)
+ * @param[in] height      The height (pixels)
+ * @param[in] pixelFormat The pixel format
+ * @param[in] clearPixels True if the pixel data should be cleared first
+ * @param[in] context The GL context
+ */
+Internal::Texture* NewBitmapTexture( unsigned int      width,
+                                     unsigned int      height,
+                                     Pixel::Format     pixelFormat,
+                                     bool              clearPixels,
+                                     Context&          context,
+                                     ResourcePolicy::Discardable discardPolicy );
+
+/**
+ * Creates a texture object from a native image (eg.: EGLImage).
+ * @param[in] nativeImage The native image to load
+ * @param[in] context The GL context
+ * @return A newly allocated texture
+ */
+Internal::Texture* NewNativeImageTexture( NativeImageInterface& nativeImage, Context& context );
+
+/**
+ * @copydoc FrameBufferTexture::FrameBufferTexture
+ * @return A newly allocated texture
+ */
+Internal::Texture* NewFrameBufferTexture( unsigned int width,
+                                          unsigned int height,
+                                          Pixel::Format pixelFormat,
+                                          RenderBuffer::Format bufferFormat,
+                                          Context& context );
+
+/**
+ * @copydoc FrameBufferTexture::FrameBufferTexture
+ * @return A newly allocated texture
+ */
+Internal::Texture* NewFrameBufferTexture( NativeImageInterfacePtr nativeImage, Context& context );
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_FACTORY_H__
diff --git a/dali/internal/render/gl-resources/texture-observer.h b/dali/internal/render/gl-resources/texture-observer.h
new file mode 100644 (file)
index 0000000..0c8d6a9
--- /dev/null
@@ -0,0 +1,48 @@
+#ifndef __DALI_INTERNAL_TEXTURE_OBSERVER_H__
+#define __DALI_INTERNAL_TEXTURE_OBSERVER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Internal
+{
+
+/**
+ * The TextureObserver observes texture lifetime
+ */
+class TextureObserver
+{
+public:
+  /**
+   * Called when a texture is discarded. This occurs in the render thread.
+   * @param[in] textureId The resource id of the discarded texture
+   */
+  virtual void TextureDiscarded( unsigned int textureId ) = 0;
+
+protected:
+  /**
+   * Virtual destructor
+   */
+  virtual ~TextureObserver(){}
+};
+
+}//Internal
+}//Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_OBSERVER_H__
diff --git a/dali/internal/render/gl-resources/texture-units.h b/dali/internal/render/gl-resources/texture-units.h
new file mode 100644 (file)
index 0000000..6b8a44b
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __DALI_INTERNAL_TEXTURE_UNITS_H__
+#define __DALI_INTERNAL_TEXTURE_UNITS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-defines.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+enum TextureUnit
+{
+  TEXTURE_UNIT_IMAGE = 0,
+  TEXTURE_UNIT_TEXT,
+  TEXTURE_UNIT_MATERIAL_DIFFUSE,
+  TEXTURE_UNIT_MATERIAL_OPACITY,
+  TEXTURE_UNIT_MATERIAL_NORMAL_MAP,
+  TEXTURE_UNIT_SHADER,
+  TEXTURE_UNIT_UPLOAD,
+  TEXTURE_UNIT_FRAMEBUFFER,
+  TEXTURE_UNIT_LAST
+};
+
+inline unsigned int TextureUnitAsGLenum( TextureUnit unit )
+{
+  // GL texture units are #defines in growing order to converting that to index
+  return GL_TEXTURE0 + static_cast<unsigned int>( unit );
+}
+
+}//Internal
+
+}//Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_UNITS_H__
diff --git a/dali/internal/render/gl-resources/texture.cpp b/dali/internal/render/gl-resources/texture.cpp
new file mode 100644 (file)
index 0000000..e61090d
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/gl-resources/texture.h>
+
+// EXTERNAL INCLUDES
+#include <math.h>
+#include <memory.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/common/image-sampler.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+// These match the GL specification
+const GLint SYSTEM_MINIFY_DEFAULT  = GL_NEAREST_MIPMAP_LINEAR;
+const GLint SYSTEM_MAGNIFY_DEFAULT = GL_LINEAR;
+
+// These are the Dali defaults
+const GLint DALI_MINIFY_DEFAULT  = GL_LINEAR;
+const GLint DALI_MAGNIFY_DEFAULT = GL_LINEAR;
+
+} // namespace
+
+/**
+ * @brief Convert a FilterMode to it's corresponding GL type.
+ *
+ * @param[in] filterMode The FilterMode type.
+ * @param[in] defaultfilterMode The filter mode to use if filterMode is DEFAULT.
+ * @param[in] defaultSystemFilterMode The filter mode to use if filterMode is NONE.
+ * @return Return the equivalent GL type.
+ */
+GLint FilterModeToGL( FilterMode::Type filterMode, GLint defaultfilterMode, GLint defaultSystemFilterMode )
+{
+  switch( filterMode )
+  {
+    case FilterMode::NEAREST:
+    {
+      return GL_NEAREST;
+    }
+    case FilterMode::LINEAR:
+    {
+      return GL_LINEAR;
+    }
+    case FilterMode::NONE:
+    {
+      return defaultSystemFilterMode;
+    }
+    case FilterMode::DEFAULT:
+    {
+      return defaultfilterMode;
+    }
+  }
+
+  return GL_LINEAR;
+}
+
+using Dali::Internal::Vertex2D;
+using Dali::Internal::Vertex3D;
+
+using namespace Dali::Pixel;
+
+Texture::Texture(Context&      context,
+                 unsigned int  width,
+                 unsigned int  height,
+                 unsigned int  imageWidth,
+                 unsigned int  imageHeight)
+: mContext(context),
+  mId(0),
+  mSamplerBitfield( 0 ),
+  mWidth(width),
+  mHeight(height),
+  mImageWidth(imageWidth),
+  mImageHeight(imageHeight),
+  mYInverted( true )
+{
+}
+
+Texture::~Texture()
+{
+  // GlCleanup() should already have been called by TextureCache ensuring the resource is destroyed
+  // on the render thread. (And avoiding a potentially problematic virtual call in the destructor)
+}
+
+void Texture::SetTextureId(GLuint id)
+{
+  mId=id;
+}
+
+void Texture::Update(Integration::Bitmap* bitmap)
+{
+  DALI_ASSERT_DEBUG( "Updating incorrect texture type" == NULL );
+}
+
+void Texture::UpdateArea( const RectArea& area )
+{
+  DALI_ASSERT_DEBUG( "Updating incorrect texture type" == NULL );
+}
+
+bool Texture::UpdateOnCreate()
+{
+  return false;
+}
+
+bool Texture::Bind(GLenum target, TextureUnit textureunit )
+{
+  // This is the only supported type at the moment
+  DALI_ASSERT_DEBUG( target == GL_TEXTURE_2D );
+  bool created = false;
+
+  if( mId == 0 )
+  {
+    if( CreateGlTexture() )
+    {
+      created = true;
+    }
+  }
+
+  // Bind the texture id
+  mContext.BindTextureForUnit(textureunit, mId );
+
+  return created;
+}
+
+void Texture::GlContextDestroyed()
+{
+  // texture is gone
+  mId = 0;
+  // reset sampler state as well
+  mSamplerBitfield = 0;
+}
+
+void Texture::GlCleanup()
+{
+  // delete the gl texture
+  if (mId != 0)
+  {
+    mContext.DeleteTextures(1,&mId);
+    mId = 0;
+  }
+}
+
+void Texture::MapUV(unsigned int numVerts,Vertex2D *verts, const PixelArea* pixelArea)
+{
+  MapUV(numVerts, (float*)(&verts->mU), sizeof(Vertex2D)/sizeof(float), pixelArea);
+}
+
+void Texture::MapUV(unsigned int numVerts,Vertex3D *verts, const PixelArea* pixelArea)
+{
+  MapUV(numVerts, (float*)(&verts->mU), sizeof(Vertex3D)/sizeof(float), pixelArea);
+}
+
+void Texture::MapUV(unsigned int numVerts, float* verts, unsigned int stride, const PixelArea* pixelArea)
+{
+  UvRect uv;
+
+  GetTextureCoordinates(uv, pixelArea);
+
+  float uScale = fabsf(uv.u2 - uv.u0);
+  float vScale = fabsf(uv.v2 - uv.v0);
+
+  if( mYInverted )
+  {
+    for( unsigned int i = 0; i < numVerts; ++i )
+    {
+      verts[0] = uv.u0 + verts[0] * uScale;
+      verts[1] = uv.v0 + verts[1] * vScale;
+      verts += stride;
+    }
+  }
+  else
+  {
+    for( unsigned int i = 0; i < numVerts; ++i )
+    {
+      verts[0] = uv.u0 + verts[0] * uScale;
+      verts[1] = 1.0f - (uv.v0 + verts[1] * vScale);
+      verts += stride;
+    }
+  }
+}
+
+unsigned int Texture::GetWidth() const
+{
+  return mWidth;
+}
+
+unsigned int Texture::GetHeight() const
+{
+  return mHeight;
+}
+
+void Texture::GetTextureCoordinates(UvRect& uv, const PixelArea* pixelArea)
+{
+  if( pixelArea == NULL )
+  {
+     GetDefaultTextureCoordinates(uv);
+     return;
+  }
+
+  // pre-calulate the normalized values
+
+  const float uScale = 1.0f / float(mWidth);
+  const float vScale = 1.0f / float(mHeight);
+  const float x = uScale * float(pixelArea->x);
+  const float y = vScale * float(pixelArea->y);
+  const float width  = uScale * float(pixelArea->width);
+  const float height = vScale * float(pixelArea->height);
+
+
+  // bottom left
+  uv.u0 = x;
+  uv.v0 = y;
+
+  // top right
+  uv.u2 = x + width;
+  uv.v2 = y + height;
+
+};
+
+void Texture::GetDefaultTextureCoordinates(UvRect& uv) const
+{
+  if ((mWidth == mImageWidth) && (mHeight == mImageHeight))
+  {
+    // set the uv's to display 0,0 to 1,1
+    uv.Reset();
+    return;
+  }
+
+  // the texture co-ordinates go from 0 to 1. But the image is smaller than the
+  // texture, so we need to adjust the uv values.
+  float uScale = float(mImageWidth)  / float(mWidth);
+  float vScale = float(mImageHeight) / float(mHeight);
+
+  // bottom left
+  uv.u0 = 0.0f;
+  uv.v0 = 0.0f;
+
+  // top right
+  uv.u2 = uScale;
+  uv.v2 = vScale;
+
+}
+
+void Texture::ApplyTextureParameter( TextureUnit unit, GLint filterType, FilterMode::Type currentFilterMode, FilterMode::Type newFilterMode, GLint daliDefault, GLint systemDefault )
+{
+  GLint newFilterModeGL = FilterModeToGL( newFilterMode, daliDefault, systemDefault );
+  GLint currentFilterModeGL = FilterModeToGL( currentFilterMode, daliDefault, systemDefault );
+
+  if( newFilterModeGL != currentFilterModeGL )
+  {
+    mContext.ActiveTexture( unit );
+    mContext.TexParameteri( GL_TEXTURE_2D, filterType, newFilterModeGL );
+  }
+}
+
+void Texture::ApplySampler( TextureUnit unit, unsigned int samplerBitfield )
+{
+  if( mSamplerBitfield != samplerBitfield && mId != 0 )
+  {
+    ApplyTextureParameter( unit,
+                           GL_TEXTURE_MIN_FILTER,
+                           ImageSampler::GetMinifyFilterMode( mSamplerBitfield ),
+                           ImageSampler::GetMinifyFilterMode( samplerBitfield ),
+                           DALI_MINIFY_DEFAULT,
+                           SYSTEM_MINIFY_DEFAULT );
+
+    ApplyTextureParameter( unit,
+                           GL_TEXTURE_MAG_FILTER,
+                           ImageSampler::GetMagnifyFilterMode( mSamplerBitfield ),
+                           ImageSampler::GetMagnifyFilterMode( samplerBitfield ),
+                           DALI_MAGNIFY_DEFAULT,
+                           SYSTEM_MAGNIFY_DEFAULT );
+
+    mSamplerBitfield = samplerBitfield;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/gl-resources/texture.h b/dali/internal/render/gl-resources/texture.h
new file mode 100644 (file)
index 0000000..1834dc8
--- /dev/null
@@ -0,0 +1,284 @@
+#ifndef __DALI_INTERNAL_TEXTURE_H__
+#define __DALI_INTERNAL_TEXTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/bitmap.h>
+#include <dali/internal/render/common/uv-rect.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/render/gl-resources/gl-resource-owner.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/native-image.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/actors/sampling.h>
+
+namespace Dali
+{
+
+class NativeImage;
+
+namespace Internal
+{
+
+class Context;
+struct Vertex3D;
+struct Vertex2D;
+
+/**
+ * Texture class.
+ */
+class Texture: public RefObject,
+               public GlResourceOwner
+{
+public:
+
+  /**
+   * Used to define the area of the texture to display
+   */
+  typedef Rect<int> PixelArea;
+
+  /**
+   * Used to define a region of a bitmap.
+   */
+  typedef Rect<unsigned int>    RectArea;     ///< rectangular area (x,y,w,h)
+
+  /**
+   * Initialization method for Texture.
+   * Might or might not be needed in specific implementations.
+   * @return true if successful, false otherwise
+   */
+  virtual bool Init() = 0;
+
+  /**
+   * Update the texture with the bitmap.
+   */
+  virtual void Update(Integration::Bitmap* bitmap);
+
+  /**
+   * Update the texture from the modified bitmap.
+   * @param area to update
+   */
+  virtual void UpdateArea( const RectArea& area );
+
+  /**
+   * Update part of the texture with a different bitmap
+   * @param[in] srcBitmap The bitmap to copy from
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  virtual void Update( Integration::Bitmap* srcBitmap, std::size_t xOffset, std::size_t yOffset ) {}
+
+  /**
+   * @return Return true if the texture should be updated on GL texture creation.
+   */
+  virtual bool UpdateOnCreate();
+
+  /**
+   * Binds the texture for use.
+   * If there is no GL texture yet, it tries to create one.
+   *
+   * @param target (e.g. GL_TEXTURE_2D)
+   * @param textureunit to bind to
+   * @return True if the opengl texture was created, false if there was already a texture
+   * or no texture could be created yet ( e.g. no bitmap data after context loss )
+   */
+  virtual bool Bind(GLenum target, TextureUnit textureunit);
+
+  /**
+   * Returns GL texture ID
+   * @return texture id
+   */
+  unsigned int GetTextureId()
+  {
+    return mId;
+  }
+
+  /**
+   * Return the width of image in pixels.
+   * @return width
+   */
+  virtual unsigned int GetWidth() const;
+
+  /**
+   * Return the height of image in pixels.
+   * @return height
+   */
+  virtual unsigned int GetHeight() const;
+
+  /**
+   * Query whether the texture data has an alpha channel.
+   * @return True if the texture data has an alpha channel.
+   */
+  virtual bool HasAlphaChannel() const = 0;
+
+  /**
+   * Query whether the texture is completely opaque
+   * @return True if all pixels of the texture data are opaque
+   */
+  virtual bool IsFullyOpaque() const = 0;
+
+  /**
+   * Sets the texture id.
+   * @param id OpenGL texture id
+   */
+  void SetTextureId(GLuint id);
+
+  /**
+   * When creating a texture mapped object, the developer can
+   * can assume the texture u,v coordinates have a range of 0 to 1.
+   * They then just call MapUV which will adjust uv values depending on
+   * whether a pixel area is being used or not.
+   *@param[in] numVerts number of vertices
+   *@param[out] verts pointer to an array of vertex objects
+   *@param[in] pixelArea the area of the texture to display, null = use default image area
+   */
+  void MapUV(unsigned int numVerts, Dali::Internal::Vertex3D* verts,  const PixelArea* pixelArea = NULL);
+
+  /**
+   * @copydoc MapUV(unsigned int,Dali::Internal::Vertex3D*, const PixelArea* pixelArea)
+   */
+  void MapUV(unsigned int numVerts, Dali::Internal::Vertex2D* verts, const PixelArea* pixelArea = NULL);
+
+  /**
+   * @copydoc MapUV(unsigned int,Dali::Internal::Vertex3D*, const PixelArea* pixelArea)
+   * @param[in] stride The number of floats on each row of the vertex object table
+   */
+  void MapUV(unsigned int numVerts, float* verts, unsigned int stride, const PixelArea* pixelArea = NULL);
+
+  /**
+   * Gets the texture coordinates for the texture.
+   * The texture maybe in an atlas or may only be part of a texture (that's been padded to be a power of 2).
+   * Why do we specify u,v coordinates for all 4 points of a texture, instead of just having bottom left u,v and top right u,v?
+   * If the texture is an atlas it maybe rotated, to encode that information we need to use all 4 u,v points.
+   * @param[out] uv coordinates.
+   * @param[in] pixelArea the area of the texture to display, null = use default image area
+   */
+  void GetTextureCoordinates(UvRect& uv, const PixelArea* pixelArea = NULL);
+
+  /**
+   * @brief Apply the given sampler to the texture.
+   *
+   * @param[in] texture unit to use
+   * @param[in] samplerBitfield A bitfield with packed sampler options.
+   */
+  void ApplySampler( TextureUnit unit, unsigned int samplerBitfield );
+
+protected:
+
+  /**
+   * Constructor.
+   * @param[in] context The GL context
+   * @param[in] width       The buffer width
+   * @param[in] height      The buffer height
+   * @param[in] imageWidth  The image width
+   * @param[in] imageHeight The image height
+   */
+  Texture( Context&      context,
+           unsigned int  width,
+           unsigned int  height,
+           unsigned int  imageWidth,
+           unsigned int  imageHeight );
+  /**
+   * Constructor.
+   * @param[in] context The GL context
+   * @param[in] width       Both the buffer width and the image width (they are equal)
+   * @param[in] height      Both the buffer height and the image height.
+   */
+  Texture( Context&      context,
+           unsigned int  width,
+           unsigned int  height );
+public:
+  /**
+   * Initialize texture for rendering.
+   * @return true on success
+   */
+  virtual bool CreateGlTexture() = 0;
+
+  /**
+   * Destructor.
+   * Delete the GL texture associated with it.
+   */
+  virtual ~Texture();
+
+public: // From GlResourceOwner
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlContextDestroyed()
+   */
+  virtual void GlContextDestroyed();
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlCleanup()
+   */
+  virtual void GlCleanup();
+
+private:
+
+  // Undefined
+  Texture(const Texture&);
+
+  // Undefined
+  Texture& operator=(const Texture& rhs);
+
+  /**
+   * Helper function for GetTextureCoordinates.
+   * Gets the texture co-ordinates without using a pixel area.
+   * It is possible the image is smaller than the texture
+   * so the texture co-ordinates have to be adjusted.
+   * @param uv texture co-ordinates
+   */
+  void GetDefaultTextureCoordinates(UvRect& uv) const;
+
+  /**
+   * @brief Apply the given texture parameters.
+   *
+   * @param[in] texture unit to use
+   * @param[in] filterType Minification or magnification.
+   * @param[in] currentFilterMode The current filter mode.
+   * @param[in] newFilterMode The new filter mode.
+   * @param[in] daliDefault The default dali filter mode for the given filterType.
+   * @param[in] systemDefault The default system filter mode for the given filterType.
+   */
+  void ApplyTextureParameter( TextureUnit unit, GLint filterType, FilterMode::Type currentFilterMode, FilterMode::Type newFilterMode, GLint daliDefault, GLint systemDefault );
+
+protected:
+
+  Context&      mContext;      ///< The GL Context
+
+  GLuint        mId;           ///< Texture id
+
+  unsigned int  mSamplerBitfield;    ///< The packed bitfield of the current sampler
+
+  unsigned int  mWidth;        ///< texture width, may be scaled power of 2 (if not in an atlas)
+  unsigned int  mHeight;       ///< texture width, may be scaled power of 2 (if not in an atlas)
+
+  unsigned int  mImageWidth;   ///< width of the original image (may be smaller than texture width)
+  unsigned int  mImageHeight;  ///< height of the original image (may be smaller than texture height)
+
+  bool          mYInverted;    ///< Whether the image is y-inverted
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TEXTURE_H__
diff --git a/dali/internal/render/queue/render-queue.cpp b/dali/internal/render/queue/render-queue.cpp
new file mode 100644 (file)
index 0000000..6c137e9
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/queue/render-queue.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+static const std::size_t INITIAL_BUFFER_SIZE = 32768;
+static const std::size_t MAX_BUFFER_SIZE     = 32768;
+
+} // unnamed namespace
+
+namespace SceneGraph
+{
+
+RenderQueue::RenderQueue()
+: container0( NULL ),
+  container1( NULL )
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  container0 = new MessageBuffer( INITIAL_BUFFER_SIZE );
+  container1 = new MessageBuffer( INITIAL_BUFFER_SIZE );
+}
+
+RenderQueue::~RenderQueue()
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  if( container0 )
+  {
+    for( MessageBuffer::Iterator iter = container0->Begin(); iter.IsValid(); iter.Next() )
+    {
+      MessageBase* message = reinterpret_cast< MessageBase* >( iter.Get() );
+
+      // Call virtual destructor explictly; since delete will not be called after placement new
+      message->~MessageBase();
+    }
+
+    delete container0;
+  }
+
+  if( container1 )
+  {
+    for( MessageBuffer::Iterator iter = container1->Begin(); iter.IsValid(); iter.Next() )
+    {
+      MessageBase* message = reinterpret_cast< MessageBase* >( iter.Get() );
+
+      // Call virtual destructor explictly; since delete will not be called after placement new
+      message->~MessageBase();
+    }
+
+    delete container1;
+  }
+}
+
+unsigned int* RenderQueue::ReserveMessageSlot( BufferIndex updateBufferIndex, std::size_t size )
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  MessageBuffer* container = GetCurrentContainer( updateBufferIndex );
+
+  return container->ReserveMessageSlot( size );
+}
+
+void RenderQueue::ProcessMessages( BufferIndex bufferIndex )
+{
+  Dali::Mutex::ScopedLock lock(mMutex);
+  MessageBuffer* container = GetCurrentContainer( bufferIndex );
+
+  for( MessageBuffer::Iterator iter = container->Begin(); iter.IsValid(); iter.Next() )
+  {
+    MessageBase* message = reinterpret_cast< MessageBase* >( iter.Get() );
+
+    message->Process( bufferIndex );
+
+    // Call virtual destructor explictly; since delete will not be called after placement new
+    message->~MessageBase();
+  }
+
+  container->Reset();
+
+  LimitBufferCapacity( bufferIndex );
+}
+
+MessageBuffer* RenderQueue::GetCurrentContainer( BufferIndex bufferIndex )
+{
+  MessageBuffer* container( NULL );
+
+  /**
+   * The update-thread queues messages with one container,
+   * whilst the render-thread is processing the other.
+   */
+  if ( !bufferIndex )
+  {
+    container = container0;
+  }
+  else
+  {
+    container = container1;
+  }
+
+  return container;
+}
+
+void RenderQueue::LimitBufferCapacity( BufferIndex bufferIndex )
+{
+  if ( !bufferIndex )
+  {
+    if( MAX_BUFFER_SIZE < container0->GetCapacity() )
+    {
+      delete container0;
+      container0 = NULL;
+      container0 = new MessageBuffer( INITIAL_BUFFER_SIZE );
+    }
+  }
+  else
+  {
+    if( MAX_BUFFER_SIZE < container1->GetCapacity() )
+    {
+      delete container1;
+      container1 = NULL;
+      container1 = new MessageBuffer( INITIAL_BUFFER_SIZE );
+    }
+  }
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/queue/render-queue.h b/dali/internal/render/queue/render-queue.h
new file mode 100644 (file)
index 0000000..cdf458f
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_QUEUE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_QUEUE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/mutex.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/message-buffer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class MessageBase;
+
+namespace SceneGraph
+{
+
+/**
+ * Allows messages to be queued for RenderManager, during the scene-graph Update.
+ */
+class RenderQueue
+{
+public:
+
+  /**
+   * Create a new RenderQueue.
+   */
+  RenderQueue();
+
+  /**
+   * Non-virtual destructor; RenderQueue is not suitable as a base class.
+   */
+  ~RenderQueue();
+
+  /**
+   * Reserve space for another message in the queue; this must then be initialized by the caller.
+   * The message will be read from the next render-thread tick.
+   * @post Calling this method may invalidate any previously returned slots.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] size The message size with respect to the size of type "char".
+   * @return A pointer to the first char allocated for the message.
+   */
+  unsigned int* ReserveMessageSlot( BufferIndex updateBufferIndex, std::size_t size );
+
+  /**
+   * Process the batch of messages, which were queued in the previous update.
+   * @pre This message should only be called by RenderManager from within the render-thread.
+   * @param[in] bufferIndex The previous update buffer index.
+   */
+  void ProcessMessages( BufferIndex bufferIndex );
+
+private:
+
+  /**
+   * Helper to retrieve the current container.
+   * The update-thread queues messages with one container, whilst the render-thread is processing the other.
+   * @param[in] bufferIndex The current buffer index.
+   * @return The container.
+   */
+  MessageBuffer* GetCurrentContainer( BufferIndex bufferIndex );
+
+  /**
+   * Helper to limit the buffer capacity i.e. after a frame when an extreme number of messages have been sent.
+   * @param[in] bufferIndex The current buffer index.
+   */
+  void LimitBufferCapacity( BufferIndex bufferIndex );
+
+  // Undefined
+  RenderQueue( const RenderQueue& );
+
+  // Undefined
+  RenderQueue& operator=( const RenderQueue& rhs );
+
+private:
+
+  Dali::Mutex mMutex;        ///< Mutex to ensure access locking
+  MessageBuffer* container0; ///< Messages are queued here when the update buffer index == 0
+  MessageBuffer* container1; ///< Messages are queued here when the update buffer index == 1
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_QUEUE_H__
diff --git a/dali/internal/render/renderers/render-geometry.cpp b/dali/internal/render/renderers/render-geometry.cpp
new file mode 100644 (file)
index 0000000..2084329
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/render/renderers/render-geometry.h>
+
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/internal/render/shaders/program.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+RenderGeometry::RenderGeometry( const GeometryDataProvider& geometryDataProvider )
+: mGeometryDataProvider( geometryDataProvider ),
+  mHasBeenUpdated(false),
+  mAttributesChanged(true)
+{
+}
+
+RenderGeometry::~RenderGeometry()
+{
+}
+
+void RenderGeometry::GlContextCreated( Context& context )
+{
+}
+
+void RenderGeometry::GlContextDestroyed()
+{
+}
+
+void RenderGeometry::AddPropertyBuffer( const PropertyBufferDataProvider* dataProvider, GpuBuffer::Target gpuBufferTarget, GpuBuffer::Usage gpuBufferUsage )
+{
+  if( gpuBufferTarget == GpuBuffer::ELEMENT_ARRAY_BUFFER )
+  {
+    RenderPropertyBuffer* renderPropertyBuffer = new RenderPropertyBuffer( *dataProvider, gpuBufferTarget, gpuBufferUsage );
+    mIndexBuffer = renderPropertyBuffer;
+  }
+  else if( gpuBufferTarget == GpuBuffer::ARRAY_BUFFER )
+  {
+    RenderPropertyBuffer* renderPropertyBuffer = new RenderPropertyBuffer( *dataProvider, gpuBufferTarget, gpuBufferUsage );
+    mVertexBuffers.PushBack( renderPropertyBuffer );
+    mAttributesChanged = true;
+  }
+}
+
+void RenderGeometry::RemovePropertyBuffer( const PropertyBufferDataProvider* dataProvider )
+{
+  if( dataProvider == &mIndexBuffer->GetDataProvider() )
+  {
+    mIndexBuffer.Reset();
+  }
+  else
+  {
+    for( RenderPropertyBufferIter iter( mVertexBuffers.Begin() ); iter != mVertexBuffers.End(); ++iter )
+    {
+      if( dataProvider == &(*iter)->GetDataProvider() )
+      {
+        //This will delete the gpu buffer associated to the RenderPropertyBuffer if there is one
+        mVertexBuffers.Remove( iter );
+        mAttributesChanged = true;
+        break;
+      }
+    }
+  }
+}
+
+void RenderGeometry::GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const
+{
+  attributeLocation.Clear();
+
+  for( size_t i(0); i< mVertexBuffers.Size(); ++i )
+  {
+    unsigned int attributeCount = mVertexBuffers[i]->GetDataProvider().GetAttributeCount( bufferIndex );
+    for( unsigned int j = 0; j < attributeCount; ++j )
+    {
+      const std::string& attributeName = mVertexBuffers[i]->GetDataProvider().GetAttributeName( bufferIndex, j );
+      unsigned int index = program.RegisterCustomAttribute( attributeName );
+      GLint location = program.GetCustomAttributeLocation( index );
+
+      if( -1 == location )
+      {
+        DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
+      }
+
+      attributeLocation.PushBack( location );
+    }
+  }
+}
+
+void RenderGeometry::OnRenderFinished()
+{
+  mHasBeenUpdated = false;
+  mAttributesChanged = false;
+}
+
+void RenderGeometry::UploadAndDraw(
+    Context& context,
+    BufferIndex bufferIndex,
+    Vector<GLint>& attributeLocation )
+{
+  if( !mHasBeenUpdated )
+  {
+    //Update buffers
+    if( mIndexBuffer )
+    {
+      mIndexBuffer->Update( context, bufferIndex );
+    }
+    for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
+    {
+      mVertexBuffers[i]->Update( context, bufferIndex );
+    }
+    mHasBeenUpdated = true;
+  }
+
+  //Bind buffers to attribute locations
+  unsigned int base = 0;
+  for( unsigned int i = 0; i < mVertexBuffers.Count(); ++i )
+  {
+    mVertexBuffers[i]->BindBuffer( context );
+    base += mVertexBuffers[i]->EnableVertexAttributes( context, bufferIndex, attributeLocation, base );
+  }
+
+  if( mIndexBuffer )
+  {
+    mIndexBuffer->BindBuffer( context );
+  }
+
+  //Bind index buffer
+  unsigned int numIndices(0u);
+  if( mIndexBuffer )
+  {
+    const PropertyBufferDataProvider& indexBuffer = mIndexBuffer->GetDataProvider();
+    numIndices = mIndexBuffer->GetDataProvider().GetDataSize(bufferIndex) / indexBuffer.GetElementSize(bufferIndex);
+  }
+
+  //Draw call
+  GeometryDataProvider::GeometryType type = mGeometryDataProvider.GetGeometryType( bufferIndex );
+  switch(type)
+  {
+    case Dali::Geometry::TRIANGLES:
+    {
+      if( numIndices )
+      {
+        context.DrawElements(GL_TRIANGLES, numIndices, GL_UNSIGNED_SHORT, 0);
+      }
+      else
+      {
+        const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
+        unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
+        context.DrawArrays( GL_TRIANGLES, 0, numVertices );
+      }
+      break;
+    }
+    case Dali::Geometry::LINES:
+    {
+      if( numIndices )
+      {
+        context.DrawElements(GL_LINES, numIndices, GL_UNSIGNED_SHORT, 0);
+      }
+      else
+      {
+        const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
+        unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
+        context.DrawArrays( GL_LINES, 0, numVertices );
+      }
+      break;
+    }
+    case Dali::Geometry::POINTS:
+    {
+      const PropertyBufferDataProvider& firstVertexBuffer = mVertexBuffers[0]->GetDataProvider();
+      unsigned int numVertices = firstVertexBuffer.GetElementCount( bufferIndex );
+      context.DrawArrays(GL_POINTS, 0, numVertices );
+      break;
+    }
+    default:
+    {
+      DALI_ASSERT_ALWAYS( 0 && "Geometry type not supported (yet)" );
+      break;
+    }
+  }
+
+  //Disable atrributes
+  for( unsigned int i = 0; i < attributeLocation.Count(); ++i )
+  {
+    if( attributeLocation[i] != -1 )
+    {
+      context.DisableVertexAttributeArray( attributeLocation[i] );
+    }
+  }
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/render/renderers/render-geometry.h b/dali/internal/render/renderers/render-geometry.h
new file mode 100644 (file)
index 0000000..80aba88
--- /dev/null
@@ -0,0 +1,139 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_GEOMETRY_H
+#define DALI_INTERNAL_SCENE_GRAPH_RENDER_GEOMETRY_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+#include <dali/internal/render/renderers/render-renderer-property-buffer.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class Context;
+class Program;
+class GpuBuffer;
+
+namespace SceneGraph
+{
+class RenderDataProvider;
+class GeometryDataProvider;
+
+typedef OwnerPointer< RenderPropertyBuffer > RenderPropertyBufferPtr;
+typedef OwnerContainer< RenderPropertyBuffer* > RenderPropertyBufferContainer;
+typedef RenderPropertyBufferContainer::Iterator RenderPropertyBufferIter;
+
+
+/**
+ * This class encapsulates the GPU buffers. It is used to upload vertex data
+ * to it's GPU buffers, to bind all the buffers and to setup/teardown vertex attribute
+ * bindings
+ */
+class RenderGeometry
+{
+public:
+
+  /**
+   * Constructor. Creates a render geometry object with no GPU buffers.
+   */
+  RenderGeometry( const GeometryDataProvider& geometryDataProvider );
+
+  /**
+   * Destructor
+   */
+  ~RenderGeometry();
+
+  /**
+   * Called on Gl Context created
+   */
+  void GlContextCreated( Context& context );
+
+  /**
+   * Called on Gl Context destroyed.
+   */
+  void GlContextDestroyed();
+
+  /**
+   * Adds a property buffer to the geometry
+   * @param[in] dataProvider The PropertyBuffer data provider
+   * @param[in] gpuBufferTarget target Specifies the type of the buffer
+   * @param[in] gpuBufferUsage usage Specifies how will the buffer be used
+   */
+  void AddPropertyBuffer( const PropertyBufferDataProvider* dataProvider, GpuBuffer::Target gpuBufferTarget, GpuBuffer::Usage gpuBufferUsage );
+
+  /**
+   * Removes a PropertyBuffer from the geometry
+   * @param[in] dataProvider The property buffer to be removed
+   */
+  void RemovePropertyBuffer(  const PropertyBufferDataProvider* dataProvider );
+
+  /**
+   * Gets the attribute locations on the shader for the attributes defined in the geometry RenderBuffers
+   * @param[out] attributeLocation The vector where the attributes locations will be stored
+   * @param[in] program The program
+   * @param[in] bufferIndex The current buffer index
+   */
+  void GetAttributeLocationFromProgram( Vector<GLint>& attributeLocation, Program& program, BufferIndex bufferIndex ) const;
+
+  /**
+   * Called from RenderManager to notify the geometry that current rendering pass has finished.
+   */
+  void OnRenderFinished();
+
+  /**
+   * Chack if the attributes for the geometry have changed
+   * @return True if vertex buffers have been added or removed since last frame, false otherwise
+   */
+  bool AttributesChanged() const
+  {
+    return mAttributesChanged;
+  }
+
+  /**
+   * Upload the geometry if it has changed, set up the attributes and perform
+   * the Draw call corresponding to the geometry type
+   * @param[in] context The GL context
+   * @param[in] bufferIndex The current buffer index
+   * @param[in] attributeLocation The location for the attributes in the shader
+   */
+  void UploadAndDraw(Context& context,
+                     BufferIndex bufferIndex,
+                     Vector<GLint>& attributeLocation );
+
+private:
+
+  const GeometryDataProvider& mGeometryDataProvider;  //Reference to update thread object
+
+  // PropertyBuffers
+  RenderPropertyBufferPtr       mIndexBuffer;
+  RenderPropertyBufferContainer mVertexBuffers;
+
+  // Booleans
+  bool mHasBeenUpdated : 1;
+  bool mAttributesChanged : 1;
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_SAMPLER_DATA_PROVIDER_H
diff --git a/dali/internal/render/renderers/render-renderer-property-buffer.cpp b/dali/internal/render/renderers/render-renderer-property-buffer.cpp
new file mode 100644 (file)
index 0000000..dfceae9
--- /dev/null
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADERS
+#include <dali/internal/render/renderers/render-renderer-property-buffer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-buffer-impl.h>  // Dali::Internal::PropertyBuffer
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/internal/render/shaders/program.h>
+
+namespace
+{
+
+using namespace Dali;
+using Dali::Property;
+using Dali::Internal::PropertyImplementationType;
+
+Dali::GLenum GetPropertyImplementationGlType( Property::Type& propertyType )
+{
+  Dali::GLenum type = GL_BYTE;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    case Property::RECTANGLE:
+    case Property::ROTATION:
+    {
+      // types not supported by gl
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      type = GL_BYTE;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      type = GL_SHORT;
+      break;
+    }
+    case Property::FLOAT:
+    case Property::VECTOR2:
+    case Property::VECTOR3:
+    case Property::VECTOR4:
+    case Property::MATRIX3:
+    case Property::MATRIX:
+    {
+      type = GL_FLOAT;
+      break;
+    }
+  }
+
+  return type;
+}
+
+size_t GetPropertyImplementationGlSize( Property::Type& propertyType )
+{
+  size_t size = 1u;
+
+  switch( propertyType )
+  {
+    case Property::NONE:
+    case Property::STRING:
+    case Property::ARRAY:
+    case Property::MAP:
+    case Property::RECTANGLE:
+    case Property::ROTATION:
+    {
+      // types not supported by gl
+      break;
+    }
+    case Property::BOOLEAN:
+    {
+      size = 1u;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      size = 2u;
+      break;
+    }
+    case Property::FLOAT:
+    case Property::VECTOR2:
+    case Property::VECTOR3:
+    case Property::VECTOR4:
+    case Property::MATRIX3:
+    case Property::MATRIX:
+    {
+      size = 4u;
+      break;
+    }
+  }
+
+  return size;
+}
+
+void UploadAttribute( Dali::Internal::Context& context,
+                      Dali::GLint attributeLocation,
+                      Dali::GLint attributeSize,
+                      size_t attributeOffset,
+                      Dali::Property::Type attributeType,
+                      Dali::GLsizei elementSize )
+{
+  // TODO: MESH_REWORK  Matrices need multiple calls to this function
+  context.VertexAttribPointer( attributeLocation,
+                               attributeSize  / GetPropertyImplementationGlSize(attributeType),
+                               GetPropertyImplementationGlType(attributeType),
+                               GL_FALSE,  // Not normalized
+                               elementSize,
+                               (void*)attributeOffset );
+}
+
+}  // unnamed namespace
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+RenderPropertyBuffer::RenderPropertyBuffer( const PropertyBufferDataProvider& propertyBufferDataProvider,
+                                            GpuBuffer::Target gpuBufferTarget,
+                                            GpuBuffer::Usage gpuBufferUsage )
+: mDataProvider( propertyBufferDataProvider ),
+  mGpuBuffer( NULL ),
+  mGpuBufferTarget( gpuBufferTarget ),
+  mGpuBufferUsage( gpuBufferUsage )
+{
+}
+
+RenderPropertyBuffer::~RenderPropertyBuffer()
+{
+}
+
+void RenderPropertyBuffer::Update( Context& context, BufferIndex bufferIndex )
+{
+  if( !mGpuBuffer || mDataProvider.HasDataChanged( bufferIndex ) )
+  {
+    if ( ! mGpuBuffer )
+    {
+       mGpuBuffer = new GpuBuffer( context, mGpuBufferTarget, mGpuBufferUsage );
+    }
+
+    // Update the GpuBuffer
+    if ( mGpuBuffer )
+    {
+      std::size_t dataSize = mDataProvider.GetDataSize( bufferIndex );
+      DALI_ASSERT_DEBUG( dataSize && "No data in the property buffer!" );
+
+      const void *data = &(mDataProvider.GetData( bufferIndex )[0]);
+      Vector<unsigned short> ushortData;
+
+      // Index buffer needs to be unsigned short which is not supported by the property system
+      if( mGpuBufferTarget == GpuBuffer::ELEMENT_ARRAY_BUFFER )
+      {
+        ushortData.Resize( dataSize );
+        const unsigned int* unsignedData = static_cast<const unsigned int*>(data);
+        unsigned int numberOfElements = dataSize / sizeof(unsigned int);
+        for( unsigned int i = 0; i < numberOfElements; ++i )
+        {
+          ushortData[i] = unsignedData[i];
+        }
+        data = &(ushortData[0]);
+      }
+
+      mGpuBuffer->UpdateDataBuffer( dataSize, data );
+      mGpuBuffer->SetStride( mDataProvider.GetElementSize( bufferIndex ) );
+    }
+  }
+}
+
+void RenderPropertyBuffer::BindBuffer( Context& context )
+{
+  mGpuBuffer->Bind();
+}
+
+unsigned int RenderPropertyBuffer::EnableVertexAttributes( Context& context, BufferIndex bufferIndex, Vector<GLint>& vAttributeLocation, unsigned int locationBase )
+{
+  unsigned int attributeCount = mDataProvider.GetAttributeCount( bufferIndex );
+
+  GLsizei elementSize = mDataProvider.GetElementSize( bufferIndex );
+
+  for( unsigned int i = 0; i < attributeCount; ++i )
+  {
+    GLint attributeLocation = vAttributeLocation[i+locationBase];
+    if( attributeLocation != -1 )
+    {
+      context.EnableVertexAttributeArray( attributeLocation );
+
+      GLint attributeSize = mDataProvider.GetAttributeSize( bufferIndex, i );
+      size_t attributeOffset = mDataProvider.GetAttributeOffset( bufferIndex, i );
+      Property::Type attributeType = mDataProvider.GetAttributeType( bufferIndex, i );
+
+      UploadAttribute( context,
+                       attributeLocation,
+                       attributeSize,
+                       attributeOffset,
+                       attributeType,
+                       elementSize );
+    }
+  }
+
+  return attributeCount;
+}
+
+void RenderPropertyBuffer::UpdateAttributeLocations( Context& context, BufferIndex bufferIndex, Program& program )
+{
+  unsigned int attributeCount = mDataProvider.GetAttributeCount( bufferIndex );
+  mAttributesLocation.Resize( attributeCount );
+
+  for( unsigned int i = 0; i < attributeCount; ++i )
+  {
+    const std::string& attributeName = mDataProvider.GetAttributeName( bufferIndex, i );
+    unsigned int index = program.RegisterCustomAttribute( attributeName );
+    GLint attributeLocation = program.GetCustomAttributeLocation( index );
+
+    if( -1 == attributeLocation )
+    {
+      DALI_LOG_WARNING( "Attribute not found in the shader: %s\n", attributeName.c_str() );
+    }
+    mAttributesLocation[i] = attributeLocation;
+  }
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/render/renderers/render-renderer-property-buffer.h b/dali/internal/render/renderers/render-renderer-property-buffer.h
new file mode 100644 (file)
index 0000000..a4966fe
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDER_RENDERER_PROPERTY_BUFFER_H
+#define DALI_INTERNAL_SCENE_GRAPH_RENDER_RENDERER_PROPERTY_BUFFER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/render/data-providers/property-buffer-data-provider.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class Context;
+class Program;
+
+namespace SceneGraph
+{
+class NewRenderer;
+/**
+ * This class encapsulates the GPU buffers. It is used to upload vertex data
+ * to it's GPU buffers, to bind all the buffers and to setup/teardown vertex attribute
+ * bindings
+ */
+class RenderPropertyBuffer
+{
+public:
+  typedef OwnerContainer< GpuBuffer* > GpuBuffers;
+
+  /**
+   * Constructor. Creates a render geometry object with no GPU buffers.
+   * @param[in] propertyBufferDataProvider The property-buffer  data provider (to fetch geometry from)
+   * @param[in] gpuBufferTarget Type of target for the gpu-buffer
+   * @param[in] gpuBufferUsage Type of target for the gpu-buffer
+   */
+  RenderPropertyBuffer( const PropertyBufferDataProvider& propertyBufferDataProvider,
+                        GpuBuffer::Target gpuBufferTarget,
+                        GpuBuffer::Usage gpuBufferUsage );
+
+  /**
+   * Destructor
+   */
+  ~RenderPropertyBuffer();
+
+  /**
+   * Perform the upload of the buffer only when requiered
+   * @param[in] context The GL context
+   * @param[in] bufferIndex The current buffer index
+   */
+  void Update( Context& context, BufferIndex bufferIndex );
+
+  /**
+   * Bind the geometry buffers
+   * @param[in] context The GL context
+   */
+  void BindBuffer( Context& context );
+
+  /**
+   * Enable the vertex attributes for each vertex buffer from the corresponding
+   * shader program.
+   * @param[in] context The GL context
+   * @param[in] bufferIndex The current buffer index
+   * @param[in] program The shader program to query for attribute locations
+   * @param[in] vAttributeLocation Vector containing attributes location for current program
+   * @param[in] locationBase Index in vAttributeLocation corresponding to the first attribute defined by this buffer
+   */
+  unsigned int EnableVertexAttributes( Context& context, BufferIndex bufferIndex, Vector<GLint>& vAttributeLocation, unsigned int locationBase);
+
+  /**
+   * Get the data provider for the buffer
+   */
+  const PropertyBufferDataProvider& GetDataProvider() const
+  {
+    return mDataProvider;
+  }
+
+private: // implementation
+
+  /**
+   * Update attribute locations
+   * @param[in] context The GL context
+   * @param[in] bufferIndex The current buffer index
+   * @param[in] program The shader program to query for attribute locations
+   */
+  void UpdateAttributeLocations( Context& context, BufferIndex bufferIndex, Program& program );
+
+private:
+  const PropertyBufferDataProvider& mDataProvider;  ///< Data provider used by this property buffer
+  Vector<GLint> mAttributesLocation;                ///< Location of the attributes for the property buffer in this renderer.
+
+  OwnerPointer<GpuBuffer> mGpuBuffer;               ///< Pointer to the GpuBuffer associated with this RenderPropertyBuffer
+  GpuBuffer::Target mGpuBufferTarget;               ///< The type of GPU buffer to create
+  GpuBuffer::Usage mGpuBufferUsage;                 ///< The type of usage the  GPU buffer will have
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_RENDER_RENDERER_PROPERTY_BUFFER_H
diff --git a/dali/internal/render/renderers/render-renderer.cpp b/dali/internal/render/renderers/render-renderer.cpp
new file mode 100644 (file)
index 0000000..5783f3e
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "render-renderer.h"
+
+#include <dali/internal/common/image-sampler.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/shaders/program.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+NewRenderer* NewRenderer::New( NodeDataProvider& nodeDataProvider,
+                               RenderDataProvider* dataProvider,
+                               RenderGeometry* renderGeometry )
+{
+  return new NewRenderer(nodeDataProvider, dataProvider, renderGeometry);
+}
+
+
+NewRenderer::NewRenderer( NodeDataProvider& nodeDataProvider,
+                          RenderDataProvider* dataProvider,
+                          RenderGeometry* renderGeometry )
+: Renderer( nodeDataProvider ),
+  mRenderDataProvider( dataProvider ),
+  mRenderGeometry( renderGeometry ),
+  mUpdateAttributesLocation( true )
+{
+}
+
+NewRenderer::~NewRenderer()
+{
+}
+
+void NewRenderer::SetRenderDataProvider( RenderDataProvider* dataProvider )
+{
+  mRenderDataProvider = dataProvider;
+  mUpdateAttributesLocation = true;
+}
+
+void NewRenderer::SetGeometry( RenderGeometry* renderGeometry )
+{
+  mRenderGeometry = renderGeometry;
+  mUpdateAttributesLocation = true;
+}
+
+// Note - this is currently called from UpdateThread, PrepareRenderInstructions,
+// as an optimisation.
+// @todo MESH_REWORK Should use Update thread objects only in PrepareRenderInstructions.
+bool NewRenderer::RequiresDepthTest() const
+{
+  return true;
+}
+
+bool NewRenderer::CheckResources()
+{
+  // Query material to check it has texture pointers & image has size
+  // Query geometry to check it has vertex buffers
+
+  // General point though - why would we have a render item in RenderThread with no ready
+  // resources in UpdateThread?
+  return true;
+}
+
+bool NewRenderer::IsOutsideClipSpace( Context& context, const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
+{
+  // @todo MESH_REWORK Add clipping
+  return false;
+}
+
+void NewRenderer::DoSetUniforms( Context& context, BufferIndex bufferIndex, Shader* shader, Program* program, unsigned int programIndex )
+{
+  // Do nothing, we're going to set up the uniforms with our own code instead
+}
+
+void NewRenderer::DoSetCullFaceMode( Context& context, BufferIndex bufferIndex )
+{
+}
+
+void NewRenderer::DoSetBlending( Context& context, BufferIndex bufferIndex )
+{
+  context.SetBlend(mUseBlend); // @todo MESH_REWORK Should use a RendererDataProvider
+
+  if( mUseBlend )
+  {
+    const MaterialDataProvider& material = mRenderDataProvider->GetMaterial();
+
+    context.SetCustomBlendColor( material.GetBlendColor( bufferIndex ) );
+
+    // Set blend source & destination factors
+    context.BlendFuncSeparate( material.GetBlendSrcFactorRgb( bufferIndex ),
+                               material.GetBlendDestFactorRgb( bufferIndex ),
+                               material.GetBlendSrcFactorAlpha( bufferIndex ),
+                               material.GetBlendDestFactorAlpha( bufferIndex ) );
+
+    // Set blend equations
+    context.BlendEquationSeparate( material.GetBlendEquationRgb( bufferIndex ),
+                                   material.GetBlendEquationAlpha( bufferIndex ) );
+  }
+}
+
+void NewRenderer::DoRender( Context& context, TextureCache& textureCache, BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
+{
+  BindTextures( textureCache, bufferIndex, program, mRenderDataProvider->GetSamplers() );
+
+  SetUniforms( bufferIndex, program );
+
+  if( mUpdateAttributesLocation || mRenderGeometry->AttributesChanged() )
+  {
+    mRenderGeometry->GetAttributeLocationFromProgram( mAttributesLocation, program, bufferIndex );
+    mUpdateAttributesLocation = false;
+  }
+
+  mRenderGeometry->UploadAndDraw( context, bufferIndex, mAttributesLocation );
+}
+
+void NewRenderer::GlContextDestroyed()
+{
+  mRenderGeometry->GlContextDestroyed();
+}
+
+void NewRenderer::GlCleanup()
+{
+}
+
+void NewRenderer::SetUniforms( BufferIndex bufferIndex, Program& program )
+{
+  // Check if the map has changed
+  DALI_ASSERT_DEBUG( mRenderDataProvider && "No Uniform map data provider available" );
+
+  const UniformMapDataProvider& uniformMapDataProvider = mRenderDataProvider->GetUniformMap();
+
+  if( uniformMapDataProvider.GetUniformMapChanged( bufferIndex ) )
+  {
+    const CollectedUniformMap& uniformMap = uniformMapDataProvider.GetUniformMap( bufferIndex );
+
+    unsigned int numberOfMaps = uniformMap.Count();
+    mUniformIndexMap.Clear(); // Clear contents, but keep memory if we don't change size
+    mUniformIndexMap.Resize( numberOfMaps );
+
+    // Remap uniform indexes to property value addresses
+    for( unsigned int mapIndex = 0 ; mapIndex < numberOfMaps ; ++mapIndex )
+    {
+      mUniformIndexMap[mapIndex].propertyValue = uniformMap[mapIndex]->propertyPtr;
+      mUniformIndexMap[mapIndex].uniformIndex = program.RegisterUniform( uniformMap[mapIndex]->uniformName );
+    }
+  }
+
+  // Set uniforms in local map
+  for( UniformIndexMappings::Iterator iter = mUniformIndexMap.Begin(),
+         end = mUniformIndexMap.End() ;
+       iter != end ;
+       ++iter )
+  {
+    SetUniformFromProperty( bufferIndex, program, *iter );
+  }
+
+  // @todo MESH_REWORK On merge, copy code from renderer to setup standard matrices and color
+
+  GLint sizeLoc = program.GetUniformLocation( Program::UNIFORM_SIZE );
+  if( -1 != sizeLoc )
+  {
+    Vector3 size = mDataProvider.GetRenderSize( bufferIndex );
+    program.SetUniform3f( sizeLoc, size.x, size.y, size.z );
+  }
+}
+
+void NewRenderer::SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map )
+{
+  GLint location = program.GetUniformLocation(map.uniformIndex);
+  if( Program::UNIFORM_UNKNOWN != location )
+  {
+    // switch based on property type to use correct GL uniform setter
+    switch ( map.propertyValue->GetType() )
+    {
+      case Property::INTEGER:
+      {
+        program.SetUniform1i( location, map.propertyValue->GetInteger( bufferIndex ) );
+        break;
+      }
+      case Property::FLOAT:
+      {
+        program.SetUniform1f( location, map.propertyValue->GetFloat( bufferIndex ) );
+        break;
+      }
+      case Property::VECTOR2:
+      {
+        Vector2 value( map.propertyValue->GetVector2( bufferIndex ) );
+        program.SetUniform2f( location, value.x, value.y );
+        break;
+      }
+
+      case Property::VECTOR3:
+      {
+        Vector3 value( map.propertyValue->GetVector3( bufferIndex ) );
+        program.SetUniform3f( location, value.x, value.y, value.z );
+        break;
+      }
+
+      case Property::VECTOR4:
+      {
+        Vector4 value( map.propertyValue->GetVector4( bufferIndex ) );
+        program.SetUniform4f( location, value.x, value.y, value.z, value.w );
+        break;
+      }
+
+      case Property::ROTATION:
+      {
+        Quaternion value( map.propertyValue->GetQuaternion( bufferIndex ) );
+        program.SetUniform4f( location, value.mVector.x, value.mVector.y, value.mVector.z, value.mVector.w );
+        break;
+      }
+
+      case Property::MATRIX:
+      {
+        const Matrix& value = map.propertyValue->GetMatrix(bufferIndex);
+        program.SetUniformMatrix4fv(location, 1, value.AsFloat() );
+        break;
+      }
+
+      case Property::MATRIX3:
+      {
+        const Matrix3& value = map.propertyValue->GetMatrix3(bufferIndex);
+        program.SetUniformMatrix3fv(location, 1, value.AsFloat() );
+        break;
+      }
+
+      default:
+      {
+        // Other property types are ignored
+        break;
+      }
+    }
+  }
+}
+
+void NewRenderer::BindTextures(
+  TextureCache& textureCache,
+  BufferIndex bufferIndex,
+  Program& program,
+  const RenderDataProvider::Samplers& samplers )
+{
+  // @todo MESH_REWORK Write a cache of texture units to commonly used sampler textures
+  unsigned int textureUnit = 0;
+
+  for( RenderDataProvider::Samplers::Iterator iter = samplers.Begin();
+       iter != samplers.End();
+       ++iter )
+  {
+    const SamplerDataProvider* sampler = *iter;
+    ResourceId textureId = sampler->GetTextureId(bufferIndex);
+    Texture* texture = textureCache.GetTexture( textureId );
+    if( texture != NULL )
+    {
+      unsigned int textureUnitUniformIndex = GetTextureUnitUniformIndex( program, *sampler );
+      TextureUnit theTextureUnit = static_cast<TextureUnit>(textureUnit);
+      BindTexture( textureCache, program, textureId, texture, theTextureUnit, textureUnitUniformIndex );
+      ApplySampler( bufferIndex, texture, theTextureUnit, *sampler );
+    }
+
+    ++textureUnit;
+  }
+}
+
+void NewRenderer::BindTexture(
+  TextureCache& textureCache,
+  Program& program,
+  ResourceId id,
+  Texture* texture,
+  TextureUnit textureUnit,
+  unsigned int textureUnitUniformIndex )
+{
+  if( texture != NULL )
+  {
+    textureCache.BindTexture( texture, id, GL_TEXTURE_2D, textureUnit );
+
+    // Set sampler uniform location for the texture
+    GLint textureUnitLoc = program.GetUniformLocation( textureUnitUniformIndex );
+    if( Program::UNIFORM_UNKNOWN != textureUnitLoc )
+    {
+      program.SetUniform1i( textureUnitLoc, textureUnit );
+    }
+  }
+}
+
+void NewRenderer::ApplySampler(
+  BufferIndex bufferIndex,
+  Texture*    texture,
+  TextureUnit textureUnit,
+  const SamplerDataProvider& sampler )
+{
+  unsigned int samplerBitfield = ImageSampler::PackBitfield(
+    static_cast< FilterMode::Type >(sampler.GetMinifyFilterMode(bufferIndex)),
+    static_cast< FilterMode::Type >(sampler.GetMagnifyFilterMode(bufferIndex)) );
+
+  texture->ApplySampler( textureUnit, samplerBitfield );
+
+  // @todo MESH_REWORK add support for wrap modes
+}
+
+unsigned int NewRenderer::GetTextureUnitUniformIndex(
+  Program& program,
+  const SamplerDataProvider& sampler )
+{
+  // Find sampler in mSamplerNameCache
+  // If it doesn't exist,
+  //   get the index by calling program.RegisterUniform and store it
+  // If it exists, it's index should be set.
+  // @todo Cache should be reset on scene change
+
+  unsigned int uniformIndex = 0;
+  bool found = false;
+
+  for( unsigned int i=0; i< mTextureUnitUniforms.Count(); ++i )
+  {
+    if( mTextureUnitUniforms[i].sampler == &sampler )
+    {
+      uniformIndex = mTextureUnitUniforms[i].index;
+      found = true;
+    }
+  }
+
+  if( ! found )
+  {
+    TextureUnitUniformIndex textureUnitUniformIndex;
+    textureUnitUniformIndex.sampler = &sampler;
+    textureUnitUniformIndex.index = program.RegisterUniform( sampler.GetTextureUnitUniformName() );
+    mTextureUnitUniforms.PushBack( textureUnitUniformIndex );
+    uniformIndex = textureUnitUniformIndex.index;
+  }
+
+  return uniformIndex;
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/renderers/render-renderer.h b/dali/internal/render/renderers/render-renderer.h
new file mode 100644 (file)
index 0000000..4756ea0
--- /dev/null
@@ -0,0 +1,230 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NEW_RENDERER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NEW_RENDERER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/resource-declarations.h> // For resource id
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/render-geometry.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class PropertyInputImpl;
+
+namespace SceneGraph
+{
+
+/**
+ * The new geometry renderer.
+ *
+ * @todo MESH_REWORK It will be merged into the base class eventually
+ */
+class NewRenderer : public Renderer
+{
+public:
+  typedef Integration::ResourceId ResourceId;
+
+public:
+  /**
+   * Create a new renderer instance
+   * @param[in] nodeDataProvider The node data provider
+   * @param[in] dataProviders The data providers for the renderer
+   * @param[in] renderGeometry The geometry for the renderer
+   */
+  static NewRenderer* New( NodeDataProvider& nodeDataProvider, RenderDataProvider* dataProviders, RenderGeometry* renderGeometry );
+  /**
+   * Constructor.
+   * @param[in] nodeDataProvider The node data provider
+   * @param[in] dataProviders The data providers for the renderer
+   * @param[in] renderGeometry The geometry for the renderer
+   */
+  NewRenderer( NodeDataProvider& nodeDataProvider, RenderDataProvider* dataProviders, RenderGeometry* renderGeometry );
+
+  virtual ~NewRenderer();
+
+  /**
+   * Change the data providers of the renderer
+   * @param[in] dataProviders The data providers
+   */
+  void SetRenderDataProvider( RenderDataProvider* dataProviders );
+
+  /**
+   * Change the geometry used by the renderer
+   * @param[in] renderGeometry The new geometry
+   */
+  void SetGeometry( RenderGeometry* renderGeometry );
+
+public: // Implementation of Renderer
+  /**
+   * @copydoc SceneGraph::Renderer::RequiresDepthTest()
+   */
+  virtual bool RequiresDepthTest() const;
+
+  /**
+   * @copydoc SceneGraph::Renderer::CheckResources()
+   */
+  virtual bool CheckResources();
+
+  /**
+   * @copydoc SceneGraph::Renderer::IsOutsideClipSpace()
+   */
+  virtual bool IsOutsideClipSpace( Context& context,
+                                   const Matrix& modelMatrix,
+                                   const Matrix& modelViewProjectionMatrix );
+
+  /**
+   * @copydoc SceneGraph::Renderer::DoSetUniforms()
+   */
+  virtual void DoSetUniforms( Context& context, BufferIndex bufferIndex, Shader* shader, Program* program, unsigned int programIndex );
+
+  /**
+   * @copydoc SceneGraph::Renderer::DoSetCullFaceMode
+   */
+  virtual void DoSetCullFaceMode(Context& context, BufferIndex bufferIndex );
+
+  /**
+   * @copydoc SceneGraph::Renderer::DoSetBlending
+   */
+  virtual void DoSetBlending(Context& context, BufferIndex bufferIndex );
+
+  /**
+   * @copydoc SceneGraph::Renderer::DoRender()
+   */
+  virtual void DoRender( Context& context,
+                         TextureCache& textureCache,
+                         BufferIndex bufferIndex,
+                         Program& program,
+                         const Matrix& modelViewMatrix,
+                         const Matrix& viewMatrix );
+
+public: // Implementation of GlResourceOwner
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlContextDestroyed()
+   */
+  virtual void GlContextDestroyed();
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlCleanup()
+   */
+  virtual void GlCleanup();
+
+private:
+  struct UniformIndexMap;
+
+  /**
+   * Set the uniforms from properties according to the uniform map
+   * @param[in] program The shader program on which to set the uniforms.
+   */
+  void SetUniforms( BufferIndex bufferIndex, Program& program );
+
+  /**
+   * Set the program uniform in the map from the mapped property
+   */
+  void SetUniformFromProperty( BufferIndex bufferIndex, Program& program, UniformIndexMap& map );
+
+  /**
+   * Bind the material textures in the samplers and setup the samplers
+   * @param[in] textureCache The texture cache
+   * @param[in] bufferIndex The buffer index
+   * @param[in] program The shader program
+   * @param[in] samplers The samplers to bind
+   */
+  void BindTextures( TextureCache& textureCache,
+                     BufferIndex bufferIndex,
+                     Program& program,
+                     const RenderDataProvider::Samplers& samplers );
+
+  /**
+   * Bind a material texture to a texture unit, and set the sampler's texture uniform
+   * to that texture unit.
+   * @param[in] textureCache The texture cache
+   * @param[in] program The shader program
+   * @param[in] id The resource id of the texture to bind
+   * @param[in] texture The texture to bind
+   * @param[in] textureUnit The texture unit index to use
+   * @param[in] nameIndex The index of the texture uniform in the program
+   */
+  void BindTexture( TextureCache& textureCache,
+                    Program& program,
+                    ResourceId id,
+                    Texture* texture,
+                    TextureUnit textureUnit,
+                    unsigned int nameIndex );
+
+  /**
+   * Apply the sampler modes to the texture.
+   * @param[in] bufferIndex The current buffer index
+   * @param[in] texture The texture to which to apply the sampler modes
+   * @param[in] textureUnit The texture unit of the texture
+   * @param[in] sampler The sampler from which to get the modes.
+   */
+  void ApplySampler( BufferIndex bufferIndex,
+                     Texture* texture,
+                     TextureUnit textureUnit,
+                     const SamplerDataProvider& sampler );
+
+  /**
+   * Get the texture uniform index of the name sampler in the program.
+   * If not already registered in the program, then this performs the registration
+   * @param[in] program The shader program
+   * @param[in] sampler The sampler holding a texture unit uniform name to search for
+   * @return The texture uniform index in the program
+   */
+  unsigned int GetTextureUnitUniformIndex( Program& program,
+                                           const SamplerDataProvider& sampler );
+
+public: //@todo MESH_REWORK make private after merge with SceneGraph::Renderer
+  OwnerPointer< RenderDataProvider > mRenderDataProvider;
+
+private:
+  RenderGeometry* mRenderGeometry;
+
+  struct TextureUnitUniformIndex
+  {
+    const SamplerDataProvider* sampler;
+    unsigned int index;
+  };
+
+  typedef Dali::Vector< TextureUnitUniformIndex > TextureUnitUniforms;
+  TextureUnitUniforms mTextureUnitUniforms;
+
+  struct UniformIndexMap
+  {
+    unsigned int uniformIndex; // The index of the cached location in the Program
+    const PropertyInputImpl* propertyValue;
+  };
+
+  typedef Dali::Vector< UniformIndexMap > UniformIndexMappings;
+  UniformIndexMappings mUniformIndexMap;
+
+  Vector<GLint> mAttributesLocation;
+  bool mUpdateAttributesLocation;
+};
+
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NEW_RENDERER_H__
diff --git a/dali/internal/render/renderers/scene-graph-image-renderer.cpp b/dali/internal/render/renderers/scene-graph-image-renderer.cpp
new file mode 100644 (file)
index 0000000..8d31438
--- /dev/null
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/renderers/scene-graph-image-renderer.h>
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/common/internal-constants.h>
+#include <dali/internal/render/common/culling-algorithms.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-debug.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gImageRenderFilter=Debug::Filter::New(Debug::NoLogging, false, "LOG_IMAGE_RENDERER");
+#endif
+
+/**
+ * VertexToTextureCoord
+ * Represents a mapping between a 1 dimensional vertex coordinate
+ * and a 1 dimensional texture coordinate.
+ */
+struct VertexToTextureCoord
+{
+  /**
+   * @param[in] xVertex Vertex coordinate
+   * @param[in] uTexture Texture coordinate
+   */
+  VertexToTextureCoord(float xVertex, float uTexture)
+  : x(xVertex),
+    u(uTexture)
+  {
+  }
+
+  float x;    ///< 1D Vertex position
+  float u;    ///< 1D Texture position
+};
+
+/**
+ * Generates a list of equally spaced intervals along a line, including
+ * intervals at the points specified in insertionList.
+ * The line starts from insertionList.begin() and ends at insertionList.end()-1
+ * The number of intervals and spacing of these intervals is specified by
+ * the caller.
+ * @param[out] intervalList An empty vector to be populated with the list of intervals.
+ * @param[in] intervals The number of intervals to be generated.
+ * @param[in] insertionList A vector containing the points on the line to be inserted.
+ */
+void GenerateIntervals(std::vector<VertexToTextureCoord>& intervalList, int intervals, const std::vector<VertexToTextureCoord>& insertionList)
+{
+  DALI_ASSERT_DEBUG(insertionList.size() >= 2);
+  DALI_ASSERT_DEBUG(intervals > 0);
+
+  std::vector<VertexToTextureCoord>::const_iterator iter = insertionList.begin();
+  if( iter != insertionList.end() )
+  {
+    std::vector<VertexToTextureCoord>::const_iterator end = insertionList.end()-1;
+
+    const float length = end->x - iter->x;
+    const float intervalSize = length / static_cast<float>(intervals);
+    float x = iter->x;
+
+    for(;iter!=end;++iter)
+    {
+      float x0 = iter[0].x;
+      float u0 = iter[0].u;
+      float x1 = iter[1].x;
+      float u1 = iter[1].u;
+
+      for(;x<x1;x+=intervalSize)
+      {
+        float progress = (x - x0) / (x1 - x0);  // progress value between current interval and next.
+        float u = u0 + (u1 - u0) * progress;    // u 1D texture coordinate value for this x position.
+        intervalList.push_back( VertexToTextureCoord( x, u ) );
+      }
+      intervalList.push_back( VertexToTextureCoord( x1, u1 ) );
+    }
+  }
+}
+
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+ImageRenderer* ImageRenderer::New( NodeDataProvider& dataProvider )
+{
+  return new ImageRenderer( dataProvider );
+}
+
+ImageRenderer::~ImageRenderer()
+{
+  if ( mTextureId > 0 )
+  {
+    mTextureCacheDELETEME->RemoveObserver(mTextureId, this);
+  }
+
+  GlCleanup();
+}
+
+void ImageRenderer::SetTextureId( ResourceId textureId )
+{
+  if ( mTextureId > 0 )
+  {
+    mTextureCacheDELETEME->RemoveObserver(mTextureId, this);
+  }
+
+  mTextureId = textureId;
+  mTexture = NULL;
+
+  if ( textureId > 0 )
+  {
+    mTextureCacheDELETEME->AddObserver(textureId, this);
+  }
+}
+
+void ImageRenderer::SetPixelArea( const ImageRenderer::PixelArea& pixelArea )
+{
+  mUsePixelArea    = true;
+  mPixelArea       = pixelArea;
+  mIsMeshGenerated = false;
+}
+
+void ImageRenderer::SetNinePatchBorder( const Vector4& border, bool inPixels )
+{
+  mBorder          = border;
+  mBorderInPixels  = inPixels;
+  mIsMeshGenerated = false;
+}
+
+void ImageRenderer::CalculateMeshData( MeshType type, const Vector2& targetSize, bool usePixelArea )
+{
+  mMeshType        = type;
+  mGeometrySize    = targetSize;
+  mUsePixelArea    = usePixelArea;
+  mIsMeshGenerated = false;
+}
+
+void ImageRenderer::TextureDiscarded( ResourceId textureId )
+{
+  DALI_ASSERT_DEBUG( mTextureId == textureId || mTextureId == 0 );
+
+  mTextureId = 0;
+  mTexture = NULL;
+}
+
+void ImageRenderer::GlContextDestroyed()
+{
+  if( mVertexBuffer )
+  {
+    mVertexBuffer->GlContextDestroyed();
+  }
+  if( mIndexBuffer )
+  {
+    mIndexBuffer->GlContextDestroyed();
+  }
+  // force recreation of the geometry in next render
+  mIsMeshGenerated = false;
+}
+
+void ImageRenderer::GlCleanup()
+{
+  DALI_LOG_INFO( gImageRenderFilter, Debug::Verbose, "GlCleanup() textureId=%d  texture:%p\n", mTextureId, mTexture);
+
+  mVertexBuffer.Reset();
+  mIndexBuffer.Reset();
+}
+
+bool ImageRenderer::RequiresDepthTest() const
+{
+  return false;
+}
+
+bool ImageRenderer::CheckResources()
+{
+  if( mTexture == NULL )
+  {
+    if ( mTextureCacheDELETEME )
+    {
+      mTexture = mTextureCacheDELETEME->GetTexture( mTextureId );
+    }
+  }
+
+  if( mTexture == NULL )
+  {
+    return false;
+  }
+
+  if( ( mTexture->GetWidth() <= 0u ) ||
+      ( mTexture->GetHeight() <= 0u ) )
+  {
+    return false;
+  }
+
+  Integration::ResourceId shaderTextureId =  mShader->GetTextureIdToRender() ;
+
+  if( shaderTextureId &&  mTextureCacheDELETEME->GetTexture( shaderTextureId ) == NULL )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+bool ImageRenderer::IsOutsideClipSpace( Context& context, const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix )
+{
+  context.IncrementRendererCount();
+
+  Rect<float> boundingBox( mGeometrySize.x * -0.5f, mGeometrySize.y * -0.5f, mGeometrySize.x, mGeometrySize.y );
+
+  DEBUG_BOUNDING_BOX( *mContext, boundingBox, modelViewProjectionMatrix );
+
+  if(Is2dBoxOutsideClipSpace( modelMatrix, modelViewProjectionMatrix, boundingBox ) )
+  {
+    context.IncrementCulledCount();
+    return true;
+  }
+  return false;
+}
+
+void ImageRenderer::DoRender( Context& context, TextureCache& textureCache, BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix )
+{
+  DALI_LOG_INFO( gImageRenderFilter, Debug::Verbose, "DoRender() textureId=%d  texture:%p\n", mTextureId, mTexture);
+
+  DALI_ASSERT_DEBUG( 0 != mTextureId && "ImageRenderer::DoRender. mTextureId == 0." );
+  DALI_ASSERT_DEBUG( NULL != mTexture && "ImageRenderer::DoRender. mTexture == NULL." );
+
+  if(! mIsMeshGenerated )
+  {
+    GenerateMeshData( mTexture );
+  }
+
+  DALI_ASSERT_DEBUG( mVertexBuffer );
+
+  mTextureCacheDELETEME->BindTexture( mTexture, mTextureId,  GL_TEXTURE_2D, TEXTURE_UNIT_IMAGE );
+
+  if( mTexture->GetTextureId() == 0 )
+  {
+    return; // early out if we haven't got a GL texture yet (e.g. due to context loss)
+  }
+
+  mTexture->ApplySampler( TEXTURE_UNIT_IMAGE, mSamplerBitfield );
+
+  // Set sampler uniform
+  GLint samplerLoc = program.GetUniformLocation( Program::UNIFORM_SAMPLER );
+  if( -1 != samplerLoc )
+  {
+    // set the uniform
+    program.SetUniform1i( samplerLoc, TEXTURE_UNIT_IMAGE );
+  }
+
+  // make sure the vertex is bound, this has to be done before
+  // we call VertexAttribPointer otherwise you get weird output on the display
+  mVertexBuffer->Bind();
+
+  samplerLoc = program.GetUniformLocation( Program::UNIFORM_SAMPLER_RECT );
+  if( -1 != samplerLoc )
+  {
+    UvRect uv;
+
+    if ( mUsePixelArea )
+    {
+      mTexture->GetTextureCoordinates( uv, &mPixelArea );
+    }
+    else
+    {
+      mTexture->GetTextureCoordinates( uv, NULL );
+    }
+
+    // set the uniform
+    program.SetUniform4f( samplerLoc, uv.u0, uv.v0, uv.u2, uv.v2 );
+  }
+
+  // Check whether the program supports the expected attributes/uniforms
+  const GLint positionLoc = program.GetAttribLocation( Program::ATTRIB_POSITION );
+  const GLint texCoordLoc = program.GetAttribLocation( Program::ATTRIB_TEXCOORD );
+
+  if ( positionLoc != -1 )
+  {
+    context.EnableVertexAttributeArray( positionLoc );
+
+    const int stride = 4 * sizeof(float);
+    context.VertexAttribPointer( positionLoc, 2, GL_FLOAT, GL_FALSE, stride, 0 );
+  }
+
+  if ( texCoordLoc != -1 )
+  {
+    context.EnableVertexAttributeArray( texCoordLoc );
+
+    const int stride = 4 * sizeof(float);
+    context.VertexAttribPointer( texCoordLoc, 2, GL_FLOAT, GL_FALSE, stride, (const void*) (sizeof(float)*2) );
+  }
+
+  switch(mMeshType)
+  {
+    case QUAD:
+    case NINE_PATCH:
+    case NINE_PATCH_NO_CENTER:
+    {
+      const GLsizei vertexCount = mVertexBuffer->GetBufferSize() / sizeof(Vertex2D); // compiler will optimize this to >> if possible
+      context.DrawArrays( GL_TRIANGLE_STRIP, 0, vertexCount );
+      break;
+    }
+    case GRID_QUAD:
+    case GRID_NINE_PATCH:
+    case GRID_NINE_PATCH_NO_CENTER:
+    {
+      const GLsizei indexCount = mIndexBuffer->GetBufferSize() / sizeof(GLushort); // compiler will optimize this to >> if possible
+      mIndexBuffer->Bind();
+      context.DrawElements( GL_TRIANGLES, indexCount, GL_UNSIGNED_SHORT, 0 );
+      break;
+    }
+  }
+
+  if ( positionLoc != -1 )
+  {
+    context.DisableVertexAttributeArray( positionLoc );
+  }
+
+  if ( texCoordLoc != -1 )
+  {
+    context.DisableVertexAttributeArray( texCoordLoc );
+  }
+}
+
+void ImageRenderer::UpdateVertexBuffer( Context& context, GLsizeiptr size, const GLvoid *data )
+{
+  // create/destroy if needed/not needed.
+  if ( size && !mVertexBuffer )
+  {
+    mVertexBuffer = new GpuBuffer( context, GpuBuffer::ARRAY_BUFFER, GpuBuffer::DYNAMIC_DRAW );
+  }
+  else if ( !size && mVertexBuffer )
+  {
+    mVertexBuffer.Reset();
+  }
+
+  // update
+  if ( mVertexBuffer )
+  {
+    mVertexBuffer->UpdateDataBuffer( size, data );
+  }
+}
+
+void ImageRenderer::UpdateIndexBuffer( Context& context, GLsizeiptr size, const GLvoid *data )
+{
+  // create/destroy if needed/not needed.
+  if ( size && !mIndexBuffer )
+  {
+    mIndexBuffer = new GpuBuffer( context, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
+  }
+  else if ( !size && mIndexBuffer )
+  {
+    mIndexBuffer.Reset();
+  }
+
+  // update
+  if ( mIndexBuffer )
+  {
+    mIndexBuffer->UpdateDataBuffer(size,data);
+  }
+}
+
+void ImageRenderer::GenerateMeshData( Texture* texture )
+{
+  const PixelArea* pixelArea = NULL;
+  if( mUsePixelArea )
+  {
+    pixelArea = &mPixelArea;
+  }
+
+  switch( mMeshType )
+  {
+    case ImageRenderer::QUAD:
+    {
+      SetQuadMeshData( texture, mGeometrySize, pixelArea );
+      break;
+    }
+    case ImageRenderer::NINE_PATCH:
+    {
+      SetNinePatchMeshData( texture, mGeometrySize, mBorder, mBorderInPixels, pixelArea, false );
+      break;
+    }
+    case ImageRenderer::NINE_PATCH_NO_CENTER:
+    {
+      SetNinePatchMeshData( texture, mGeometrySize, mBorder, mBorderInPixels, pixelArea, true );
+      break;
+    }
+    case ImageRenderer::GRID_QUAD:
+    {
+      SetGridMeshData( texture, mGeometrySize, NULL, false, pixelArea );
+      break;
+    }
+    case ImageRenderer::GRID_NINE_PATCH:
+    case ImageRenderer::GRID_NINE_PATCH_NO_CENTER:
+    {
+      SetGridMeshData( texture, mGeometrySize, &mBorder, mBorderInPixels, pixelArea );
+      break;
+    }
+  }
+  mIsMeshGenerated = true;
+}
+
+void ImageRenderer::SetQuadMeshData( Texture* texture, const Vector2& size, const PixelArea* pixelArea )
+{
+  const float x0 = -0.5f * size.x;
+  const float y0 = -0.5f * size.y;
+  const float x1 =  0.5f * size.x;
+  const float y1 =  0.5f * size.y;
+
+  /*
+   * Here we render the square as a single square, as texture
+   * coordinates linearly interpolate between the 4 vertices.
+   *
+   * Note: a square (or a quad) is rendered as 2 triangles.
+   * Vertices 0,1,2 represent triangle A.
+   * Vertices 1,2,3 represent triangle B.
+   *
+   * No indices are needed as we tell GL to render in strip mode
+   * (GL_TRIANGLE_STRIP), which is faster, and consumes less
+   * memory.
+   *
+   *  0---------2
+   *  |        /|
+   *  |  A    / |
+   *  |      /  |
+   *  |     /   |
+   *  |    /    |
+   *  |   /     |
+   *  |  /      |
+   *  | /    B  |
+   *  |/        |
+   *  1---------3
+   */
+
+  Vertex2D verts[]={
+                     {x0, y0, 0.0, 0.0},
+                     {x0, y1, 0.0, 1.0},
+                     {x1, y0, 1.0, 0.0},
+                     {x1, y1, 1.0, 1.0}
+                   };
+
+  // We may only be displaying an area of the texture.
+  // Calling MapUV converts the u,v values to correct values for the pixel area
+
+  texture->MapUV( sizeof(verts)/sizeof(Vertex2D), verts, pixelArea );
+
+  UpdateVertexBuffer( *mContextDELETEME, sizeof(verts), verts );
+  UpdateIndexBuffer( *mContextDELETEME, 0, NULL );
+}
+
+void ImageRenderer::SetNinePatchMeshData( Texture* texture, const Vector2& size, const Vector4& border, bool borderInPixels, const PixelArea* pixelArea, bool noCenter )
+{
+  DALI_ASSERT_ALWAYS( mTexture->GetWidth()  > 0.0f && "Invalid Texture width" );
+  DALI_ASSERT_ALWAYS( mTexture->GetHeight() > 0.0f && "Invalid Texture height" );
+
+  float textureWidth  = mTexture->GetWidth();
+  float textureHeight = mTexture->GetHeight();
+
+  float borderLeft, borderTop, borderRight, borderBottom; // pixels from edge
+  float borderX0, borderY0, borderX1, borderY1; // In the range 0 -> 1
+
+  if ( borderInPixels )
+  {
+    borderLeft   = border.x;
+    borderTop    = border.y;
+    borderRight  = border.z;
+    borderBottom = border.w;
+
+    borderX0 = border.x / textureWidth;
+    borderY0 = border.y / textureHeight;
+    borderX1 = 1.0f - ( border.z / textureWidth );
+    borderY1 = 1.0f - ( border.w / textureHeight );
+  }
+  else
+  {
+    borderLeft   = textureWidth  * border.x;
+    borderTop    = textureHeight * border.y;
+    borderRight  = textureWidth  * (1.0f - border.z);
+    borderBottom = textureHeight * (1.0f - border.w);
+
+    borderX0 = border.x;
+    borderY0 = border.y;
+    borderX1 = border.z;
+    borderY1 = border.w;
+  }
+
+  const float u0 = 0.0f;
+  const float u3 = 1.0f;
+  const float u1 = borderX0;
+  const float u2 = borderX1;
+
+  const float v0 = 0.0f;
+  const float v3 = 1.0f;
+  const float v1 = borderY0;
+  const float v2 = borderY1;
+
+  const float x0 = size.x * -0.5;
+  const float x1 = x0 + borderLeft;
+  const float x2 = x0 + size.x - borderRight;
+  const float x3 = x0 + size.x;
+
+  const float y0 = size.y * -0.5;
+  const float y1 = y0 + borderTop;
+  const float y2 = y0 + size.y - borderBottom;
+  const float y3 = y0 + size.y;
+
+
+  if ( !noCenter )
+  {
+    /*
+     * We're breaking a quad in to 9 smaller quads, so that when it's
+     * stretched the corners maintain their size.
+     * For speed the 9-patch is drawn with a single triangle span, the draw
+     * order of the span is 1->9.
+     * Previously it would draw three separate spans (1->3, 4->6, 7->9), but now it
+     * it does it one go by turning the corner when gets to the end of each row.
+     *
+     * No indices are needed as we tell GL to render in strip mode
+     * (GL_TRIANGLE_STRIP), which is faster, and consumes less
+     * memory.
+     *
+     *  |---|---------------|---|
+     *  |  7|    --> 8      | 9 |
+     *  |---|---------------|---|
+     *  |   |               |   |
+     *  | 6 |     <-- 5     | 4 |
+     *  |   |               |   |
+     *  |   |               |   |
+     *  |---|---------------|---|
+     *  | 1 |      2 -->    | 3 |
+     *  |---|---------------|---|
+     */
+
+    Vertex2D vertsWithCenter[]={
+                                 // bottom left
+                                 {  x0, y0, u0, v0 },
+                                 {  x0, y1, u0, v1 },
+                                 {  x1, y0, u1, v0 },
+                                 {  x1, y1, u1, v1 },
+
+                                 // bottom middle
+                                 {  x2, y0, u2, v0 },
+                                 {  x2, y1, u2, v1 },
+
+                                 // bottom right
+                                 {  x3, y0, u3, v0 },
+                                 {  x3, y1, u3, v1 },
+
+                                 // turn the corner
+                                 {  x3, y1, u3, v1 },
+                                 {  x3, y1, u3, v1 },
+
+                                 // 10 verts here
+
+                                 // middle right
+                                 {  x3, y2, u3, v2 },
+                                 {  x2, y1, u2, v1 },
+                                 {  x2, y2, u2, v2 },
+
+                                 // middle left
+
+                                 {  x1, y1, u1, v1 },
+                                 {  x1, y2, u1, v2 },
+                                 {  x0, y1, u0, v1 },
+                                 {  x0, y2, u0, v2 },
+
+                                 // turn the corner
+                                 {  x0, y2, u0, v2 },
+                                 {  x0, y2, u0, v2 },
+
+                                 // top left
+                                 {  x0, y3, u0, v3 },
+                                 {  x1, y2, u1, v2 },
+                                 {  x1, y3, u1, v3 },
+
+                                 // top middle
+                                 {  x2, y2, u2, v2 },
+                                 {  x2, y3, u2, v3 },
+
+                                 // top right
+                                 {  x3, y2, u3, v2 },
+                                 {  x3, y3, u3, v3 },
+                               };
+
+    const size_t vertsSize = sizeof( vertsWithCenter );
+    const unsigned int vertexCount = vertsSize / sizeof( vertsWithCenter[0] );
+    texture->MapUV( vertexCount, vertsWithCenter, pixelArea );
+    UpdateVertexBuffer( *mContextDELETEME, vertsSize, vertsWithCenter );
+  }
+  else
+  {
+    /*
+     * The center part is not going to be rendered. The 9-patch border is drawn with
+     * a single triangle span, and the draw order of the span is 1->8.
+     *
+     *  |---|---------------|---|
+     *  | 7 |    <-- 6      | 5 |
+     *  |---|---------------|---|
+     *  |   |               |   |
+     *  |   |               |   |
+     *  | 8 |               | 4 |
+     *  |   | (not rendered)|   |
+     *  |   |               |   |
+     *  |---|---------------|---|
+     *  | 1 |      2 -->    | 3 |
+     *  |---|---------------|---|
+     */
+
+    Vertex2D vertsWithNoCenter[]={
+                                   // bottom left (1)
+                                   {  x0, y0, u0, v0 },
+                                   {  x0, y1, u0, v1 },
+                                   {  x1, y0, u1, v0 },
+                                   {  x1, y1, u1, v1 },
+
+                                   // bottom middle (2)
+                                   {  x2, y0, u2, v0 },
+                                   {  x2, y1, u2, v1 },
+
+                                   // bottom right (3)
+                                   {  x3, y0, u3, v0 },
+                                   {  x3, y1, u3, v1 },
+
+                                   // reset the starting point to x3, y1
+                                   {  x3, y1, u3, v1 },
+                                   {  x3, y1, u3, v1 },
+
+                                   // middle right (4)
+                                   {  x3, y2, u3, v2 },
+                                   {  x2, y1, u2, v1 },
+                                   {  x2, y2, u2, v2 },
+
+                                   // corner turning
+                                   {  x2, y2, u2, v2 },
+                                   {  x3, y2, u3, v2 },
+                                   {  x3, y2, u3, v2 },
+
+                                   // top right (5)
+                                   {  x3, y3, u3, v3 },
+                                   {  x2, y2, u2, v2 },
+                                   {  x2, y3, u2, v3 },
+
+                                   // top middle (6)
+                                   {  x1, y2, u1, v2 },
+                                   {  x1, y3, u1, v3 },
+
+                                   // reset point to x0,y3
+                                   {  x1, y3, u1, v3 },
+                                   {  x0, y3, u0, v3 },
+                                   {  x0, y3, u0, v3 },
+
+                                   // top left box (starting from (x0,y3)) (7)
+                                   {  x0, y2, u0, v2 },
+                                   {  x1, y3, u1, v3 },
+                                   {  x1, y2, u1, v2 },
+
+                                   // reset point
+                                   {  x1, y2, u1, v2 },
+
+                                   // middle left (8)
+                                   {  x0, y2, u0, v2 },
+                                   {  x1, y1, u1, v2 },
+                                   {  x0, y1, u0, v2 },
+                                 };
+
+    const size_t vertsSize = sizeof( vertsWithNoCenter );
+    const unsigned int vertexCount = vertsSize / sizeof( vertsWithNoCenter[0] );
+    texture->MapUV( vertexCount, vertsWithNoCenter, pixelArea );
+    UpdateVertexBuffer( *mContextDELETEME, vertsSize, vertsWithNoCenter );
+  }
+  // not using an index buffer
+  UpdateIndexBuffer( *mContextDELETEME, 0, NULL );
+
+}
+
+void ImageRenderer::SetGridMeshData( Texture* texture, const Vector2& size, const Vector4* border, bool borderInPixels, const PixelArea* pixelArea )
+{
+  /*
+   * Quad Grid:
+   * In Grid Mode, we tessellate the single quad into smaller quads
+   * at approximately (guideGridSize x guideGridSize) in size.
+   *
+   * Conversion of Quad to Gridded Quad.
+   *
+   * |-----------|    |---|---|---|
+   * |           |    |   |   |   |
+   * |           | -> |---|---|---|
+   * |           |    |   |   |   |
+   * |-----------|    |---|---|---|
+   *
+   * 9-Patch Grid:
+   * In Grid Mode, we tessellate each quad of a 9-patch
+   * (see SetNinePatchMeshData) into smaller quads at approximately
+   * (guideGridSize x guideGridSize) in size.
+   *
+   * This satisfies the two requirements of a 9-patch with grid:
+   *
+   * 1. Texture coordinates within each section of the 9-patch
+   * should change linearly to that 9-patch's rules.
+   * 2. The image as as whole should provide Vertex points at
+   * approximate guideGridSize intervals.
+   *
+   * The result should be the horizontal and vertical lines of
+   * a 9-patch overlayed by the horizontal and vertical lines of
+   * a grid.
+   *
+   * Non-overlayed:
+   *  |     |     |     |     |     |     | <- Grid Markers
+   * -|-------|-------------------|-------|
+   *  |       |                   |       |
+   *  |   1   |         2         |   3   |
+   * -|       |                   |       |
+   *  |-------+-------------------+-------|
+   *  |       |                   |       |
+   * -|       |                   |       |
+   *  |       |                   |       |
+   *  |       |                   |       |
+   * -|   4   |         5         |   6   | <- 9 Patch.
+   *  |       |                   |       |
+   *  |       |                   |       |
+   * -|       |                   |       |
+   *  |       |                   |       |
+   *  |-------+-------------------+-------|
+   * -|       |                   |       |
+   *  |   7   |         8         |   9   |
+   *  |       |                   |       |
+   * -|-------|-------------------|-------|
+   *
+   *
+   * Overlayed:
+   *  |     |     |     |     |     |     | <- Grid Markers
+   * -|-------|-------------------|-------|
+   *  |     | |   |     |     |   | |     |
+   *  |     | |   |     |     |   | |     |
+   * -|-----|-|---|-----|-----|---|-|-----|
+   *  |-------+-------------------+-------|
+   *  |     | |   |     |     |   | |     |
+   * -|-----|-|---|-----|-----|---|-|-----|
+   *  |     | |   |     |     |   | |     |
+   *  |     | |   |     |     |   | |     |
+   * -|-----|-|---|-----|-----|---|-|-----| <- 9 Patch.
+   *  |     | |   |     |     |   | |     |
+   *  |     | |   |     |     |   | |     |
+   * -|-----|-|---|-----|-----|---|-|-----|
+   *  |     | |   |     |     |   | |     |
+   *  |-------+-------------------+-------|
+   * -|-----|-|---|-----|-----|---|-|-----|
+   *  |     | |   |     |     |   | |     |
+   *  |     | |   |     |     |   | |     |
+   * -|-------|-------------------|-------|
+   */
+
+  std::vector<VertexToTextureCoord> horizontalDivisions;
+  std::vector<VertexToTextureCoord> verticalDivisions;
+
+  const float guideGridSize = mShader->GetGridDensity();
+
+  const int textureWidth = texture->GetWidth();
+  const int textureHeight = texture->GetHeight();
+
+  const float halfWidth = size.width * 0.5f;
+  const float halfHeight = size.height * 0.5f;
+
+  // Determine how many rectangles across and down to tesselate image into.
+  const int guideRectX = (size.width / guideGridSize);
+  const int guideRectY = (size.height / guideGridSize);
+
+  // Build up list of points in X axis where vertices need to go.
+  std::vector<VertexToTextureCoord> insertionList;
+  insertionList.reserve(4);
+  insertionList.push_back( VertexToTextureCoord( -halfWidth, 0.0f ) );
+
+  // If 9-Patch Border exists, add additional border points in list.
+  if(border)
+  {
+    float borderX0, borderX1, borderU0, borderU1;
+
+    if ( borderInPixels )
+    {
+      borderX0 = border->x - halfWidth;
+      borderX1 = halfWidth - border->z;
+
+      borderU0 = border->x / textureWidth;
+      borderU1 = 1.0f - (border->z / textureWidth);
+    }
+    else
+    {
+      borderX0 = border->x * textureWidth - halfWidth;
+      borderX1 = halfWidth - (1.0f - border->z) * textureWidth;
+      borderU0 = border->x;
+      borderU1 = border->z;
+    }
+
+    insertionList.push_back( VertexToTextureCoord( borderX0, borderU0 ) );
+    insertionList.push_back( VertexToTextureCoord( borderX1, borderU1 ) );
+  }
+
+  insertionList.push_back( VertexToTextureCoord( halfWidth, 1.0f ) );
+  GenerateIntervals(horizontalDivisions, guideRectX + 2, insertionList);
+
+  // Build up list of points in Y axis where vertices need to go.
+  insertionList.clear();
+  insertionList.push_back( VertexToTextureCoord( -halfHeight, 0.0f ) );
+
+  // If 9-Patch Border exists, add additional border points in list.
+  if(border)
+  {
+    float borderY0, borderY1, borderU0, borderU1;
+
+    if ( borderInPixels )
+    {
+      borderY0 = border->y - halfHeight;
+      borderY1 = halfHeight - border->w;
+
+      borderU0 = border->y / textureHeight;
+      borderU1 = 1.0f - (border->w / textureHeight);
+    }
+    else
+    {
+      borderY0 = border->y * textureHeight - halfHeight;
+      borderY1 = halfHeight - (1.0f - border->w) * textureHeight;
+
+      borderU0 = border->y;
+      borderU1 = border->w;
+    }
+
+    insertionList.push_back( VertexToTextureCoord( borderY0, borderU0 ) );
+    insertionList.push_back( VertexToTextureCoord( borderY1, borderU1 ) );
+  }
+
+  insertionList.push_back( VertexToTextureCoord( halfHeight, 1.0f ) );
+  GenerateIntervals(verticalDivisions, guideRectY + 2, insertionList);
+
+  // Now build up Vertex pattern based on the above X and Y lists.
+  const int totalVertices = horizontalDivisions.size() * verticalDivisions.size();
+  Vertex2D* vertices = new Vertex2D[totalVertices];
+  Vertex2D* vertex = vertices;
+
+  for(std::vector<VertexToTextureCoord>::const_iterator yIter = verticalDivisions.begin(); yIter != verticalDivisions.end(); ++yIter )
+  {
+    for(std::vector<VertexToTextureCoord>::const_iterator xIter = horizontalDivisions.begin(); xIter != horizontalDivisions.end(); ++xIter )
+    {
+      vertex->mX = xIter->x;
+      vertex->mU = xIter->u;
+      vertex->mY = yIter->x;
+      vertex->mV = yIter->u;
+      vertex++;
+    }
+  }
+
+  // Build up Triangle indicies, very predictable pattern.
+  const size_t rectX = horizontalDivisions.size() - 1;
+  const size_t rectY = verticalDivisions.size() - 1;
+  const size_t totalIndices = rectX * rectY * 6;             // 2 triangles per quad (rect) and 3 points to define each triangle.
+  GLushort* indices = new GLushort[totalIndices];
+
+  GenerateMeshIndices(indices, rectX, rectY);
+
+  texture->MapUV( totalVertices, vertices, pixelArea );
+
+  UpdateVertexBuffer( *mContextDELETEME, totalVertices * sizeof(Vertex2D) , vertices );
+  UpdateIndexBuffer( *mContextDELETEME, totalIndices * sizeof(GLushort), indices );
+
+  delete[] vertices;
+  delete[] indices;
+}
+
+void ImageRenderer::GenerateMeshIndices(GLushort* indices, int rectanglesX, int rectanglesY)
+{
+  GLushort *i = indices;
+  const int meshEndIndex = rectanglesY * (rectanglesX + 1);
+
+  int index = 0;
+  while(index < meshEndIndex)
+  {
+    const int rowEndIndex = index + rectanglesX;
+    for (; index < rowEndIndex; index++ )
+    {
+      *i++ = index;
+      *i++ = index + 1 + rectanglesX;
+      *i++ = index + 1;
+
+      *i++ = index + 1;
+      *i++ = index + 1 + rectanglesX;
+      *i++ = index + 2 + rectanglesX;
+    }
+    index++;    // one extra vertex per row than rects.
+  }
+}
+
+ImageRenderer::ImageRenderer( NodeDataProvider& dataProvider )
+: Renderer( dataProvider ),
+  mTexture( NULL ),
+  mBorder( 0.45, 0.45, 0.1, 0.1 ),
+  mPixelArea(),
+  mGeometrySize(),
+  mTextureId( 0 ),
+  mMeshType( ImageRenderer::QUAD ),
+  mIsMeshGenerated( false ),
+  mBorderInPixels( false ),
+  mUsePixelArea( false )
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/renderers/scene-graph-image-renderer.h b/dali/internal/render/renderers/scene-graph-image-renderer.h
new file mode 100644 (file)
index 0000000..226501b
--- /dev/null
@@ -0,0 +1,231 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_IMAGE_RENDERER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_IMAGE_RENDERER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture-observer.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class GpuBuffer;
+
+namespace SceneGraph
+{
+class NodeDataProvider;
+
+/**
+ * Used to render an image.
+ */
+class ImageRenderer : public Renderer, public TextureObserver
+{
+public:
+
+  typedef Dali::ImageActor::PixelArea PixelArea;
+
+  enum MeshType
+  {
+    QUAD,
+    NINE_PATCH,
+    NINE_PATCH_NO_CENTER,
+    GRID_QUAD,
+    GRID_NINE_PATCH,
+    GRID_NINE_PATCH_NO_CENTER ///< Not supported yet.
+  };
+
+  /**
+   * Create a new ImageRenderer.
+   * @param dataprovider to render
+   * @return The newly allocated ImageRenderer.
+   */
+  static ImageRenderer* New( NodeDataProvider& dataprovider );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~ImageRenderer();
+
+  /**
+   * Set the texture used to render.
+   * @param[in] textureId The id of the texture used to render.
+   */
+  void SetTextureId( ResourceId textureId );
+
+  /**
+   * Set the pixel area for the renderer
+   * @param[in] pixelArea An area within the texture, used when building UV coordinates.
+   */
+  void SetPixelArea( const ImageRenderer::PixelArea& pixelArea );
+
+  /**
+   * Set 9 patch border for the image renderer
+   * @param[in] border The border for nine-patch meshes.
+   * @param[in] borderInPixels True if border is in pixels instead of percentages.
+   */
+  void SetNinePatchBorder( const Vector4& border, bool inPixels );
+
+  /**
+   * Calculate the mesh data used by the ImageRenderer.
+   * @param[in] type The type of mesh data required; either quad, nine-patch or grid.
+   * @param[in] targetSize The size which the mesh data should fit inside.
+   * @param[in] usePixelArea whether to use pixel area or not
+   */
+  void CalculateMeshData( MeshType type, const Vector2& targetSize, bool usePixelArea );
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlContextDestroyed()
+   */
+  virtual void GlContextDestroyed();
+
+  /**
+   * @copydoc Dali::Internal::GlResourceOwner::GlCleanup()
+   */
+  virtual void GlCleanup();
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::Renderer::RequiresDepthTest()
+   */
+  virtual bool RequiresDepthTest() const;
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::Renderer::CheckResources()
+   */
+  virtual bool CheckResources();
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::Renderer::IsOutsideClipSpace()
+   */
+  virtual bool IsOutsideClipSpace( Context& context, const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix );
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::Renderer::DoRender()
+   */
+  virtual void DoRender( Context& context, TextureCache& textureCache, BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix );
+
+protected: // TextureObserver implementation
+
+  /**
+   * @copydoc Dali::Internal::TextureObserver::TextureDiscarded()
+   */
+  virtual void TextureDiscarded( ResourceId textureId );
+
+private:
+  /**
+   * Helper to update the vertex buffer.
+   */
+  void UpdateVertexBuffer( Context& context, GLsizeiptr size, const GLvoid *data );
+
+  /**
+   * Helper to update the index buffer.
+   */
+  void UpdateIndexBuffer( Context& context, GLsizeiptr size, const GLvoid *data );
+
+  /**
+   * Helper to generate mesh data when required
+   * @param[in] texture Texture from which to get UV data
+   */
+  void GenerateMeshData( Texture* texture );
+
+  /**
+   * Helper to fill vertex/index buffers with quad data.
+   * (Quads are simple meshes, and thus have a specialised mesh generation method)
+   *
+   * @param[in] texture Texture from which to get UV data
+   * @param[in] size
+   * @param[in] pixelArea An area within the texture, used when building UV coordinates. A value of NULL means use default image size.
+   */
+  void SetQuadMeshData( Texture* texture, const Vector2& size, const PixelArea* pixelArea );
+
+  /**
+   * Helper to fill vertex/index buffers with nine-patch data.
+   * (9-Patches are simple meshes, and thus have a specialised mesh generation method)
+   *
+   * @param[in] texture Texture from which to get UV data
+   * @param[in] size The target size.
+   * @param[in] border 9 patch border information.
+   * @param[in] borderInPixels True if border is in pixels instead of percentages.
+   * @param[in] pixelArea An area within the texture, used when building UV coordinates. A value of NULL means use default image size.
+   * @param[in] noCenter True if the center section of nine patch should not be rendered.
+   */
+  void SetNinePatchMeshData( Texture* texture, const Vector2& size, const Vector4& border, bool borderInPixels, const PixelArea* pixelArea, bool noCenter );
+
+  /**
+   * Helper to fill vertex/index buffers with grid data.
+   * This can build grid meshes that are either of type Quad or type 9-Patch
+   *
+   * @param[in] size The target size.
+   * @param[in] border 9 patch border information (pass NULL for no border i.e. a standard Quad)
+   * @param[in] borderInPixels True if border is in pixels instead of percentages.
+   * @param[in] pixelArea An area within the texture, used when building UV coordinates. A value of NULL means use default image size.
+   */
+  void SetGridMeshData( Texture* texture, const Vector2& size, const Vector4* border, bool borderInPixels, const PixelArea* pixelArea );
+
+  /**
+   * Helper to fill index buffer with uniform grid data.
+   * @param[in] indices pointer to indices buffer to be filled
+   * @param[in] rectanglesX number of columns for rectangles in grid
+   * @param[in] rectanglesY number of rows for rectangles in grid
+   */
+  void GenerateMeshIndices(GLushort* indices, int rectanglesX, int rectanglesY);
+
+  /**
+   * Private constructor. @see New()
+   */
+  ImageRenderer( NodeDataProvider& dataprovider );
+
+  // Undefined
+  ImageRenderer( const ImageRenderer& );
+
+  // Undefined
+  ImageRenderer& operator=( const ImageRenderer& rhs );
+
+private:
+
+  Texture*    mTexture;
+
+  OwnerPointer< GpuBuffer > mVertexBuffer;
+  OwnerPointer< GpuBuffer > mIndexBuffer;
+
+  Vector4   mBorder;
+  PixelArea mPixelArea;
+  Vector2   mGeometrySize;
+  ResourceId  mTextureId;
+
+  // flags
+  MeshType  mMeshType        : 3; // 4 values fits in 3 bits just fine
+  bool      mIsMeshGenerated : 1;
+  bool      mBorderInPixels  : 1;
+  bool      mUsePixelArea    : 1;
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_IMAGE_RENDERER_H__
diff --git a/dali/internal/render/renderers/scene-graph-renderer-debug.cpp b/dali/internal/render/renderers/scene-graph-renderer-debug.cpp
new file mode 100644 (file)
index 0000000..433cc30
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scene-graph-renderer-debug.h"
+#include <dali/internal/common/shader-data.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/data-providers/node-data-provider.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+namespace
+{
+/* rewritten in another patch
+#if defined ( DEBUG_ENABLED )
+
+// Create shader for debug drawing
+const std::string DEBUG_DRAW_VERTEX_SHADER(
+  "attribute mediump vec3 aPosition;\n"
+  "uniform mediump mat4 uMvpMatrix;\n"
+  "void main()\n"
+  "{\n"
+  "  gl_Position = uMvpMatrix * vec4(aPosition, 1.0);\n"
+  "}\n" );
+
+const std::string DEBUG_DRAW_FRAGMENT_SHADER(
+  "uniform lowp vec4 uColor;\n"
+  "void main()\n"
+  "{\n"
+  "  gl_FragColor = uColor;\n"
+  "}\n" );
+
+static Program* gDebugProgram(NULL); ///< a simple debug shader
+
+#endif
+*/
+} // anonymous namespace
+
+void DebugBoundingBox(Context& context, Rect<float> boundingBox, const Matrix& mvp)
+{
+/* rewritten in another patch
+#if defined ( DEBUG_ENABLED )
+  if( gDebugProgram == NULL )
+  {
+    Internal::ShaderDataPtr shaderData( new Internal::ShaderData( DEBUG_DRAW_VERTEX_SHADER, DEBUG_DRAW_FRAGMENT_SHADER ) );
+    gDebugProgram = Program::New( shaderData.Get(), context, true );
+  }
+
+  context.SetBlend( false );
+  context.CullFace( CullNone );
+
+  const unsigned int numPoints=8;
+  GLfloat vertices[numPoints*3] = {
+    boundingBox.x,                      boundingBox.y, 0.0f,
+    boundingBox.x,                      boundingBox.y + boundingBox.height, 0.0f,
+
+    boundingBox.x,                      boundingBox.y + boundingBox.height, 0.0f,
+    boundingBox.x + boundingBox.width,  boundingBox.y + boundingBox.height, 0.0f,
+
+    boundingBox.x + boundingBox.width,  boundingBox.y + boundingBox.height, 0.0f,
+    boundingBox.x + boundingBox.width,  boundingBox.y, 0.0f,
+
+    boundingBox.x + boundingBox.width,  boundingBox.y, 0.0f,
+    boundingBox.x,                      boundingBox.y, 0.0f,
+  };
+
+  gDebugProgram->Use();
+
+  GpuBuffer vertexBuffer(context,GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW);
+  vertexBuffer.UpdateDataBuffer(numPoints * 3 * sizeof(float), &vertices[0]);
+  vertexBuffer.Bind();
+
+  GLint positionLoc    = gDebugProgram->GetAttribLocation(Program::ATTRIB_POSITION);
+  context.VertexAttribPointer( positionLoc, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0 );
+  context.EnableVertexAttributeArray( positionLoc );
+
+  GLint mvpLoc = gDebugProgram->GetUniformLocation(Program::UNIFORM_MVP_MATRIX);
+  if( mvpLoc != Program::UNIFORM_UNKNOWN )
+  {
+    gDebugProgram->SetUniformMatrix4fv( mvpLoc, 1, mvp.AsFloat() );
+  }
+  GLint colorLoc = gDebugProgram->GetUniformLocation(Program::UNIFORM_COLOR);
+  if( colorLoc != Program::UNIFORM_UNKNOWN )
+  {
+    gDebugProgram->SetUniform4f( colorLoc, 0.0f, 1.0f, 1.0f, 1.0f );
+  }
+
+  context.DrawArrays(GL_LINES, 0, numPoints);
+
+  context.DisableVertexAttributeArray( positionLoc );
+#endif
+*/
+}
+
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/render/renderers/scene-graph-renderer-debug.h b/dali/internal/render/renderers/scene-graph-renderer-debug.h
new file mode 100644 (file)
index 0000000..e174c48
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
+#define __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/rect.h>
+
+// Uncomment to debug bounding boxes of objects
+//#define DEBUG_DISPLAY_BOUNDING_BOX 1
+
+namespace Dali
+{
+namespace Internal
+{
+class Context;
+
+namespace SceneGraph
+{
+class NodeDataProvider;
+
+void DebugBoundingBox(Context& context, Rect<float> boundingBox, const Matrix& mvp);
+
+#if defined(DEBUG_ENABLED) && defined(DEBUG_DISPLAY_BOUNDING_BOX)
+#define DEBUG_BOUNDING_BOX( context, boundingBox, mvp )                     \
+  DebugBoundingBox( context, boundingBox, mvp )
+#else
+#define DEBUG_BOUNDING_BOX( context, boundingBox, mvp )
+#endif
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+
+#endif // __DALI_INTERNAL_SCENEGRAPH_RENDERER_DEBUG_H__
diff --git a/dali/internal/render/renderers/scene-graph-renderer-declarations.h b/dali/internal/render/renderers/scene-graph-renderer-declarations.h
new file mode 100644 (file)
index 0000000..71adfde
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDERER_DECLARATIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDERER_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Renderer;
+
+typedef std::vector<Renderer*>      RendererContainer;
+typedef RendererContainer::iterator RendererIter;
+
+enum EffectType
+{
+  NO_EFFECT,
+  SHADOW_EFFECT,
+  REFLECT_EFFECT
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDERER_DECLARATIONS_H__
diff --git a/dali/internal/render/renderers/scene-graph-renderer.cpp b/dali/internal/render/renderers/scene-graph-renderer.cpp
new file mode 100644 (file)
index 0000000..e612695
--- /dev/null
@@ -0,0 +1,300 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-declarations.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-debug.h>
+#include <dali/internal/render/data-providers/node-data-provider.h>
+#include <dali/public-api/actors/blending.h>
+#include <dali/internal/common/image-sampler.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+static Matrix gModelViewProjectionMatrix( false ); ///< a shared matrix to calculate the MVP matrix, dont want to store it in object to reduce storage overhead
+static Matrix3 gNormalMatrix; ///< a shared matrix to calculate normal matrix, dont want to store it in object to reduce storage overhead
+
+/**
+ * Helper to set view and projection matrices once per program
+ * @param program to set the matrices to
+ * @param modelMatrix to set
+ * @param viewMatrix to set
+ * @param projectionMatrix to set
+ * @param modelViewMatrix to set
+ * @param modelViewProjectionMatrix to set
+ */
+inline void SetMatrices( Program& program,
+                         const Matrix& modelMatrix,
+                         const Matrix& viewMatrix,
+                         const Matrix& projectionMatrix,
+                         const Matrix& modelViewMatrix,
+                         const Matrix& modelViewProjectionMatrix )
+{
+  GLint loc = program.GetUniformLocation(Program::UNIFORM_MODEL_MATRIX);
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    program.SetUniformMatrix4fv( loc, 1, modelMatrix.AsFloat() );
+  }
+  loc = program.GetUniformLocation( Program::UNIFORM_VIEW_MATRIX );
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    if( program.GetViewMatrix() != &viewMatrix )
+    {
+      program.SetViewMatrix( &viewMatrix );
+      program.SetUniformMatrix4fv( loc, 1, viewMatrix.AsFloat() );
+    }
+  }
+  // set projection matrix if program has not yet received it this frame or if it is dirty
+  loc = program.GetUniformLocation( Program::UNIFORM_PROJECTION_MATRIX );
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    if( program.GetProjectionMatrix() != &projectionMatrix )
+    {
+      program.SetProjectionMatrix( &projectionMatrix );
+      program.SetUniformMatrix4fv( loc, 1, projectionMatrix.AsFloat() );
+    }
+  }
+  loc = program.GetUniformLocation(Program::UNIFORM_MODELVIEW_MATRIX);
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    program.SetUniformMatrix4fv( loc, 1, modelViewMatrix.AsFloat() );
+  }
+
+  loc = program.GetUniformLocation( Program::UNIFORM_MVP_MATRIX );
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    program.SetUniformMatrix4fv( loc, 1, modelViewProjectionMatrix.AsFloat() );
+  }
+
+  loc = program.GetUniformLocation( Program::UNIFORM_NORMAL_MATRIX );
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    gNormalMatrix = modelViewMatrix;
+    gNormalMatrix.Invert();
+    gNormalMatrix.Transpose();
+    program.SetUniformMatrix3fv( loc, 1, gNormalMatrix.AsFloat() );
+  }
+}
+
+}
+
+namespace SceneGraph
+{
+
+void Renderer::Initialize( Context& context, TextureCache& textureCache )
+{
+  mContextDELETEME = &context;
+  mTextureCacheDELETEME = &textureCache;
+}
+
+Renderer::~Renderer()
+{
+}
+
+void Renderer::SetShader( Shader* shader )
+{
+  mShader = shader;
+}
+
+void Renderer::SetUseBlend( bool useBlend )
+{
+  mUseBlend = useBlend;
+}
+
+void Renderer::SetBlendingOptions( unsigned int options )
+{
+  mBlendingOptions.SetBitmask( options );
+}
+
+void Renderer::SetBlendColor( const Vector4& color )
+{
+  mBlendingOptions.SetBlendColor( color );
+}
+
+void Renderer::SetCullFace( CullFaceMode mode )
+{
+  DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
+  mCullFaceMode = mode;
+}
+
+void Renderer::SetSampler( unsigned int samplerBitfield )
+{
+  mSamplerBitfield = samplerBitfield;
+}
+
+void Renderer::Render( Context& context,
+                       TextureCache& textureCache,
+                       BufferIndex bufferIndex,
+                       Shader& defaultShader,
+                       const Matrix& modelViewMatrix,
+                       const Matrix& viewMatrix,
+                       const Matrix& projectionMatrix,
+                       float frametime,
+                       bool cull )
+{
+  // @todo MESH_REWORK Fix when merging! :D
+  NewRenderer* renderer = dynamic_cast<NewRenderer*>(this);
+  if( renderer )
+  {
+    // Get the shader from the material:
+    mShader = &renderer->mRenderDataProvider->GetShader();
+  }
+
+  // if mShader is NULL it means we're set to default
+  if( !mShader )
+  {
+    mShader = &defaultShader;
+  }
+
+  if( !CheckResources() )
+  {
+    // CheckResources() is overriden in derived classes.
+    // Prevents modify the GL state if resources are not ready and nothing is to be rendered.
+    return;
+  }
+
+  // Calculate the MVP matrix first so we can do the culling test
+  const Matrix& modelMatrix = mDataProvider.GetModelMatrix( bufferIndex );
+  Matrix::Multiply( gModelViewProjectionMatrix, modelViewMatrix, projectionMatrix );
+
+  // Get the program to use:
+  Program* program = mShader->GetProgram();
+  if( !program )
+  {
+    // if program is NULL it means this is a custom shader with non matching geometry type so we need to use default shaders program
+    program = defaultShader.GetProgram();
+    DALI_ASSERT_DEBUG( program && "Default shader should always have a program available." );
+    if( !program )
+    {
+      DALI_LOG_ERROR( "Failed to get program for shader at address %p.", (void*) &*mShader );
+      return;
+    }
+
+  }
+
+  // Check culling (does not need the program to be in use)
+  if( cull && ! program->ModifiesGeometry() )
+  {
+    if( IsOutsideClipSpace( context, modelMatrix, gModelViewProjectionMatrix ) )
+    {
+      // don't do any further gl state changes as this renderer is not visible
+      return;
+    }
+  }
+
+  // Take the program into use so we can send uniforms to it
+  program->Use();
+
+  DoSetCullFaceMode( context, bufferIndex );
+
+  DoSetBlending( context, bufferIndex );
+
+  // Ignore missing uniforms - custom shaders and flat color shaders don't have SAMPLER
+  // set projection and view matrix if program has not yet received them yet this frame
+  SetMatrices( *program, modelMatrix, viewMatrix, projectionMatrix, modelViewMatrix, gModelViewProjectionMatrix );
+
+  // set color uniform
+  GLint loc = program->GetUniformLocation( Program::UNIFORM_COLOR );
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    const Vector4& color = mDataProvider.GetRenderColor( bufferIndex );
+    program->SetUniform4f( loc, color.r, color.g, color.b, color.a );
+  }
+  loc = program->GetUniformLocation(Program::UNIFORM_TIME_DELTA);
+  if( Program::UNIFORM_UNKNOWN != loc )
+  {
+    program->SetUniform1f( loc, frametime );
+  }
+
+  //@todo MESH_REWORK Remove after removing ImageRenderer
+  DoSetUniforms(context, bufferIndex, mShader, program );
+
+  // subclass rendering and actual draw call
+  DoRender( context, textureCache, bufferIndex, *program, modelViewMatrix, viewMatrix );
+}
+
+// can be overridden by deriving class
+void Renderer::DoSetUniforms(Context& context, BufferIndex bufferIndex, Shader* shader, Program* program )
+{
+  shader->SetUniforms( context, *program, bufferIndex );
+}
+
+// can be overridden by deriving class
+void Renderer::DoSetCullFaceMode(Context& context, BufferIndex bufferIndex )
+{
+  // Set face culling mode
+  context.CullFace( mCullFaceMode );
+}
+
+// can be overridden by deriving class
+void Renderer::DoSetBlending(Context& context, BufferIndex bufferIndex )
+{
+  // Enables/disables blending mode.
+  context.SetBlend( mUseBlend );
+
+  // Set the blend color
+  const Vector4* const customColor = mBlendingOptions.GetBlendColor();
+  if( customColor )
+  {
+    context.SetCustomBlendColor( *customColor );
+  }
+  else
+  {
+    context.SetDefaultBlendColor();
+  }
+
+  // Set blend source & destination factors
+  context.BlendFuncSeparate( mBlendingOptions.GetBlendSrcFactorRgb(),
+                             mBlendingOptions.GetBlendDestFactorRgb(),
+                             mBlendingOptions.GetBlendSrcFactorAlpha(),
+                             mBlendingOptions.GetBlendDestFactorAlpha() );
+
+  // Set blend equations
+  context.BlendEquationSeparate( mBlendingOptions.GetBlendEquationRgb(),
+                                 mBlendingOptions.GetBlendEquationAlpha() );
+
+}
+
+Renderer::Renderer( NodeDataProvider& dataprovider )
+: mDataProvider( dataprovider ),
+  mContextDELETEME(NULL),
+  mTextureCacheDELETEME( NULL ),
+  mShader( NULL ),
+  mSamplerBitfield( ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) ),
+  mUseBlend( false ),
+  mCullFaceMode( CullNone )
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/renderers/scene-graph-renderer.h b/dali/internal/render/renderers/scene-graph-renderer.h
new file mode 100644 (file)
index 0000000..c5ebb7c
--- /dev/null
@@ -0,0 +1,214 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDERER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDERER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/internal/common/blending-options.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+#include <dali/internal/render/gl-resources/gl-resource-owner.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-declarations.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/common/type-abstraction-enums.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class Context;
+class Texture;
+class Program;
+
+namespace SceneGraph
+{
+class SceneController;
+class Shader;
+class TextureCache;
+class NodeDataProvider;
+
+/**
+ * Renderers are used to render images, text, & meshes etc.
+ * These objects are used during RenderManager::Render(), so properties modified during
+ * the Update must either be double-buffered, or set via a message added to the RenderQueue.
+ */
+class Renderer : public GlResourceOwner
+{
+public:
+
+  /**
+   * Second-phase construction.
+   * This is called when the renderer is inside render thread
+   * @param[in] textureCache to use
+   */
+  void Initialize( Context& context, TextureCache& textureCache );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Renderer();
+
+  /**
+   * Set the Shader used to render.
+   * @param[in] shader The shader used to render.
+   */
+  void SetShader( Shader* shader );
+
+  /**
+   * Set whether the ImageRenderer should use blending
+   * @param[in] useBlend True if blending should be used.
+   */
+  void SetUseBlend( bool useBlend );
+
+  /**
+   * Set the blending options.
+   * @param[in] options A bitmask of blending options.
+   */
+  void SetBlendingOptions( unsigned int options );
+
+  /**
+   * Set the blend color.
+   * @param[in] color The new blend-color.
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * Set the face-culling mode.
+   * @param[in] mode The face-culling mode.
+   */
+  void SetCullFace( CullFaceMode mode );
+
+  /**
+   * Set the sampler used to render the set texture.
+   * @param[in] samplerBitfield The packed sampler options used to render.
+   */
+  void SetSampler( unsigned int samplerBitfield );
+
+  /**
+   * Query whether the derived type of Renderer requires depth testing.
+   * @return True if the renderer requires depth testing.
+   */
+  virtual bool RequiresDepthTest() const = 0;
+
+  /**
+   * Called to render during RenderManager::Render().
+   * @param[in] context The context used for rendering
+   * @param[in] textureCache The texture cache used to get textures
+   * @param[in] bufferIndex The index of the previous update buffer.
+   * @param[in] defaultShader in case there is no custom shader
+   * @param[in] modelViewMatrix The model-view matrix.
+   * @param[in] viewMatrix The view matrix.
+   * @param[in] projectionMatrix The projection matrix.
+   * @param[in] frametime The elapsed time between the last two updates.
+   * @param[in] cull Whether to frustum cull this renderer
+   */
+  void Render( Context& context,
+               TextureCache& textureCache,
+               BufferIndex bufferIndex,
+               Shader& defaultShader,
+               const Matrix& modelViewMatrix,
+               const Matrix& viewMatrix,
+               const Matrix& projectionMatrix,
+               float frametime,
+               bool cull );
+
+protected:
+  /**
+   * Protected constructor; only derived classes can be instantiated.
+   * @param dataprovider for rendering
+   */
+  Renderer( NodeDataProvider& dataprovider );
+
+private:
+
+  // Undefined
+  Renderer( const Renderer& );
+
+  // Undefined
+  Renderer& operator=( const Renderer& rhs );
+
+  /**
+   * Checks if renderer's resources are ready to be used.
+   *
+   * @return \e true if they are. Otherwise \e false.
+   */
+  virtual bool CheckResources() = 0;
+
+  /**
+   * Checks if renderer is culled.
+   * @param[in] modelMatrix The model matrix.
+   * @param[in] modelViewProjectionMatrix The MVP matrix.
+   * @return \e true if it is. Otherwise \e false.
+   */
+  virtual bool IsOutsideClipSpace( Context& context, const Matrix& modelMatrix, const Matrix& modelViewProjectionMatrix ) = 0;
+
+  /**
+   * Called from Render prior to DoRender().
+   * @todo MESH_REWORK Remove after merge
+   */
+  virtual void DoSetUniforms( Context& context, BufferIndex bufferIndex, Shader* shader, Program* program );
+
+  /**
+   * Called from Render prior to DoRender(). Default method to set CullFaceMode
+   * @todo MESH_REWORK Remove after merge
+   */
+  virtual void DoSetCullFaceMode( Context& context, BufferIndex bufferIndex );
+
+  /**
+   * Called from Render prior to DoRender(). Default method to set blending options
+   * @todo MESH_REWORK Remove after merge
+   */
+  virtual void DoSetBlending( Context& context, BufferIndex bufferIndex );
+
+  /**
+   * Called from Render; implemented in derived classes.
+   * @param[in] context The context used for rendering
+   * @param[in] textureCache The texture cache used to get textures
+   * @param[in] bufferIndex The index of the previous update buffer.
+   * @param[in] program to use.
+   * @param[in] modelViewMatrix The model-view matrix.
+   * @param[in] viewMatrix The view matrix.
+   */
+  virtual void DoRender( Context& context, TextureCache& textureCache, BufferIndex bufferIndex, Program& program, const Matrix& modelViewMatrix, const Matrix& viewMatrix ) = 0;
+
+protected:
+
+  NodeDataProvider& mDataProvider;        // @todo MESH_REWORK rename to mNodeDataProvider. Shouldn't it be const?
+
+  Context* mContextDELETEME; // TODO: MESH_REWORK DELETE THIS
+  TextureCache* mTextureCacheDELETEME; // TODO: MESH_REWORK DELETE THIS
+  Shader* mShader;
+  unsigned int mSamplerBitfield;          ///< Sampler options used for texture filtering
+
+  bool mUseBlend:1;                 ///< True if blending should be enabled, 1 bit is enough
+private:
+
+  BlendingOptions mBlendingOptions;
+  CullFaceMode mCullFaceMode:3;     ///< cullface enum, 3 bits is enough
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDERER_H__
diff --git a/dali/internal/render/shader-source/README b/dali/internal/render/shader-source/README
new file mode 100644 (file)
index 0000000..26166ad
--- /dev/null
@@ -0,0 +1,18 @@
+Automatic Shader String Generation
+----------------------------------
+
+ - The filename of the shaders determines the strings that are generated.
+ - Ensure your shader is named according to the following rules:
+   - All lowercase.
+   - Word separation using "-".
+   - Suffix should be ".txt".
+   - For example: "my-new-shader.txt".
+ - Both the vertex and the fragment shader should be stored in the same text file.
+ - The vertex shader should be encapsulated within "<VertexShader>" and "</VertexShader>".
+ - The fragment shader should be encapsulated within "<FragmentShader>" and "</FragmentShader>".
+ - A header and a source file will be automatically generated using this information.
+   - They will contain several string constants.
+   - The generated strings will be in camel case using the dashes to separate out the words.
+     - e.g, for "my-new-shader.txt", we will get "MyNewShaderVertex" & "MyNewShaderFragment".
+ - When you wish to use these strings in your code, you should include the file "dali-shaders.h".
+
diff --git a/dali/internal/render/shader-source/image.txt b/dali/internal/render/shader-source/image.txt
new file mode 100644 (file)
index 0000000..7851fa7
--- /dev/null
@@ -0,0 +1,44 @@
+<VertexShader>
+
+attribute mediump vec3  aPosition;
+attribute mediump vec2  aTexCoord;
+
+uniform   mediump mat4  uModelView;
+uniform   mediump mat4  uProjection;
+uniform   mediump mat4  uMvpMatrix;
+uniform   mediump mat3  uNormalMatrix;
+uniform   mediump mat4  uModelMatrix;
+uniform   mediump mat4  uViewMatrix;
+
+uniform   mediump vec4  uColor;
+
+varying   mediump vec2  vTexCoord;
+
+uniform   mediump vec4  sTextureRect;
+uniform   mediump vec4  sEffectRect;
+
+void main()
+{
+  gl_Position = uMvpMatrix * vec4(aPosition, 1.0);
+  vTexCoord = aTexCoord;
+}
+
+</VertexShader>
+
+<FragmentShader>
+
+uniform sampler2D sTexture;
+uniform sampler2D sEffect;
+
+uniform mediump vec4 sTextureRect;
+uniform mediump vec4 sEffectRect;
+
+uniform mediump vec4 uColor;
+varying mediump vec2 vTexCoord;
+
+void main()
+{
+  gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;
+}
+
+</FragmentShader>
diff --git a/dali/internal/render/shaders/custom-uniform.cpp b/dali/internal/render/shaders/custom-uniform.cpp
new file mode 100644 (file)
index 0000000..082fbb5
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/shaders/custom-uniform.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/shaders/program.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+CustomUniform::CustomUniform()
+: mCacheIndex( 0 )
+{
+}
+
+CustomUniform::~CustomUniform()
+{
+}
+
+void CustomUniform::Initialize( Program& program, const char* name )
+{
+  mCacheIndex = program.RegisterUniform( name );
+}
+
+void CustomUniform::Reset()
+{
+  mCacheIndex = 0;
+}
+
+int CustomUniform::GetUniformLocation( Program& program, const char* name )
+{
+  if( 0 == mCacheIndex )
+  {
+    Initialize( program, name );
+  }
+
+  return program.GetUniformLocation( mCacheIndex );
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/shaders/custom-uniform.h b/dali/internal/render/shaders/custom-uniform.h
new file mode 100644 (file)
index 0000000..e718f7f
--- /dev/null
@@ -0,0 +1,79 @@
+#ifndef __DALI_INTERNAL_CUSTOM_UNIFORM_H__
+#define __DALI_INTERNAL_CUSTOM_UNIFORM_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Program;
+
+/**
+ * Helper class to handle the index of the custom uniforms
+ */
+class CustomUniform
+{
+public: // API
+
+  /**
+   * Creates a custom uniform
+   */
+  CustomUniform();
+
+  /**
+   * Destructor, nonvirtual as not a base class
+   */
+  ~CustomUniform();
+
+  /**
+   * Initializes the custom uniform. Should be called only once
+   * @param program to use
+   * @param name of the uniform
+   */
+  void Initialize( Program& program, const char* name );
+
+  /**
+   * Resets the custom uniform in case program was changed
+   */
+  void Reset();
+
+  /**
+   * Gets the uniform location for custom uniform
+   * @param program to use
+   * @param name of the uniform
+   */
+  int GetUniformLocation( Program& program, const char* name );
+
+private: // Data
+
+  unsigned int mCacheIndex; ///< internal cache index
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_CUSTOM_UNIFORM_H__
+
diff --git a/dali/internal/render/shaders/program-cache.h b/dali/internal/render/shaders/program-cache.h
new file mode 100644 (file)
index 0000000..7c40a01
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __DALI_INTERNAL_PROGRAM_CACHE_H__
+#define __DALI_INTERNAL_PROGRAM_CACHE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-abstraction.h> // for GLenum
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Program;
+
+/**
+ * This class is interface for caching Program objects
+ */
+class ProgramCache
+{
+public:
+
+  /**
+   * Constructor
+   */
+  ProgramCache()
+  { }
+
+  /**
+   * Destructor, virtual as this is an interface
+   */
+  virtual ~ProgramCache()
+  { }
+
+public: // API
+
+  /**
+   * @return GlAbstraction
+   */
+  virtual Integration::GlAbstraction& GetGlAbstraction() = 0;
+
+  /**
+   * Get the program from cache with hash
+   * @param shaderHash to use
+   * @return program
+   */
+  virtual Program* GetProgram( size_t shaderHash ) = 0;
+
+  /**
+   * Add a program to cache
+   * @param shaderHash of the program
+   * @param program to add
+   */
+  virtual void AddProgram( size_t shaderHash, Program* program ) = 0;
+
+  /**
+   * Get currently bound program
+   * @return program that is currently used
+   */
+  virtual Program* GetCurrentProgram() = 0;
+
+  /**
+   * Set the currently bound program
+   * @param program that is used
+   */
+  virtual void SetCurrentProgram( Program* program ) = 0;
+
+  /**
+   * @return true if program binaries are supported
+   */
+  virtual bool IsBinarySupported() = 0;
+
+  /**
+   * @return the binary format to use
+   */
+  virtual GLenum ProgramBinaryFormat() = 0;
+
+  /**
+   * @param programData to store/save
+   */
+  virtual void StoreBinary( Internal::ShaderDataPtr programData ) = 0;
+
+private: // not implemented as non-copyable
+
+  ProgramCache( const ProgramCache& rhs );
+  ProgramCache& operator=( const ProgramCache& rhs );
+
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROGRAM_CACHE_H__
+
diff --git a/dali/internal/render/shaders/program-controller.cpp b/dali/internal/render/shaders/program-controller.cpp
new file mode 100644 (file)
index 0000000..0958710
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/shaders/program-controller.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/common/shader-saver.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/common/post-process-resource-dispatcher.h>
+#include <dali/internal/render/gl-resources/gl-call-debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ProgramController::ProgramController( Integration::GlAbstraction& glAbstraction )
+: mShaderSaver( 0 ),
+  mGlAbstraction( glAbstraction ),
+  mCurrentProgram( NULL ),
+  mProgramBinaryFormat( 0 ),
+  mNumberOfProgramBinaryFormats( 0 )
+{
+  // we have 17 default programs so make room for those and a few custom ones as well
+  mProgramCache.Reserve( 32 );
+}
+
+ProgramController::~ProgramController()
+{
+}
+
+void ProgramController::ResetProgramMatrices()
+{
+  const ProgramIterator end = mProgramCache.End();
+  for ( ProgramIterator iter = mProgramCache.Begin(); iter != end; ++iter )
+  {
+    Program* program = (*iter)->GetProgram();
+    program->SetProjectionMatrix( NULL );
+    program->SetViewMatrix( NULL );
+  }
+}
+
+void ProgramController::GlContextCreated()
+{
+  // reset any potential previous errors
+  LOG_GL( "GetError()\n" );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.GetError() );
+
+  // find out if program binaries are supported and the format enum as well
+  Dali::Vector<GLint> programBinaryFormats;
+
+  CHECK_GL( mGlAbstraction, mGlAbstraction.GetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &mNumberOfProgramBinaryFormats ) );
+  LOG_GL("GetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES) = %d\n", mNumberOfProgramBinaryFormats );
+
+  if( GL_NO_ERROR == mGlAbstraction.GetError() && 0 < mNumberOfProgramBinaryFormats )
+  {
+    programBinaryFormats.Resize( mNumberOfProgramBinaryFormats );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, &programBinaryFormats[0] ) );
+    LOG_GL("GetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES) = %d\n", programBinaryFormats[0] );
+    mProgramBinaryFormat = programBinaryFormats[0];
+  }
+}
+
+void ProgramController::GlContextDestroyed()
+{
+  mNumberOfProgramBinaryFormats = 0;
+  mProgramBinaryFormat = 0;
+
+  SetCurrentProgram( NULL );
+  // Inform programs they are no longer valid
+  const ProgramIterator end = mProgramCache.End();
+  for ( ProgramIterator iter = mProgramCache.Begin(); iter != end; ++iter )
+  {
+    (*iter)->GetProgram()->GlContextDestroyed();
+  }
+}
+
+Integration::GlAbstraction& ProgramController::GetGlAbstraction()
+{
+  return mGlAbstraction;
+}
+
+Program* ProgramController::GetProgram( size_t shaderHash )
+{
+  Program* program = NULL;
+  const ProgramIterator end = mProgramCache.End();
+  for ( ProgramIterator iter = mProgramCache.Begin(); iter != end; ++iter )
+  {
+    size_t hash = (*iter)->GetHash();
+    if( shaderHash == hash )
+    {
+      program = (*iter)->GetProgram();
+      break;
+    }
+  }
+  return program;
+}
+
+void ProgramController::AddProgram( size_t shaderHash, Program* program )
+{
+  // we expect unique hash values so its event thread sides job to guarantee that
+  // AddProgram is only called after program checks that GetProgram returns NULL
+  mProgramCache.PushBack( new ProgramPair( program, shaderHash ) );
+}
+
+Program* ProgramController::GetCurrentProgram()
+{
+  return mCurrentProgram;
+}
+
+void ProgramController::SetCurrentProgram( Program* program )
+{
+  mCurrentProgram = program;
+}
+
+bool ProgramController::IsBinarySupported()
+{
+  return mNumberOfProgramBinaryFormats > 0;
+}
+
+unsigned int ProgramController::ProgramBinaryFormat()
+{
+  return mProgramBinaryFormat;
+}
+
+void ProgramController::StoreBinary( Internal::ShaderDataPtr programData )
+{
+  DALI_ASSERT_DEBUG( programData->GetBufferSize() > 0 );
+  DALI_ASSERT_DEBUG( mShaderSaver && "SetShaderSaver() should have been called during startup." );
+
+  if( mShaderSaver != NULL )
+  {
+    mShaderSaver->SaveBinary( programData );
+  }
+}
+
+void ProgramController::SetShaderSaver( ShaderSaver& shaderSaver )
+{
+  mShaderSaver = &shaderSaver;
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/shaders/program-controller.h b/dali/internal/render/shaders/program-controller.h
new file mode 100644 (file)
index 0000000..3ceb2a9
--- /dev/null
@@ -0,0 +1,193 @@
+#ifndef __DALI_INTERNAL_PROGRAM_CONTROLLER_H__
+#define __DALI_INTERNAL_PROGRAM_CONTROLLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/shaders/program-cache.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ShaderSaver;
+
+/**
+ * This class is the owner of GL shader programs
+ */
+class ProgramController : public ProgramCache
+{
+public:
+
+  /**
+   * Wrapper for a program and its hash code
+   */
+  class ProgramPair
+  {
+  public: // API
+
+    /**
+     * Constructor
+     * @param program
+     * @param shaderHash
+     */
+    ProgramPair( Program* program, size_t shaderHash )
+    : mProgram( program ), mShaderHash( shaderHash )
+    { }
+
+    /**
+     * Destructor, non-virtual as not a base
+     */
+    ~ProgramPair()
+    {
+      delete mProgram;
+    }
+
+    /**
+     * Inline getter for the program
+     * @return the program
+     */
+    inline Program* GetProgram()
+    {
+      return mProgram;
+    }
+
+    /**
+     * Inline getter for the hash
+     * @return the hash
+     */
+    inline size_t GetHash()
+    {
+      return mShaderHash;
+    }
+
+  private: // Not implemented
+    ProgramPair( const ProgramPair& );
+    ProgramPair& operator=( const ProgramPair& );
+
+  private: // Data
+    Program* mProgram;
+    size_t mShaderHash;
+  };
+
+  /**
+   * Constructor
+   * @param postProcessDispatcher to send save binary message back to update
+   */
+  ProgramController( Integration::GlAbstraction& glAbstraction );
+
+  /**
+   * Destructor, non virtual as not a base class
+   */
+  ~ProgramController();
+
+public: // API
+
+  /**
+   * Resets the program matrices. Must be called at the beginning of every frame
+   */
+  void ResetProgramMatrices();
+
+  /**
+   * Notifies the cache that context is (re)created
+   */
+  void GlContextCreated();
+
+  /**
+   * Notifies cache that context is lost
+   */
+  void GlContextDestroyed();
+
+  /**
+   * Set the destination for compiler shader binaries so they can be saved.
+   * @note Must be called during initialisation.
+   */
+  void SetShaderSaver( ShaderSaver& shaderSaver );
+
+private: // From ProgramCache
+
+  /**
+   * @copydoc ProgramCache::GetGlAbstraction
+   */
+  virtual Integration::GlAbstraction& GetGlAbstraction();
+
+  /**
+   * @copydoc ProgramCache::GetProgram
+   */
+  virtual Program* GetProgram( size_t shaderHash );
+
+  /**
+   * @copydoc ProgramCache::AddProgram
+   */
+  virtual void AddProgram( size_t shaderHash, Program* program );
+
+  /**
+   * @copydoc ProgramCache::GetCurrentProgram
+   */
+  virtual Program* GetCurrentProgram();
+
+  /**
+   * @copydoc ProgramCache::SetCurrentProgram
+   */
+  virtual void SetCurrentProgram( Program* program );
+
+  /**
+   * @copydoc ProgramCache::IsBinarySupported
+   */
+  virtual bool IsBinarySupported();
+
+  /**
+   * @copydoc ProgramCache::ProgramBinaryFormat
+   */
+  virtual GLenum ProgramBinaryFormat();
+
+  /**
+   * @copydoc ProgramCache::StoreBinary
+   */
+  virtual void StoreBinary( Internal::ShaderDataPtr programData );
+
+private: // not implemented as non-copyable
+
+  ProgramController( const ProgramController& rhs );
+  ProgramController& operator=( const ProgramController& rhs );
+
+private: // Data
+
+  ShaderSaver* mShaderSaver;
+  Integration::GlAbstraction& mGlAbstraction;
+  Program* mCurrentProgram;
+
+  typedef OwnerContainer< ProgramPair* > ProgramContainer;
+  typedef ProgramContainer::Iterator ProgramIterator;
+  ProgramContainer mProgramCache;
+
+  GLint mProgramBinaryFormat;
+  GLint mNumberOfProgramBinaryFormats;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROGRAM_CONTROLLER_H__
+
diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp
new file mode 100644 (file)
index 0000000..0c5ba69
--- /dev/null
@@ -0,0 +1,712 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/shaders/program.h>
+
+// EXTERNAL INCLUDES
+#include <iomanip>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/common/shader-data.h>
+#include <dali/integration-api/gl-defines.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/shaders/program-cache.h>
+#include <dali/internal/render/gl-resources/gl-call-debug.h>
+
+namespace
+{
+void LogWithLineNumbers( const char * source )
+{
+  unsigned int lineNumber = 0u;
+  const char *prev = source;
+  const char *ptr = prev;
+
+  while( true )
+  {
+    if(lineNumber > 200u)
+    {
+      break;
+    }
+    // seek the next end of line or end of text
+    while( *ptr!='\n' && *ptr != '\0' )
+    {
+      ++ptr;
+    }
+
+    std::string line( prev, ptr-prev );
+    Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, "%4d %s\n", lineNumber, line.c_str());
+
+    if( *ptr == '\0' )
+    {
+      break;
+    }
+    prev = ++ptr;
+    ++lineNumber;
+  }
+}
+
+} //namespace
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// LOCAL STUFF
+namespace
+{
+
+const char* gStdAttribs[ Program::ATTRIB_TYPE_LAST ] =
+{
+  "aPosition",    // ATTRIB_POSITION
+  "aNormal",      // ATTRIB_NORMAL
+  "aTexCoord",    // ATTRIB_TEXCOORD
+  "aColor",       // ATTRIB_COLOR
+  "aBoneWeights", // ATTRIB_BONE_WEIGHTS
+  "aBoneIndices"  // ATTRIB_BONE_INDICES
+};
+
+const char* gStdUniforms[ Program::UNIFORM_TYPE_LAST ] =
+{
+  "uMvpMatrix",           // UNIFORM_MVP_MATRIX
+  "uModelView",           // UNIFORM_MODELVIEW_MATRIX
+  "uProjection",          // UNIFORM_PROJECTION_MATRIX
+  "uModelMatrix",         // UNIFORM_MODEL_MATRIX,
+  "uViewMatrix",          // UNIFORM_VIEW_MATRIX,
+  "uNormalMatrix",        // UNIFORM_NORMAL_MATRIX
+  "uColor",               // UNIFORM_COLOR
+  "uCustomTextureCoords", // UNIFORM_CUSTOM_TEXTURE_COORDS
+  "sTexture",             // UNIFORM_SAMPLER
+  "sTextureRect",         // UNIFORM_SAMPLER_RECT
+  "sEffect",              // UNIFORM_EFFECT_SAMPLER
+  "sEffectRect",          // UNIFORM_EFFECT_SAMPLER_RECT
+  "uTimeDelta",           // UNIFORM_TIME_DELTA
+  "sOpacityTexture",      // UNIFORM_SAMPLER_OPACITY
+  "sNormalMapTexture",    // UNIFORM_SAMPLER_NORMAL_MAP
+  "uSize"                 // UNIFORM_SIZE
+};
+
+}  // <unnamed> namespace
+
+// IMPLEMENTATION
+
+Program* Program::New( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
+{
+  size_t shaderHash = shaderData->GetHashValue();
+  Program* program = cache.GetProgram( shaderHash );
+
+  if( NULL == program )
+  {
+    // program not found so create it
+    program = new Program( cache, shaderData, modifiesGeometry );
+
+    // we want to lazy load programs so dont do a Load yet, it gets done in Use()
+
+    cache.AddProgram( shaderHash, program );
+  }
+
+  return program;
+}
+
+void Program::Use()
+{
+  if ( !mLinked )
+  {
+    Load();
+  }
+
+  if ( mLinked )
+  {
+    if ( this != mCache.GetCurrentProgram() )
+    {
+      LOG_GL( "UseProgram(%d)\n", mProgramId );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.UseProgram(mProgramId) );
+
+      mCache.SetCurrentProgram( this );
+    }
+  }
+}
+
+bool Program::IsUsed()
+{
+  return ( this == mCache.GetCurrentProgram() );
+}
+
+GLint Program::GetAttribLocation( AttribType type )
+{
+  DALI_ASSERT_DEBUG(type != ATTRIB_UNKNOWN);
+
+  return GetCustomAttributeLocation( type );
+}
+
+unsigned int Program::RegisterCustomAttribute( const std::string& name )
+{
+  unsigned int index = 0;
+  // find the value from cache
+  for( ;index < mAttributeLocations.size(); ++index )
+  {
+    if( mAttributeLocations[ index ].first == name )
+    {
+      // name found so return index
+      return index;
+    }
+  }
+  // if we get here, index is one past end so push back the new name
+  mAttributeLocations.push_back( std::make_pair( name, ATTRIB_UNKNOWN ) );
+  return index;
+}
+
+GLint Program::GetCustomAttributeLocation( unsigned int attributeIndex )
+{
+  // debug check that index is within name cache
+  DALI_ASSERT_DEBUG( mAttributeLocations.size() > attributeIndex );
+
+  // check if we have already queried the location of the attribute
+  GLint location = mAttributeLocations[ attributeIndex ].second;
+
+  if( location == ATTRIB_UNKNOWN )
+  {
+    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetAttribLocation( mProgramId, mAttributeLocations[ attributeIndex ].first.c_str() ) );
+
+    mAttributeLocations[ attributeIndex ].second = location;
+    LOG_GL( "GetAttributeLocation(program=%d,%s) = %d\n", mProgramId, mAttributeLocations[ attributeIndex ].first.c_str(), mAttributeLocations[ attributeIndex ].second );
+  }
+
+  return location;
+}
+
+
+unsigned int Program::RegisterUniform( const std::string& name )
+{
+  unsigned int index = 0;
+  // find the value from cache
+  for( ;index < mUniformLocations.size(); ++index )
+  {
+    if( mUniformLocations[ index ].first == name )
+    {
+      // name found so return index
+      return index;
+    }
+  }
+  // if we get here, index is one past end so push back the new name
+  mUniformLocations.push_back( std::make_pair( name, UNIFORM_NOT_QUERIED ) );
+  return index;
+}
+
+GLint Program::GetUniformLocation( unsigned int uniformIndex )
+{
+  // debug check that index is within name cache
+  DALI_ASSERT_DEBUG( mUniformLocations.size() > uniformIndex );
+
+  // check if we have already queried the location of the uniform
+  GLint location = mUniformLocations[ uniformIndex ].second;
+
+  if( location == UNIFORM_NOT_QUERIED )
+  {
+    location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetUniformLocation( mProgramId, mUniformLocations[ uniformIndex ].first.c_str() ) );
+
+    mUniformLocations[ uniformIndex ].second = location;
+    LOG_GL( "GetUniformLocation(program=%d,%s) = %d\n", mProgramId, mUniformLocations[ uniformIndex ].first.c_str(), mUniformLocations[ uniformIndex ].second );
+  }
+
+  return location;
+}
+
+void Program::SetUniform1i( GLint location, GLint value0 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // check if uniform location fits the cache
+  if( location >= MAX_UNIFORM_CACHE_SIZE )
+  {
+    // not cached, make the gl call
+    LOG_GL( "Uniform1i(%d,%d)\n", location, value0 );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform1i( location, value0 ) );
+  }
+  else
+  {
+    // check if the value is different from what's already been set
+    if( value0 != mUniformCacheInt[ location ] )
+    {
+      // make the gl call
+      LOG_GL( "Uniform1i(%d,%d)\n", location, value0 );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform1i( location, value0 ) );
+      // update cache
+      mUniformCacheInt[ location ] = value0;
+    }
+  }
+}
+
+void Program::SetUniform4i( GLint location, GLint value0, GLint value1, GLint value2, GLint value3 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // Not caching these as based on current analysis this is not called that often by our shaders
+  LOG_GL( "Uniform4i(%d,%d,%d,%d,%d)\n", location, value0, value1, value2, value3 );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform4i( location, value0, value1, value2, value3 ) );
+}
+
+void Program::SetUniform1f( GLint location, GLfloat value0 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // check if uniform location fits the cache
+  if( location >= MAX_UNIFORM_CACHE_SIZE )
+  {
+    // not cached, make the gl call
+    LOG_GL( "Uniform1f(%d,%f)\n", location, value0 );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform1f( location, value0 ) );
+  }
+  else
+  {
+    // check if the same value has already been set, reset if it is different
+    if( ( fabsf(value0 - mUniformCacheFloat[ location ]) >= Math::MACHINE_EPSILON_1 ) )
+    {
+      // make the gl call
+      LOG_GL( "Uniform1f(%d,%f)\n", location, value0 );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform1f( location, value0 ) );
+
+      // update cache
+      mUniformCacheFloat[ location ] = value0;
+    }
+  }
+}
+
+void Program::SetUniform2f( GLint location, GLfloat value0, GLfloat value1 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // Not caching these as based on current analysis this is not called that often by our shaders
+  LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) );
+}
+
+void Program::SetUniform3f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // Not caching these as based on current analysis this is not called that often by our shaders
+  LOG_GL( "Uniform3f(%d,%f,%f,%f)\n", location, value0, value1, value2 );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform3f( location, value0, value1, value2 ) );
+}
+
+void Program::SetUniform4f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2, GLfloat value3 )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // check if uniform location fits the cache
+  if( location >= MAX_UNIFORM_CACHE_SIZE )
+  {
+    // not cached, make the gl call
+    LOG_GL( "Uniform4f(%d,%f,%f,%f,%f)\n", location, value0, value1, value2, value3 );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform4f( location, value0, value1, value2, value3 ) );
+  }
+  else
+  {
+    // check if the same value has already been set, reset if any component is different
+    // checking index 3 first because we're often animating alpha (rgba)
+    if( ( fabsf(value3 - mUniformCacheFloat4[ location ][ 3 ]) >= Math::MACHINE_EPSILON_1 )||
+        ( fabsf(value0 - mUniformCacheFloat4[ location ][ 0 ]) >= Math::MACHINE_EPSILON_1 )||
+        ( fabsf(value1 - mUniformCacheFloat4[ location ][ 1 ]) >= Math::MACHINE_EPSILON_1 )||
+        ( fabsf(value2 - mUniformCacheFloat4[ location ][ 2 ]) >= Math::MACHINE_EPSILON_1 ) )
+    {
+      // make the gl call
+      LOG_GL( "Uniform4f(%d,%f,%f,%f,%f)\n", location, value0, value1, value2, value3 );
+      CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform4f( location, value0, value1, value2, value3 ) );
+      // update cache
+      mUniformCacheFloat4[ location ][ 0 ] = value0;
+      mUniformCacheFloat4[ location ][ 1 ] = value1;
+      mUniformCacheFloat4[ location ][ 2 ] = value2;
+      mUniformCacheFloat4[ location ][ 3 ] = value3;
+    }
+  }
+}
+
+void Program::SetUniformMatrix4fv( GLint location, GLsizei count, const GLfloat* value )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+  // Not caching these calls. Based on current analysis this is called very often
+  // but with different values (we're using this for MVP matrices)
+  // NOTE! we never want driver or GPU to transpose
+  LOG_GL( "UniformMatrix4fv(%d,%d,GL_FALSE,%x)\n", location, count, value );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.UniformMatrix4fv( location, count, GL_FALSE, value ) );
+}
+
+void Program::SetUniformMatrix3fv( GLint location, GLsizei count, const GLfloat* value )
+{
+  DALI_ASSERT_DEBUG( IsUsed() ); // should not call this if this program is not used
+
+  if( UNIFORM_UNKNOWN == location )
+  {
+    // From http://www.khronos.org/opengles/sdk/docs/man/xhtml/glUniform.xml : Notes
+    // If location is equal to UNIFORM_UNKNOWN, the data passed in will be silently ignored and the
+    // specified uniform variable will not be changed.following opengl silently do nothing
+    return;
+  }
+
+
+  // Not caching these calls. Based on current analysis this is called very often
+  // but with different values (we're using this for MVP matrices)
+  // NOTE! we never want driver or GPU to transpose
+  LOG_GL( "UniformMatrix3fv(%d,%d,GL_FALSE,%x)\n", location, count, value );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.UniformMatrix3fv( location, count, GL_FALSE, value ) );
+}
+
+void Program::GlContextCreated()
+{
+}
+
+void Program::GlContextDestroyed()
+{
+  mLinked = false;
+  mVertexShaderId = 0;
+  mFragmentShaderId = 0;
+  mProgramId = 0;
+
+  ResetAttribsUniformCache();
+}
+
+bool Program::ModifiesGeometry()
+{
+  return mModifiesGeometry;
+}
+
+Program::Program( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
+: mCache( cache ),
+  mGlAbstraction( mCache.GetGlAbstraction() ),
+  mProjectionMatrix( NULL ),
+  mViewMatrix( NULL ),
+  mLinked( false ),
+  mVertexShaderId( 0 ),
+  mFragmentShaderId( 0 ),
+  mProgramId( 0 ),
+  mProgramData(shaderData),
+  mModifiesGeometry( modifiesGeometry )
+{
+  // reserve space for standard attributes
+  mAttributeLocations.reserve( ATTRIB_TYPE_LAST );
+  for( int i=0; i<ATTRIB_TYPE_LAST; ++i )
+  {
+    RegisterCustomAttribute( gStdAttribs[i] );
+  }
+
+  // reserve space for standard uniforms
+  mUniformLocations.reserve( UNIFORM_TYPE_LAST );
+  // reset built in uniform names in cache
+  for( int i = 0; i < UNIFORM_TYPE_LAST; ++i )
+  {
+    RegisterUniform( gStdUniforms[ i ] );
+  }
+  // reset values
+  ResetAttribsUniformCache();
+}
+
+Program::~Program()
+{
+  Unload();
+}
+
+void Program::Load()
+{
+  DALI_ASSERT_ALWAYS( NULL != mProgramData.Get() && "Program data is not initialized" );
+  DALI_ASSERT_DEBUG( mProgramId == 0 && "mProgramId != 0, so about to leak a GL resource by overwriting it." );
+
+  LOG_GL( "CreateProgram()\n" );
+  mProgramId = CHECK_GL( mGlAbstraction, mGlAbstraction.CreateProgram() );
+
+  GLint linked = GL_FALSE;
+
+  const bool binariesSupported = mCache.IsBinarySupported();
+
+  // if shader binaries are supported and ShaderData contains compiled bytecode?
+  if( binariesSupported && mProgramData->HasBinary() )
+  {
+    DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - Using Compiled Shader, Size = %d\n", mProgramData->GetBufferSize());
+
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ProgramBinary(mProgramId, mCache.ProgramBinaryFormat(), mProgramData->GetBufferData(), mProgramData->GetBufferSize()) );
+
+    CHECK_GL( mGlAbstraction, mGlAbstraction.ValidateProgram(mProgramId) );
+
+    GLint success;
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv( mProgramId, GL_VALIDATE_STATUS, &success ) );
+
+    DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "ValidateProgram Status = %d\n", success);
+
+    CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv( mProgramId, GL_LINK_STATUS, &linked ) );
+
+    if( GL_FALSE == linked )
+    {
+      DALI_LOG_ERROR("Failed to load program binary \n");
+
+      GLint nLength;
+      CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv( mProgramId, GL_INFO_LOG_LENGTH, &nLength) );
+      if(nLength > 0)
+      {
+        Dali::Vector< char > szLog;
+        szLog.Reserve( nLength ); // Don't call Resize as we don't want to initialise the data, just reserve a buffer
+        CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramInfoLog( mProgramId, nLength, &nLength, szLog.Begin() ) );
+        DALI_LOG_ERROR( "Program Link Error: %s\n", szLog.Begin() );
+      }
+    }
+    else
+    {
+      mLinked = true;
+      DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Reused binary.\n" );
+    }
+  }
+
+  // Fall back to compiling and linking the vertex and fragment sources
+  if( GL_FALSE == linked )
+  {
+    DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - Runtime compilation\n");
+    if( CompileShader( GL_VERTEX_SHADER, mVertexShaderId, mProgramData->GetVertexShader() ) )
+    {
+      if( CompileShader( GL_FRAGMENT_SHADER, mFragmentShaderId, mProgramData->GetFragmentShader() ) )
+      {
+        Link();
+
+        if( binariesSupported && mLinked )
+        {
+          GLint  binaryLength = 0;
+          GLenum binaryFormat;
+          DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Compiled and linked.\n\nVS:\n%s\nFS:\n%s\n", mProgramData->GetVertexShader(), mProgramData->GetFragmentShader() );
+
+          CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength) );
+          DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - GL_PROGRAM_BINARY_LENGTH_OES: %d\n", binaryLength);
+          if( binaryLength > 0 )
+          {
+            // Allocate space for the bytecode in ShaderData
+            mProgramData->AllocateBuffer(binaryLength);
+            // Copy the bytecode to ShaderData
+            CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramBinary(mProgramId, binaryLength, NULL, &binaryFormat, mProgramData->GetBufferData()) );
+            mCache.StoreBinary( mProgramData );
+            DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Saved binary.\n" );
+          }
+        }
+      }
+    }
+  }
+
+  // No longer needed
+  FreeShaders();
+}
+
+void Program::Unload()
+{
+  FreeShaders();
+
+  if( this == mCache.GetCurrentProgram() )
+  {
+    CHECK_GL( mGlAbstraction, mGlAbstraction.UseProgram(0) );
+
+    mCache.SetCurrentProgram( NULL );
+  }
+
+  if (mProgramId)
+  {
+    LOG_GL( "DeleteProgram(%d)\n", mProgramId );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteProgram( mProgramId ) );
+    mProgramId = 0;
+  }
+
+  mLinked = false;
+
+}
+
+bool Program::CompileShader( GLenum shaderType, GLuint& shaderId, const char* src )
+{
+  if (!shaderId)
+  {
+    LOG_GL( "CreateShader(%d)\n", shaderType );
+    shaderId = CHECK_GL( mGlAbstraction, mGlAbstraction.CreateShader( shaderType ) );
+    LOG_GL( "AttachShader(%d,%d)\n", mProgramId, shaderId );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.AttachShader( mProgramId, shaderId ) );
+  }
+
+  LOG_GL( "ShaderSource(%d)\n", shaderId );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.ShaderSource(shaderId, 1, &src, NULL ) );
+
+  LOG_GL( "CompileShader(%d)\n", shaderId );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.CompileShader( shaderId ) );
+
+  GLint compiled;
+  LOG_GL( "GetShaderiv(%d)\n", shaderId );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.GetShaderiv( shaderId, GL_COMPILE_STATUS, &compiled ) );
+
+  if (compiled == GL_FALSE)
+  {
+    DALI_LOG_ERROR("Failed to compile shader\n");
+    LogWithLineNumbers(src);
+
+    GLint nLength;
+    mGlAbstraction.GetShaderiv( shaderId, GL_INFO_LOG_LENGTH, &nLength);
+    if(nLength > 0)
+    {
+      Dali::Vector< char > szLog;
+      szLog.Reserve( nLength ); // Don't call Resize as we don't want to initialise the data, just reserve a buffer
+      mGlAbstraction.GetShaderInfoLog( shaderId, nLength, &nLength, szLog.Begin() );
+      DALI_LOG_ERROR( "Shader Compiler Error: %s\n", szLog.Begin() );
+    }
+
+    DALI_ASSERT_ALWAYS( 0 && "Shader compilation failure" );
+  }
+
+  return compiled != 0;
+}
+
+void Program::Link()
+{
+  LOG_GL( "LinkProgram(%d)\n", mProgramId );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.LinkProgram( mProgramId ) );
+
+  GLint linked;
+  LOG_GL( "GetProgramiv(%d)\n", mProgramId );
+  CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv( mProgramId, GL_LINK_STATUS, &linked ) );
+
+  if (linked == GL_FALSE)
+  {
+    DALI_LOG_ERROR("Shader failed to link \n");
+
+    GLint nLength;
+    mGlAbstraction.GetProgramiv( mProgramId, GL_INFO_LOG_LENGTH, &nLength);
+    if(nLength > 0)
+    {
+      Dali::Vector< char > szLog;
+      szLog.Reserve( nLength ); // Don't call Resize as we don't want to initialise the data, just reserve a buffer
+      mGlAbstraction.GetProgramInfoLog( mProgramId, nLength, &nLength, szLog.Begin() );
+      DALI_LOG_ERROR( "Shader Link Error: %s\n", szLog.Begin() );
+    }
+
+    DALI_ASSERT_ALWAYS( 0 && "Shader linking failure" );
+  }
+
+  mLinked = linked != GL_FALSE;
+}
+
+void Program::FreeShaders()
+{
+  if (mVertexShaderId)
+  {
+    LOG_GL( "DeleteShader(%d)\n", mVertexShaderId );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DetachShader( mProgramId, mVertexShaderId ) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteShader( mVertexShaderId ) );
+    mVertexShaderId = 0;
+  }
+
+  if (mFragmentShaderId)
+  {
+    LOG_GL( "DeleteShader(%d)\n", mFragmentShaderId );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DetachShader( mProgramId, mFragmentShaderId ) );
+    CHECK_GL( mGlAbstraction, mGlAbstraction.DeleteShader( mFragmentShaderId ) );
+    mFragmentShaderId = 0;
+  }
+}
+
+void Program::ResetAttribsUniformCache()
+{
+  // reset attribute locations
+  for( unsigned i = 0; i < mAttributeLocations.size() ; ++i )
+  {
+    mAttributeLocations[ i ].second = ATTRIB_UNKNOWN;
+  }
+
+  // reset all gl uniform locations
+  for( unsigned int i = 0; i < mUniformLocations.size(); ++i )
+  {
+    // reset gl program locations and names
+    mUniformLocations[ i ].second = UNIFORM_NOT_QUERIED;
+  }
+
+  // reset uniform cache
+  for( int i = 0; i < MAX_UNIFORM_CACHE_SIZE; ++i )
+  {
+    // GL initializes uniforms to 0
+    mUniformCacheInt[ i ] = 0;
+    mUniformCacheFloat[ i ] = 0.0f;
+    mUniformCacheFloat4[ i ][ 0 ] = 0.0f;
+    mUniformCacheFloat4[ i ][ 1 ] = 0.0f;
+    mUniformCacheFloat4[ i ][ 2 ] = 0.0f;
+    mUniformCacheFloat4[ i ][ 3 ] = 0.0f;
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/shaders/program.h b/dali/internal/render/shaders/program.h
new file mode 100644 (file)
index 0000000..50d02d6
--- /dev/null
@@ -0,0 +1,374 @@
+#ifndef __DALI_INTERNAL_PROGRAM_H__
+#define __DALI_INTERNAL_PROGRAM_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/integration-api/gl-abstraction.h>
+#include <dali/internal/common/shader-data.h>
+
+namespace Dali
+{
+
+class Matrix;
+
+namespace Integration
+{
+class GlAbstraction;
+class ShaderData;
+}
+
+namespace Internal
+{
+
+class ProgramCache;
+
+/*
+ * A program contains a vertex & fragment shader.
+ *
+ * A program will contain vertex attributes and uniform variables.
+ *
+ * uColor is set to the value specified by Actor::SetColor and is
+ * animatable through the property Actor::COLOR
+ */
+class Program
+{
+public:
+
+  /**
+   * Size of the uniform cache per program
+   * GLES specification states that minimum uniform count for fragment shader
+   * is 16 and for vertex shader 128. We're caching the 16 common ones for now
+   */
+  static const int MAX_UNIFORM_CACHE_SIZE = 16;
+
+  /**
+   * Constant for uniform / attribute not found
+   */
+  static const int NOT_FOUND = -1;
+
+  /**
+   * Vertex attributes
+   */
+  enum AttribType
+  {
+    ATTRIB_UNKNOWN = -1,
+    ATTRIB_POSITION,
+    ATTRIB_NORMAL,
+    ATTRIB_TEXCOORD,
+    ATTRIB_COLOR,
+    ATTRIB_BONE_WEIGHTS,
+    ATTRIB_BONE_INDICES,
+    ATTRIB_TYPE_LAST
+  };
+
+  /**
+   * Common shader uniform names
+   */
+  enum UniformType
+  {
+    UNIFORM_NOT_QUERIED = -2,
+    UNIFORM_UNKNOWN = -1,
+    UNIFORM_MVP_MATRIX,
+    UNIFORM_MODELVIEW_MATRIX,
+    UNIFORM_PROJECTION_MATRIX,
+    UNIFORM_MODEL_MATRIX,
+    UNIFORM_VIEW_MATRIX,
+    UNIFORM_NORMAL_MATRIX,
+    UNIFORM_COLOR,
+    UNIFORM_CUSTOM_TEXTURE_COORDS,
+    UNIFORM_SAMPLER,
+    UNIFORM_SAMPLER_RECT,
+    UNIFORM_EFFECT_SAMPLER,
+    UNIFORM_EFFECT_SAMPLER_RECT,
+    UNIFORM_TIME_DELTA,
+    UNIFORM_SAMPLER_OPACITY,
+    UNIFORM_SAMPLER_NORMAL_MAP,
+
+    UNIFORM_SIZE,
+    UNIFORM_TYPE_LAST
+  };
+
+  /**
+   * Creates a new program, or returns a copy of an existing program in the program cache
+   * @param[in] cache where the programs are stored
+   * @param[in] shaderData  A pointer to a data structure containing the program source
+   *                        and optionally precompiled binary. If the binary is empty the program bytecode
+   *                        is copied into it after compilation and linking)
+   * @param[in] modifiesGeometry True if the shader modifies geometry
+   * @return pointer to the program
+   */
+  static Program* New( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry );
+
+  /**
+   * Takes this program into use
+   */
+  void Use();
+
+  /**
+   * @return true if this program is used currently
+   */
+  bool IsUsed();
+
+  /**
+   * @param [in] type of the attribute
+   * @return the index of the attribute
+   */
+  GLint GetAttribLocation( AttribType type );
+
+  /**
+   * Register an attribute name in our local cache
+   * @param [in] name attribute name
+   * @return the index of the attribute name in local cache
+   */
+  unsigned int RegisterCustomAttribute( const std::string& name );
+
+  /**
+   * Gets the location of a pre-registered attribute.
+   * @param [in] attributeIndex of the attribute in local cache
+   * @return the index of the attribute in the GL program
+   */
+  GLint GetCustomAttributeLocation( unsigned int attributeIndex );
+
+  /**
+   * Register a uniform name in our local cache
+   * @param [in] name uniform name
+   * @return the index of the uniform name in local cache
+   */
+  unsigned int RegisterUniform( const std::string& name );
+
+  /**
+   * Gets the location of a pre-registered uniform.
+   * Uniforms in list UniformType are always registered and in the order of the enumeration
+   * @param [in] uniformIndex of the uniform in local cache
+   * @return the index of the uniform in the GL program
+   */
+  GLint GetUniformLocation( unsigned int uniformIndex );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as int
+   */
+  void SetUniform1i( GLint location, GLint value0 );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as int
+   * @param [in] value1 as int
+   * @param [in] value2 as int
+   * @param [in] value3 as int
+   */
+  void SetUniform4i( GLint location, GLint value0, GLint value1, GLint value2, GLint value3 );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as float
+   */
+  void SetUniform1f( GLint location, GLfloat value0 );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as float
+   * @param [in] value1 as float
+   */
+  void SetUniform2f( GLint location, GLfloat value0, GLfloat value1 );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as float
+   * @param [in] value1 as float
+   * @param [in] value2 as float
+   */
+  void SetUniform3f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2 );
+
+  /**
+   * Sets the uniform value
+   * @param [in] location of uniform
+   * @param [in] value0 as float
+   * @param [in] value1 as float
+   * @param [in] value2 as float
+   * @param [in] value3 as float
+   */
+  void SetUniform4f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2, GLfloat value3 );
+
+  /**
+   * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
+   * so make sure your matrix is in correct order for GL.
+   * @param [in] location Location of uniform
+   * @param [in] count Count of matrices
+   * @param [in] value values as float pointers
+   */
+  void SetUniformMatrix4fv( GLint location, GLsizei count, const GLfloat* value );
+
+  /**
+   * Sets the uniform value as matrix. NOTE! we never want GPU to transpose
+   * so make sure your matrix is in correct order for GL.
+   * @param [in] location Location of uniform
+   * @param [in] count Count of matrices
+   * @param [in] value values as float pointers
+   */
+  void SetUniformMatrix3fv( GLint location, GLsizei count, const GLfloat* value );
+
+  /**
+   * Needs to be called when GL context is (re)created
+   */
+  void GlContextCreated();
+
+  /**
+   * Needs to be called when GL context is destroyed
+   */
+  void GlContextDestroyed();
+
+  /**
+   * @return true if this program modifies geometry
+   */
+  bool ModifiesGeometry();
+
+  /**
+   * Set the projection matrix that has currently been sent
+   * @param matrix to set
+   */
+  void SetProjectionMatrix( const Matrix* matrix )
+  {
+    mProjectionMatrix = matrix;
+  }
+
+  /**
+   * Get the projection matrix that has currently been sent
+   * @return the matrix that is set
+   */
+  const Matrix* GetProjectionMatrix()
+  {
+    return mProjectionMatrix;
+  }
+
+  /**
+   * Set the projection matrix that has currently been sent
+   * @param matrix to set
+   */
+  void SetViewMatrix( const Matrix* matrix )
+  {
+    mViewMatrix = matrix;
+  }
+
+  /**
+   * Get the projection matrix that has currently been sent
+   * @return the matrix that is set
+   */
+  const Matrix* GetViewMatrix()
+  {
+    return mViewMatrix;
+  }
+
+private: // Implementation
+
+  /**
+   * Constructor, private so no direct instantiation
+   * @param[in] cache where the programs are stored
+   * @param[in] shaderData A smart pointer to a data structure containing the program source and binary
+   * @param[in] modifiesGeometry True if the vertex shader changes geometry
+   */
+  Program( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry );
+
+public:
+
+  /**
+   * Destructor, non virtual as no virtual methods or inheritance
+   */
+  ~Program();
+
+private:
+
+  // default constructor, not defined
+  Program();
+  // assignment operator, not defined
+  Program& operator=( const Program& );
+
+  /**
+   * Load the shader, from a precompiled binary if available, else from source code
+   */
+  void Load();
+
+  /**
+   * Unload the shader
+   */
+  void Unload();
+
+  /**
+   * Compile the shader
+   * @param shaderType vertex or fragment shader
+   * @param shaderId of the shader, returned
+   * @param src of the shader
+   * @return true if the compilation succeeded
+   */
+  bool CompileShader(GLenum shaderType, GLuint& shaderId, const char* src);
+
+  /**
+   * Links the shaders together to create program
+   */
+  void Link();
+
+  /**
+   * Frees the shader programs
+   */
+  void FreeShaders();
+
+  /**
+   * Resets caches
+   */
+  void ResetAttribsUniformCache();
+
+private:  // Data
+
+  ProgramCache& mCache;                       ///< The program cache
+  Integration::GlAbstraction& mGlAbstraction; ///< The OpenGL Abstraction layer
+  const Matrix* mProjectionMatrix;            ///< currently set projection matrix
+  const Matrix* mViewMatrix;                  ///< currently set view matrix
+  bool mLinked;                               ///< whether the program is linked
+  GLuint mVertexShaderId;                     ///< GL identifier for vertex shader
+  GLuint mFragmentShaderId;                   ///< GL identifier for fragment shader
+  GLuint mProgramId;                          ///< GL identifier for program
+  Internal::ShaderDataPtr mProgramData;    ///< Shader program source and binary (when compiled & linked or loaded)
+
+  // location caches
+  std::vector< std::pair< std::string, GLint > > mAttributeLocations; ///< attribute location cache
+  std::vector< std::pair< std::string, GLint > > mUniformLocations; ///< uniform location cache
+
+  // uniform value caching
+  GLint mUniformCacheInt[ MAX_UNIFORM_CACHE_SIZE ];         ///< Value cache for uniforms of single int
+  GLfloat mUniformCacheFloat[ MAX_UNIFORM_CACHE_SIZE ];     ///< Value cache for uniforms of single float
+  GLfloat mUniformCacheFloat4[ MAX_UNIFORM_CACHE_SIZE ][4]; ///< Value cache for uniforms of four float
+  bool mModifiesGeometry;  ///< True if the program changes geometry
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PROGRAM_H__
diff --git a/dali/internal/render/shaders/scene-graph-shader.cpp b/dali/internal/render/shaders/scene-graph-shader.cpp
new file mode 100644 (file)
index 0000000..913a071
--- /dev/null
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/render-debug.h>
+#include <dali/internal/render/gl-resources/context.h>
+#include <dali/internal/render/gl-resources/texture.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/gl-resources/texture-units.h>
+#include <dali/internal/render/shaders/program.h>
+#include <dali/internal/render/shaders/uniform-meta.h>
+#include <dali/internal/common/image-sampler.h>
+
+// See render-debug.h
+#ifdef DALI_PRINT_RENDER_INFO
+
+#include <sstream>
+#define DALI_DEBUG_OSTREAM(streamName) std::stringstream streamName;
+
+#define DALI_PRINT_UNIFORM(streamName,bufferIndex,name,value) \
+  { \
+    streamName << " " << name << ": " << value; \
+  }
+
+#define DALI_PRINT_CUSTOM_UNIFORM(streamName,bufferIndex,name,property) \
+  { \
+    streamName << " " << name << ": "; \
+    property.DebugPrint( streamName, bufferIndex ); \
+  }
+
+#define DALI_PRINT_SHADER_UNIFORMS(streamName) \
+  { \
+    std::string debugString( streamName.str() ); \
+    DALI_LOG_RENDER_INFO( "           %s\n", debugString.c_str() ); \
+  }
+
+#else // DALI_PRINT_RENDER_INFO
+
+#define DALI_DEBUG_OSTREAM(streamName)
+#define DALI_PRINT_UNIFORM(streamName,bufferIndex,name,value)
+#define DALI_PRINT_CUSTOM_UNIFORM(streamName,bufferIndex,name,property)
+#define DALI_PRINT_SHADER_UNIFORMS(streamName)
+
+#endif // DALI_PRINT_RENDER_INFO
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+template <> struct ParameterType< Dali::ShaderEffect::GeometryHints> : public BasicType< Dali::ShaderEffect::GeometryHints > {};
+template <> struct ParameterType< Dali::ShaderEffect::UniformCoordinateType > : public BasicType< Dali::ShaderEffect::UniformCoordinateType > {};
+
+namespace SceneGraph
+{
+
+Shader::Shader( Dali::ShaderEffect::GeometryHints& hints )
+: mGeometryHints( hints ),
+  mGridDensity( Dali::ShaderEffect::DEFAULT_GRID_DENSITY ),
+  mTexture( NULL ),
+  mRenderTextureId( 0 ),
+  mUpdateTextureId( 0 ),
+  mProgram( NULL ),
+  mRenderQueue( NULL ),
+  mTextureCache( NULL )
+{
+}
+
+Shader::~Shader()
+{
+}
+
+void Shader::Initialize( RenderQueue& renderQueue, TextureCache& textureCache )
+{
+  mRenderQueue = &renderQueue;
+  mTextureCache = &textureCache;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// The following methods are called during UpdateManager::Update()
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Shader::ForwardTextureId( BufferIndex updateBufferIndex, ResourceId textureId )
+{
+  mUpdateTextureId = textureId;
+
+  typedef MessageValue1< Shader, Integration::ResourceId > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( this, &Shader::SetTextureId, textureId );
+}
+
+Integration::ResourceId Shader::GetEffectTextureResourceId()
+{
+  return mUpdateTextureId;
+}
+
+void Shader::ForwardUniformMeta( BufferIndex updateBufferIndex, UniformMeta* meta )
+{
+  // Defer setting uniform metadata until the next Render
+
+  typedef MessageValue1< Shader, UniformMeta* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( this, &Shader::InstallUniformMetaInRender, meta );
+}
+
+void Shader::ForwardCoordinateType( BufferIndex updateBufferIndex, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
+{
+  // Defer setting uniform coordinate type until the next Render
+  typedef MessageValue2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( this, &Shader::SetCoordinateTypeInRender, index, type );
+}
+
+void Shader::ForwardGridDensity( BufferIndex updateBufferIndex, float density )
+{
+  typedef MessageValue1< Shader, float > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( this, &Shader::SetGridDensity, density );
+}
+
+void Shader::ForwardHints( BufferIndex updateBufferIndex, Dali::ShaderEffect::GeometryHints hint )
+{
+  typedef MessageValue1< Shader, Dali::ShaderEffect::GeometryHints > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue->ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( this, &Shader::SetGeometryHints, hint );
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// The following methods are called during RenderManager::Render()
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+void Shader::SetTextureId( Integration::ResourceId textureId )
+{
+  if ( mRenderTextureId != textureId )
+  {
+    mRenderTextureId = textureId;
+    mTexture = NULL;
+  }
+}
+
+Integration::ResourceId Shader::GetTextureIdToRender()
+{
+  return mRenderTextureId;
+}
+
+void Shader::SetGridDensity( float density )
+{
+  mGridDensity = density;
+}
+
+float Shader::GetGridDensity()
+{
+  return mGridDensity;
+}
+
+void Shader::InstallUniformMetaInRender( UniformMeta* meta )
+{
+  mUniformMetadata.PushBack( meta );
+}
+
+void Shader::SetCoordinateTypeInRender( unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
+{
+  DALI_ASSERT_DEBUG( index < mUniformMetadata.Count() );
+  mUniformMetadata[ index ]->SetCoordinateType( type );
+}
+
+void Shader::SetProgram( Internal::ShaderDataPtr shaderData,
+                         ProgramCache* programCache,
+                         bool modifiesGeometry )
+{
+  DALI_LOG_TRACE_METHOD_FMT( Debug::Filter::gShader, "%d\n", shaderData->GetHashValue() );
+
+  mProgram = Program::New( *programCache, shaderData, modifiesGeometry );
+  // The program cache owns the Program object so we don't need to worry about this raw allocation here.
+}
+
+Program* Shader::GetProgram()
+{
+  return mProgram;
+}
+
+void Shader::SetUniforms( Context& context,
+                          Program& program,
+                          BufferIndex bufferIndex )
+{
+  if( mRenderTextureId && ( mTexture == NULL ) )
+  {
+    mTexture = mTextureCache->GetTexture( mRenderTextureId );
+
+    DALI_ASSERT_DEBUG( mTexture != NULL );
+  }
+
+  GLint loc = Program::UNIFORM_UNKNOWN;
+
+  if( mTexture )
+  {
+    // if effect sampler uniform used by the program ?
+    const GLint loc = program.GetUniformLocation( Program::UNIFORM_EFFECT_SAMPLER );
+    if( Program::UNIFORM_UNKNOWN != loc )
+    {
+      // got effect texture, bind it to texture unit 1
+      mTextureCache->BindTexture( mTexture, mRenderTextureId, GL_TEXTURE_2D, TEXTURE_UNIT_SHADER);
+
+      // Apply the default sampling options for now
+      mTexture->ApplySampler( TEXTURE_UNIT_SHADER, ImageSampler::PackBitfield( FilterMode::DEFAULT, FilterMode::DEFAULT ) );
+
+      DALI_PRINT_UNIFORM( debugStream, bufferIndex, "sEffect", TEXTURE_UNIT_SHADER );
+      // set the uniform
+      program.SetUniform1i( loc, TEXTURE_UNIT_SHADER );
+    }
+  }
+
+  // We should have one UniformMeta per uniform property
+  for ( unsigned int i = 0u; i < mUniformMetadata.Count(); ++i )
+  {
+    UniformMeta& metadata = *mUniformMetadata[i];
+    const PropertyBase& property = metadata.property;
+
+    // send the updated uniform to the program
+    if ( metadata.name.length() > 0 )
+    {
+      // 0 means program has not got a cache index for this uniform
+      if( 0 == metadata.cacheIndex )
+      {
+        // register cacheindex for this program
+        metadata.cacheIndex = program.RegisterUniform( metadata.name );
+      }
+      loc = program.GetUniformLocation( metadata.cacheIndex );
+
+      // if we find uniform with location
+      if ( Program::UNIFORM_UNKNOWN != loc )
+      {
+        DALI_PRINT_CUSTOM_UNIFORM( debugStream, bufferIndex, metadata.name, property );
+
+        // switch based on property type to use correct GL uniform setter
+        switch ( property.GetType() )
+        {
+          case Property::BOOLEAN :
+          {
+            program.SetUniform1i( loc, property.GetBoolean( bufferIndex ) );
+            break;
+          }
+          case Property::INTEGER :
+          {
+            program.SetUniform1i( loc, property.GetInteger( bufferIndex ) );
+            break;
+          }
+          case Property::FLOAT :
+          {
+            program.SetUniform1f( loc, property.GetFloat( bufferIndex ) );
+            break;
+          }
+          case Property::VECTOR2 :
+          {
+            Vector2 value( property.GetVector2( bufferIndex ) );
+
+            switch ( metadata.coordinateType )
+            {
+              case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_POSITION :
+              {
+                /**
+                 * Convert coordinates from viewport to GL view space
+                 *
+                 * Viewport coordinate
+                 * (0,0)
+                 *      +-----+
+                 *      |     |
+                 *      |     |
+                 *      +-----+
+                 *             (width,height)
+                 *
+                 * GL view space coordinates
+                 * (width/2,-height/2)
+                 *      +-----+
+                 *      |     |
+                 *      |     |
+                 *      +-----+
+                 *             (-width/2,height/2)
+                 **/
+                const Rect< int >& viewport = context.GetViewport();
+                value.x = viewport.width * 0.5f - value.x;
+                value.y = value.y - viewport.height * 0.5f;
+
+                break;
+              }
+              case Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION :
+              {
+                // Check diagram in COORDINATE_TYPE_VIEWPORT_POSITION
+                value.x *= -1.0f;
+                break;
+              }
+              case Dali::ShaderEffect::COORDINATE_TYPE_DEFAULT :
+              {
+                // nothing to do in this case
+                break;
+              }
+              // no default so compiler will warn if a case is not handled
+            }
+
+            program.SetUniform2f( loc, value.x, value.y );
+            break;
+          }
+
+          case Property::VECTOR3 :
+          {
+            Vector3 value( property.GetVector3( bufferIndex ) );
+            if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
+            {
+              value.y *= -1.0f;
+            }
+
+            program.SetUniform3f( loc, value.x, value.y, value.z );
+            break;
+          }
+
+          case Property::VECTOR4 :
+          {
+            Vector4 value( property.GetVector4( bufferIndex ) );
+            if( Dali::ShaderEffect::COORDINATE_TYPE_VIEWPORT_DIRECTION == metadata.coordinateType)
+            {
+              value.y *= -1.0f;
+            }
+
+            program.SetUniform4f( loc, value.x, value.y, value.z, value.w );
+            break;
+          }
+
+          case Property::MATRIX:
+          {
+            const Matrix& value = property.GetMatrix(bufferIndex);
+            program.SetUniformMatrix4fv(loc, 1, value.AsFloat() );
+            break;
+          }
+
+          case Property::MATRIX3:
+          {
+            const Matrix3& value = property.GetMatrix3(bufferIndex);
+            program.SetUniformMatrix3fv(loc, 1, value.AsFloat() );
+            break;
+          }
+
+          case Property::NONE:
+          case Property::ROTATION:
+          case Property::STRING:
+          case Property::RECTANGLE:
+          case Property::MAP:
+          case Property::ARRAY:
+          {
+            DALI_LOG_ERROR( "Invalid property type for a uniform" );
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  DALI_PRINT_SHADER_UNIFORMS(debugStream);
+}
+
+
+// Messages
+
+void SetTextureIdMessage( EventThreadServices& eventThreadServices, const Shader& shader, Integration::ResourceId textureId )
+{
+  typedef MessageDoubleBuffered1< Shader, Integration::ResourceId > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &shader, &Shader::ForwardTextureId, textureId );
+}
+
+void SetGridDensityMessage( EventThreadServices& eventThreadServices, const Shader& shader, float density )
+{
+  typedef MessageDoubleBuffered1< Shader, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &shader, &Shader::ForwardGridDensity, density );
+}
+
+void SetHintsMessage( EventThreadServices& eventThreadServices, const Shader& shader, Dali::ShaderEffect::GeometryHints hint )
+{
+  typedef MessageDoubleBuffered1< Shader, Dali::ShaderEffect::GeometryHints > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &shader, &Shader::ForwardHints, hint );
+}
+
+void InstallUniformMetaMessage( EventThreadServices& eventThreadServices, const Shader& shader, UniformMeta& meta )
+{
+  typedef MessageDoubleBuffered1< Shader, UniformMeta* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &shader, &Shader::ForwardUniformMeta, &meta );
+}
+
+void SetCoordinateTypeMessage( EventThreadServices& eventThreadServices, const Shader& shader, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type )
+{
+  typedef MessageDoubleBuffered2< Shader, unsigned int, Dali::ShaderEffect::UniformCoordinateType > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &shader, &Shader::ForwardCoordinateType, index, type );
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/render/shaders/scene-graph-shader.h b/dali/internal/render/shaders/scene-graph-shader.h
new file mode 100644 (file)
index 0000000..198b557
--- /dev/null
@@ -0,0 +1,304 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_SHADER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_SHADER_H__
+
+/*
+ * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+
+#include <dali/internal/common/shader-data.h>
+
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/type-abstraction-enums.h>
+
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/effects/shader-declarations.h>
+
+#include <dali/internal/update/common/property-owner.h>
+
+#include <dali/internal/render/gl-resources/gl-resource-owner.h>
+#include <dali/internal/render/gl-resources/texture-declarations.h>
+#include <dali/internal/render/common/render-manager.h>
+
+
+namespace Dali
+{
+
+namespace Integration
+{
+typedef unsigned int ResourceId;
+} // namespace Integration
+
+namespace Internal
+{
+
+class Program;
+
+namespace SceneGraph
+{
+
+class RenderQueue;
+class UniformMeta;
+class TextureCache;
+
+/**
+ * A base class for a collection of shader programs, to apply an effect to different geometry types.
+ * This class is also the default shader so its easier to override default behaviour
+ */
+class Shader : public PropertyOwner
+{
+public:
+
+  /**
+   * Constructor
+   * @param hints Geometry hints
+   */
+  Shader( Dali::ShaderEffect::GeometryHints& hints );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Shader();
+
+  /**
+   * Second stage initialization, called when added to the UpdateManager
+   * @param renderQueue Used to queue messages from update to render thread.
+   * @param textureCache Used to retrieve effect textures when rendering.
+   */
+  void Initialize( RenderQueue& renderQueue, TextureCache& textureCache );
+
+  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+  // The following methods are called during UpdateManager::Update()
+  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Query whether a shader geometry hint is set.
+   * @pre The shader has been initialized.
+   * @param[in] hint The geometry hint to check.
+   * @return True if the given geometry hint is set.
+   */
+  bool GeometryHintEnabled( Dali::ShaderEffect::GeometryHints hint ) const
+  {
+    return mGeometryHints & hint;
+  }
+
+  /**
+   * Retrieve the set of geometry hints.
+   * @return The hints.
+   */
+  Dali::ShaderEffect::GeometryHints GetGeometryHints() const
+  {
+    return mGeometryHints;
+  }
+
+  /**
+   * Set the geometry hints.
+   * @param[in] hints The hints.
+   */
+  void SetGeometryHints( Dali::ShaderEffect::GeometryHints hints )
+  {
+    mGeometryHints = hints;
+  }
+
+  /**
+   * @return True if the fragment shader outputs only 1.0 on the alpha channel
+   *
+   * @note Shaders that can output any value on the alpha channel
+   * including 1.0 should return false for this.
+   */
+  bool IsOutputOpaque();
+
+  /**
+   * @return True if the fragment shader can output any value but 1.0 on the alpha channel
+   *
+   * @note Shaders that can output any value on the alpha channel
+   * including 1.0 should return false for this
+   */
+  bool IsOutputTransparent();
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex )
+  {
+    // no default properties
+  }
+
+  /**
+   * Set the ID used to access textures
+   * @pre This method is not thread-safe, and should only be called from the update-thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] textureId The texture ID.
+   */
+  void ForwardTextureId( BufferIndex updateBufferIndex, Integration::ResourceId textureId );
+
+  /**
+   * Gets the effect texture resource ID
+   * This is zero if there is effect texture
+   * @return the resource Id
+   */
+  Integration::ResourceId GetEffectTextureResourceId();
+
+  /**
+   * Forwards the meta data from the update thread to the render thread for actual
+   * installation. (Installation is to a std::vector, which is not thread safe)
+   * @sa InstallUniformMetaInRender
+   * @pre This method should only be called from the update thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] meta A pointer to a UniformMeta to be owned by the Shader.
+   */
+  void ForwardUniformMeta( BufferIndex updateBufferIndex, UniformMeta* meta );
+
+  /**
+   * Forwards coordinate type to render
+   * @sa InstallUniformMetaInRender
+   * @pre This method should only be called from the update thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] index of the metadata.
+   * @param[in] type the coordinate type.
+   */
+  void ForwardCoordinateType( BufferIndex updateBufferIndex, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type );
+
+  /**
+   * Forwards the grid density.
+   * @pre This method is not thread-safe, and should only be called from the update thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] density The grid density.
+   */
+  void ForwardGridDensity( BufferIndex updateBufferIndex, float density );
+
+  /**
+   * Forwards hints.
+   * @pre This method is not thread-safe, and should only be called from the update thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] hint The geometry hints.
+   */
+  void ForwardHints( BufferIndex updateBufferIndex, Dali::ShaderEffect::GeometryHints hint );
+
+  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+  // The following methods are called in Render thread
+  ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+  /**
+   * Set the ID used to access textures
+   * @pre This method is not thread-safe, and should only be called from the render thread.
+   * @param[in] textureId The texture ID.
+   */
+  void SetTextureId( Integration::ResourceId textureId );
+
+  /**
+   * Get the texture id, that will be used in the next call to Shader::Apply()
+   * @return textureId The texture ID
+   */
+  Integration::ResourceId GetTextureIdToRender();
+
+  /**
+   * Sets grid density
+   * @pre This method is not thread-safe, and should only be called from the update thread.
+   * @param[in] value The grid density
+   */
+  void SetGridDensity(float value);
+
+  /**
+   * Get the grid density ID.
+   * @pre This method is not thread-safe, and should only be called from the render thread.
+   * @return The grid density.
+   */
+  float GetGridDensity();
+
+  /**
+   * Installs metadata related to a newly installed uniform property.
+   * @pre This method is not thread-safe, and should only be called from the render-thread.
+   * @param[in] meta A pointer to a UniformMeta to be owned by the Shader.
+   */
+  void InstallUniformMetaInRender( UniformMeta* meta );
+
+  /**
+   * Sets the uniform coordinate type
+   * @param index of the uniform
+   * @param type to set
+   */
+  void SetCoordinateTypeInRender( unsigned int index, Dali::ShaderEffect::UniformCoordinateType type );
+
+  /**
+   * @brief Set the program for this shader.
+   * @param[in] shaderData        The program's vertex/fragment source and optionally precompiled shader binary.
+   * @param[in] programCache      Owner of the Programs.
+   * @param[in] modifiesGeometry  True if the vertex shader changes the positions of vertexes such that
+   * they might exceed the bounding box of vertexes passing through the default transformation.
+   */
+  void SetProgram( Internal::ShaderDataPtr shaderData,
+                   ProgramCache* programCache,
+                   bool modifiesGeometry );
+
+  /**
+   * Get the program built for this shader
+   * @return The program built from the shader sources.
+   */
+  Program* GetProgram();
+
+  /**
+   * Sets the shader specific uniforms including custom uniforms
+   * @pre The shader has been initialized.
+   * @pre This method is not thread-safe, and should only be called from the render-thread.
+   * @param[in] context The context used to render.
+   * @param[in] program to use.
+   * @param[in] bufferIndex The buffer to read shader properties from.
+   * @param[in] type        the type of the object (geometry) that is being rendered.
+   * @param[in] subType     Identifier for geometry types with specialised default shaders
+   */
+  void SetUniforms( Context& context,
+                    Program& program,
+                    BufferIndex bufferIndex );
+
+private: // Data
+
+  Dali::ShaderEffect::GeometryHints mGeometryHints;    ///< shader geometry hints for building the geometry
+  float                          mGridDensity;      ///< grid density
+
+  Texture*                       mTexture;          ///< Raw Pointer to Texture
+  Integration::ResourceId        mRenderTextureId;  ///< Copy of the texture ID for the render thread
+  Integration::ResourceId        mUpdateTextureId;  ///< Copy of the texture ID for update thread
+
+  Program*                       mProgram;
+
+  typedef OwnerContainer< UniformMeta* > UniformMetaContainer;
+  UniformMetaContainer           mUniformMetadata;     ///< A container of owned UniformMeta values; one for each property in PropertyOwner::mDynamicProperties
+
+  // These members are only safe to access during UpdateManager::Update()
+  RenderQueue*                   mRenderQueue;                   ///< Used for queuing a message for the next Render
+
+  // These members are only safe to access in render thread
+  TextureCache*                  mTextureCache; // Used for retrieving textures in the render thread
+};
+
+// Messages for Shader, to be processed in Update thread.
+void SetTextureIdMessage( EventThreadServices& eventThreadServices, const Shader& shader, Integration::ResourceId textureId );
+void SetGridDensityMessage( EventThreadServices& eventThreadServices, const Shader& shader, float density );
+void SetHintsMessage( EventThreadServices& eventThreadServices, const Shader& shader, Dali::ShaderEffect::GeometryHints hint );
+void InstallUniformMetaMessage( EventThreadServices& eventThreadServices, const Shader& shader, UniformMeta& meta );
+void SetCoordinateTypeMessage( EventThreadServices& eventThreadServices, const Shader& shader, unsigned int index, Dali::ShaderEffect::UniformCoordinateType type );
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_SHADER_H__
diff --git a/dali/internal/render/shaders/uniform-meta.h b/dali/internal/render/shaders/uniform-meta.h
new file mode 100644 (file)
index 0000000..7f066d2
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef __DALI_INTERNAL_UNIFORM_META_H__
+#define __DALI_INTERNAL_UNIFORM_META_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <cstring> // for memcpy & memset
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/compile-time-math.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class PropertyBase;
+
+/**
+ * Holds the metadata associated with a Shader uniform.
+ */
+class UniformMeta
+{
+public:
+
+  /**
+   * Create a UniformMeta.
+   */
+  static UniformMeta* New( const std::string& name, const PropertyBase& property, Dali::ShaderEffect::UniformCoordinateType coordType )
+  {
+    return new UniformMeta( name, property, coordType );
+  }
+
+  /**
+   * Copy constructor
+   * @param [in] meta The UniformMeta to copy.
+   */
+  UniformMeta( const UniformMeta& meta )
+  : name( meta.name ),
+    property( meta.property ),
+    cacheIndex( meta.cacheIndex ),
+    coordinateType( meta.coordinateType )
+  {
+  }
+
+  /**
+   * Set the coordinate type.
+   * @param [in] coordType The new coordinate type.
+   */
+  void SetCoordinateType( Dali::ShaderEffect::UniformCoordinateType coordType )
+  {
+    coordinateType = coordType;
+  }
+
+private:
+
+  /**
+   * Constructor
+   */
+  UniformMeta( const std::string& uniformName, const PropertyBase& prop, Dali::ShaderEffect::UniformCoordinateType coordType )
+  : name( uniformName ),
+    property( prop ),
+    cacheIndex( 0 ),
+    coordinateType( coordType )
+  {
+  }
+
+  // Undefined
+  UniformMeta& operator=( const UniformMeta& rhs );
+
+public:
+
+  std::string name; ///< name of uniform to set/animate
+  const PropertyBase& property; ///< reference to the corresponding property
+  unsigned int cacheIndex; ///< internal program cache index
+  Dali::ShaderEffect::UniformCoordinateType coordinateType; ///< The coordinate type of the uniform
+
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_UNIFORM_META_H__
diff --git a/dali/internal/update/animation/property-accessor.h b/dali/internal/update/animation/property-accessor.h
new file mode 100644 (file)
index 0000000..7769f06
--- /dev/null
@@ -0,0 +1,127 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_ACCESSOR_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_ACCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/update/common/animatable-property.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A wrapper class for getting/setting a property.
+ * Animators use this instead of accessing properties directly.
+ */
+template < typename PropertyType >
+class PropertyAccessor
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property to access.
+   */
+  PropertyAccessor( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::AnimatableProperty<PropertyType>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyAccessor is not suitable as a base class.
+   */
+  ~PropertyAccessor()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyAccessor is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   */
+  const PropertyType& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, const PropertyType& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Set() mProperty was NULL" );
+    mProperty->Set( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, const PropertyType& value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyAccessor::Bake() mProperty was NULL" );
+    mProperty->Bake( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  PropertyAccessor(const PropertyAccessor& property);
+
+  // Undefined
+  PropertyAccessor& operator=(const PropertyAccessor& rhs);
+
+private:
+
+  SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_ACCESSOR_H__
diff --git a/dali/internal/update/animation/property-component-accessor.h b/dali/internal/update/animation/property-component-accessor.h
new file mode 100644 (file)
index 0000000..e1e596b
--- /dev/null
@@ -0,0 +1,403 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_COMPONENT_ACCESSOR_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_COMPONENT_ACCESSOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/update/common/animatable-property.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * A wrapper class for getting/setting a float component of another property.
+ * Animators use this instead of accessing properties directly.
+ */
+template < typename PropertyType >
+class PropertyComponentAccessorX
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property which holds a float component.
+   */
+  PropertyComponentAccessorX( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::AnimatableProperty<PropertyType>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyComponentAccessorX is not suitable as a base class.
+   */
+  ~PropertyComponentAccessorX()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyComponentAccessorX is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   */
+  const float& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorX::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex ).x; // X Component only!
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorX::Set() mProperty was NULL" );
+    mProperty->SetX( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorX::Bake() mProperty was NULL" );
+    mProperty->BakeX( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  PropertyComponentAccessorX(const PropertyComponentAccessorX& property);
+
+  // Undefined
+  PropertyComponentAccessorX& operator=(const PropertyComponentAccessorX& rhs);
+
+private:
+
+  SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
+};
+
+/**
+ * A wrapper class for getting/setting a float component of another property.
+ * Animators use this instead of accessing properties directly.
+ */
+template < typename PropertyType >
+class PropertyComponentAccessorY
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property which holds a float component.
+   */
+  PropertyComponentAccessorY( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::AnimatableProperty<PropertyType>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyComponentAccessorY is not suitable as a base class.
+   */
+  ~PropertyComponentAccessorY()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyComponentAccessorY is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   */
+  const float& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorY::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex ).y; // Y Component only!
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorY::Set() mProperty was NULL" );
+    mProperty->SetY( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorY::Bake() mProperty was NULL" );
+    mProperty->BakeY( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  PropertyComponentAccessorY(const PropertyComponentAccessorY& property);
+
+  // Undefined
+  PropertyComponentAccessorY& operator=(const PropertyComponentAccessorY& rhs);
+
+private:
+
+  SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
+};
+
+/**
+ * A wrapper class for getting/setting a float component of another property.
+ * Animators use this instead of accessing properties directly.
+ */
+template < typename PropertyType >
+class PropertyComponentAccessorZ
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property which holds a float component.
+   */
+  PropertyComponentAccessorZ( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::AnimatableProperty<PropertyType>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyComponentAccessorZ is not suitable as a base class.
+   */
+  ~PropertyComponentAccessorZ()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyComponentAccessorZ is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   */
+  const float& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorZ::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex ).z; // Z Component only!
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorZ::Set() mProperty was NULL" );
+    mProperty->SetZ( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorZ::Bake() mProperty was NULL" );
+    mProperty->BakeZ( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  PropertyComponentAccessorZ(const PropertyComponentAccessorZ& property);
+
+  // Undefined
+  PropertyComponentAccessorZ& operator=(const PropertyComponentAccessorZ& rhs);
+
+private:
+
+  SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
+};
+
+/**
+ * A wrapper class for getting/setting a float component of another property.
+ * Animators use this instead of accessing properties directly.
+ */
+template < typename PropertyType >
+class PropertyComponentAccessorW
+{
+public:
+
+  /**
+   * Create a property component.
+   * @param [in] property The property which holds a float component.
+   */
+  PropertyComponentAccessorW( SceneGraph::PropertyBase* property )
+  : mProperty( dynamic_cast< SceneGraph::AnimatableProperty<PropertyType>* >(property) )
+  {
+  }
+
+  /**
+   * Non-virtual destructor; PropertyComponentAccessorW is not suitable as a base class.
+   */
+  ~PropertyComponentAccessorW()
+  {
+  }
+
+  /**
+   * Query whether the accessor is set.
+   * @return True if set.
+   */
+  bool IsSet() const
+  {
+    return mProperty != NULL;
+  }
+
+  /**
+   * Reset the property accessor
+   * @post Calling any other PropertyComponentAccessorW is invalid.
+   */
+  void Reset()
+  {
+    mProperty = NULL;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  bool IsClean() const
+  {
+    return mProperty->IsClean();
+  }
+
+  /**
+   * Read access to the property.
+   * @param [in] bufferIndex The current update buffer index.
+   */
+  const float& Get( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorW::Get() mProperty was NULL" );
+    return mProperty->Get( bufferIndex ).w; // W Component only!
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Set()
+   */
+  void Set( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorW::Set() mProperty was NULL" );
+    mProperty->SetW( bufferIndex, value );
+  }
+
+  /**
+   * @copydoc SceneGraph::AnimatableProperty<float>::Bake()
+   */
+  void Bake( BufferIndex bufferIndex, float value ) const
+  {
+    DALI_ASSERT_DEBUG( NULL != mProperty && "PropertyComponentAccessorW::Bake() mProperty was NULL" );
+    mProperty->BakeW( bufferIndex, value );
+  }
+
+private:
+
+  // Undefined
+  PropertyComponentAccessorW(const PropertyComponentAccessorW& property);
+
+  // Undefined
+  PropertyComponentAccessorW& operator=(const PropertyComponentAccessorW& rhs);
+
+private:
+
+  SceneGraph::AnimatableProperty<PropertyType>* mProperty; ///< The real property
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_COMPONENT_ACCESSOR_H__
diff --git a/dali/internal/update/animation/scene-graph-animation.cpp b/dali/internal/update/animation/scene-graph-animation.cpp
new file mode 100644 (file)
index 0000000..a2538d1
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/animation/scene-graph-animation.h>
+
+// EXTERNAL INCLUDES
+#include <cmath> // fmod
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+
+Animation::Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, Dali::Animation::EndAction endAction, Dali::Animation::EndAction disconnectAction )
+: mDurationSeconds(durationSeconds),
+  mSpeedFactor( speedFactor ),
+  mLooping(isLooping),
+  mEndAction(endAction),
+  mDisconnectAction(disconnectAction),
+  mState(Stopped),
+  mElapsedSeconds(playRange.x*mDurationSeconds),
+  mPlayCount(0),
+  mPlayRange( playRange )
+{
+}
+
+Animation::~Animation()
+{
+}
+
+void Animation::SetDuration(float durationSeconds)
+{
+  mDurationSeconds = durationSeconds;
+}
+
+void Animation::SetLooping(bool looping)
+{
+  mLooping = looping;
+}
+
+void Animation::SetEndAction(Dali::Animation::EndAction action)
+{
+  mEndAction = action;
+}
+
+void Animation::SetDisconnectAction(Dali::Animation::EndAction action)
+{
+  if ( mDisconnectAction != action )
+  {
+    mDisconnectAction = action;
+
+    for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter )
+    {
+      (*iter)->SetDisconnectAction( action );
+    }
+  }
+}
+
+void Animation::SetPlayRange( const Vector2& range )
+{
+  mPlayRange = range;
+
+  //Make sure mElapsedSeconds is within the new range
+  mElapsedSeconds = Dali::Clamp(mElapsedSeconds, mPlayRange.x*mDurationSeconds , mPlayRange.y*mDurationSeconds );
+}
+
+void Animation::Play()
+{
+  mState = Playing;
+
+  if ( mSpeedFactor < 0.0f && mElapsedSeconds <= mPlayRange.x*mDurationSeconds )
+  {
+    mElapsedSeconds = mPlayRange.y * mDurationSeconds;
+  }
+
+  SetAnimatorsActive( true );
+}
+
+void Animation::PlayFrom( float progress )
+{
+  //If the animation is already playing this has no effect
+  if( mState != Playing )
+  {
+    mElapsedSeconds = progress * mDurationSeconds;
+    mState = Playing;
+
+    SetAnimatorsActive( true );
+  }
+}
+
+void Animation::Pause()
+{
+  if (mState == Playing)
+  {
+    mState = Paused;
+  }
+}
+
+void Animation::Bake(BufferIndex bufferIndex, EndAction action)
+{
+  if( action == Dali::Animation::BakeFinal )
+  {
+    if( mSpeedFactor > 0.0f )
+    {
+      mElapsedSeconds = mPlayRange.y*mDurationSeconds + Math::MACHINE_EPSILON_1; // Force animation to reach it's end
+    }
+    else
+    {
+      mElapsedSeconds = mPlayRange.x*mDurationSeconds - Math::MACHINE_EPSILON_1; //Force animation to reach it's beginning
+    }
+  }
+
+  UpdateAnimators( bufferIndex, true/*bake the final result*/, true /*animation finished*/ );
+}
+
+void Animation::SetAnimatorsActive( bool active )
+{
+  for ( AnimatorIter iter = mAnimators.Begin(), endIter = mAnimators.End(); iter != endIter; ++iter )
+  {
+    (*iter)->SetActive( active );
+  }
+}
+
+bool Animation::Stop(BufferIndex bufferIndex)
+{
+  bool animationFinished(false);
+
+  if (mState == Playing || mState == Paused)
+  {
+    animationFinished = true; // The actor-thread should be notified of this
+
+    if( mEndAction != Dali::Animation::Discard )
+    {
+      Bake( bufferIndex, mEndAction );
+
+      // Animators are automatically set to inactive in Bake
+    }
+    else
+    {
+      SetAnimatorsActive( false );
+    }
+
+    // The animation has now been played to completion
+    ++mPlayCount;
+  }
+
+  mElapsedSeconds = mPlayRange.x*mDurationSeconds;
+  mState = Stopped;
+
+  return animationFinished;
+}
+
+void Animation::OnDestroy(BufferIndex bufferIndex)
+{
+  if (mState == Playing || mState == Paused)
+  {
+    if (mEndAction != Dali::Animation::Discard)
+    {
+      Bake( bufferIndex, mEndAction );
+
+      // Animators are automatically set to inactive in Bake
+    }
+    else
+    {
+      SetAnimatorsActive( false );
+    }
+  }
+
+  mState = Destroyed;
+}
+
+void Animation::AddAnimator( AnimatorBase* animator )
+{
+  animator->ConnectToSceneGraph();
+  animator->SetDisconnectAction( mDisconnectAction );
+
+  mAnimators.PushBack( animator );
+}
+
+bool Animation::Update(BufferIndex bufferIndex, float elapsedSeconds)
+{
+  if (mState == Stopped || mState == Destroyed)
+  {
+    // Short circuit when animation isn't running
+    return false;
+  }
+
+  // The animation must still be applied when Paused/Stopping
+  if (mState == Playing)
+  {
+    mElapsedSeconds += elapsedSeconds * mSpeedFactor;
+  }
+
+  Vector2 playRangeSeconds = mPlayRange * mDurationSeconds;
+  if (mLooping)
+  {
+    if (mElapsedSeconds > playRangeSeconds.y )
+    {
+      mElapsedSeconds = playRangeSeconds.x + fmod(mElapsedSeconds, playRangeSeconds.y);
+    }
+    else if( mElapsedSeconds < playRangeSeconds.x )
+    {
+      mElapsedSeconds = playRangeSeconds.y - fmod(mElapsedSeconds, playRangeSeconds.y);
+    }
+  }
+
+  const bool animationFinished(mState == Playing                                                &&
+                              (( mSpeedFactor > 0.0f && mElapsedSeconds > playRangeSeconds.y )  ||
+                               ( mSpeedFactor < 0.0f && mElapsedSeconds < playRangeSeconds.x ))
+                              );
+
+  UpdateAnimators(bufferIndex, animationFinished && (mEndAction != Dali::Animation::Discard), animationFinished);
+
+  if (animationFinished)
+  {
+    // The animation has now been played to completion
+    ++mPlayCount;
+
+    mElapsedSeconds = playRangeSeconds.x;
+    mState = Stopped;
+  }
+
+  return animationFinished;
+}
+
+void Animation::UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished )
+{
+  float elapsedSecondsClamped = Clamp( mElapsedSeconds, mPlayRange.x * mDurationSeconds,mPlayRange.y * mDurationSeconds );
+
+  //Loop through all animators
+  bool applied(true);
+  for ( AnimatorIter iter = mAnimators.Begin(); iter != mAnimators.End(); )
+  {
+    AnimatorBase *animator = *iter;
+
+    if( animator->Orphan() )
+    {
+      //Remove animators whose PropertyOwner has been destroyed
+      iter = mAnimators.Erase(iter);
+    }
+    else
+    {
+      if( animator->IsEnabled() )
+      {
+        const float initialDelay(animator->GetInitialDelay());
+        if (elapsedSecondsClamped >= initialDelay || mSpeedFactor < 0.0f )
+        {
+          // Calculate a progress specific to each individual animator
+          float progress(1.0f);
+          const float animatorDuration = animator->GetDuration();
+          if (animatorDuration > 0.0f) // animators can be "immediate"
+          {
+            progress = Clamp((elapsedSecondsClamped - initialDelay) / animatorDuration, 0.0f , 1.0f );
+          }
+          animator->Update(bufferIndex, progress, bake);
+        }
+        applied = true;
+      }
+      else
+      {
+        applied = false;
+      }
+
+      if ( animationFinished )
+      {
+        animator->SetActive( false );
+      }
+
+      if (applied)
+      {
+        INCREASE_COUNTER(PerformanceMonitor::ANIMATORS_APPLIED);
+      }
+
+      ++iter;
+    }
+  }
+
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/animation/scene-graph-animation.h b/dali/internal/update/animation/scene-graph-animation.h
new file mode 100644 (file)
index 0000000..c00a21e
--- /dev/null
@@ -0,0 +1,451 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/animation.h>
+
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/animation/scene-graph-animator.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Animation;
+
+typedef OwnerContainer< Animation* > AnimationContainer;
+
+typedef AnimationContainer::Iterator AnimationIter;
+typedef AnimationContainer::ConstIterator AnimationConstIter;
+
+/**
+ * Animations are used to change the properties of scene graph objects, as part of a scene
+ * managers "update" phase. An animation is a container of Animator objects; the actual setting
+ * of object values is done by the animators.
+ */
+class Animation
+{
+public:
+
+  typedef Dali::Animation::EndAction EndAction;
+
+  enum State
+  {
+    Stopped,
+    Playing,
+    Paused,
+    Destroyed
+  };
+
+  /**
+   * Construct a new Animation.
+   * @param[in] durationSeconds The duration of the animation in seconds.
+   * @param[in] speedFactor Multiplier to the animation velocity.
+   * @param[in] playRange Minimum and maximum progress between which the animation will play.
+   * @param[in] isLooping Whether the animation will loop.
+   * @param[in] endAction The action to perform when the animation ends.
+   * @param[in] disconnectAction The action to perform when the property owner of an animator is disconnected.
+   * @return A new Animation
+   */
+  static Animation* New( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction )
+  {
+    return new Animation( durationSeconds, speedFactor, playRange, isLooping, endAction, disconnectAction );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Animation();
+
+  /**
+   * Set the duration of an animation.
+   * @pre durationSeconds must be greater than zero.
+   * @param[in] durationSeconds The duration in seconds.
+   */
+  void SetDuration(float durationSeconds);
+
+  /**
+   * Retrieve the duration of the animation.
+   * @return The duration in seconds.
+   */
+  float GetDuration() const
+  {
+    return mDurationSeconds;
+  }
+
+  /*
+   * Retrieve the current progress of the animation.
+   * @return The current progress as a normalized value between [0,1].
+   */
+  float GetCurrentProgress() const
+  {
+    if( mDurationSeconds > 0.0f )
+    {
+      return mElapsedSeconds / mDurationSeconds;
+    }
+
+    return 0.0f;
+  }
+
+  /*
+   * Sets the progress of the animation.
+   * @param[in] The new progress as a normalized value between [0,1]
+   */
+  void SetCurrentProgress( float progress )
+  {
+    mElapsedSeconds = mDurationSeconds * progress;
+  }
+
+  void SetSpeedFactor( float factor )
+  {
+    mSpeedFactor = factor;
+  }
+
+  /**
+   * Set whether the animation will loop.
+   * @param[in] looping True if the animation will loop.
+   */
+  void SetLooping(bool looping);
+
+  /**
+   * Query whether the animation will loop.
+   * @return True if the animation will loop.
+   */
+  bool IsLooping() const
+  {
+    return mLooping;
+  }
+
+  /**
+   * Set the end action of the animation.
+   * @param[in] action The end action.
+   */
+  void SetEndAction(EndAction action);
+
+  /**
+   * Retrieve the action performed when the animation ends.
+   * @return The end action.
+   */
+  EndAction GetEndAction()
+  {
+    return mEndAction;
+  }
+
+  /**
+   * Set the disconnect action of the animation when connected objects are disconnected.
+   * This action is performed during the next update when
+   * the connected object is disconnected.
+   * @param[in] action The disconnect action.
+   */
+  void SetDisconnectAction(EndAction action);
+
+  /**
+   * Retrieve the action performed when the animation is destroyed.
+   * @return The destroy action.
+   */
+  EndAction GetDisconnectAction()
+  {
+    return mDisconnectAction;
+  }
+
+  /**
+   * Set the playing range. The animation will only play between the minimum and maximum progress
+   * speficied.
+   *
+   * @param[in] range Two values between [0,1] to specify minimum and maximum progress.
+   */
+  void SetPlayRange( const Vector2& range );
+
+  /**
+   * Play the animation.
+   */
+  void Play();
+
+  /*
+   * Play the animation from a given point
+   * @param[in] progress A value between [0,1] form where the animation should start playing
+   */
+  void PlayFrom( float progress );
+
+  /**
+   * Pause the animation.
+   */
+  void Pause();
+
+  /**
+   * Stop the animation.
+   * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
+   * @return True if the animation has finished (otherwise it wasn't playing)
+   */
+  bool Stop(BufferIndex bufferIndex);
+
+  /**
+   * Called shortly before the animation is destroyed.
+   * @param[in] bufferIndex The buffer to update when mEndAction == Bake.
+   */
+  void OnDestroy(BufferIndex bufferIndex);
+
+  /**
+   * Query whether the animation is playing, paused or stopped.
+   * Note that even when paused, the Update() method should be called,
+   * since the current progress must be reapplied each frame.
+   */
+  State GetState() const
+  {
+    return mState;
+  }
+
+  /**
+   * Retrive a count of the number of times the animation has been played to completion.
+   * This can be used to emit "Finised" signals from the public-api
+   */
+  int GetPlayCount() const
+  {
+    return mPlayCount;
+  }
+
+  /**
+   * Add a newly created animator.
+   * Animators are automatically removed, when orphaned from an animatable scene object.
+   * @param[in] animator The animator to add.
+   * @param[in] propertyOwner The scene-object that owns the animatable property.
+   * @post The animator is owned by this animation.
+   */
+  void AddAnimator( AnimatorBase* animator );
+
+  /**
+   * Retrieve the animators from an animation.
+   * @return The container of animators.
+   */
+  AnimatorContainer& GetAnimators()
+  {
+    return mAnimators;
+  }
+
+  /**
+   * This causes the animators to change the properties of objects in the scene graph.
+   * @pre The animation is playing or paused.
+   * @param[in] bufferIndex The buffer to update.
+   * @param[in] elapsedSeconds The time elapsed since the previous frame.
+   * @return True if the animation has finished.
+   */
+  bool Update(BufferIndex bufferIndex, float elapsedSeconds);
+
+
+protected:
+
+  /**
+   * Protected constructor. See New()
+   */
+  Animation( float durationSeconds, float speedFactor, const Vector2& playRange, bool isLooping, EndAction endAction, EndAction disconnectAction );
+
+
+private:
+
+  /**
+   * Helper for Update, also used to bake when the animation is stopped or destroyed.
+   * @param[in] bufferIndex The buffer to update.
+   * @param[in] bake True if the final result should be baked.
+   * @param[in] animationFinished True if the animation has finished.
+   */
+  void UpdateAnimators( BufferIndex bufferIndex, bool bake, bool animationFinished );
+
+  /**
+   * Helper function to bake the result of the animation when it is stopped or
+   * destroyed.
+   * @param[in] bufferIndex The buffer to update.
+   * @param[in] action The end action specified.
+   */
+  void Bake(BufferIndex bufferIndex, EndAction action );
+
+  /**
+   * Helper function to set active state of animators.
+   * @param[in] active Every animator is set to this state
+   */
+  void SetAnimatorsActive( bool active );
+
+  // Undefined
+  Animation(const Animation&);
+
+  // Undefined
+  Animation& operator=(const Animation& rhs);
+
+protected:
+
+  float mDurationSeconds;
+  float mSpeedFactor;
+  bool mLooping;
+  EndAction mEndAction;
+  EndAction mDisconnectAction;
+
+  State mState;
+  float mElapsedSeconds;
+  int mPlayCount;
+
+  Vector2 mPlayRange;
+  AnimatorContainer mAnimators;
+};
+
+}; //namespace SceneGraph
+
+// value types used by messages
+template <> struct ParameterType< Dali::Animation::EndAction > : public BasicType< Dali::Animation::EndAction > {};
+
+namespace SceneGraph
+{
+
+// Messages for Animation
+
+inline void SetDurationMessage( EventThreadServices& eventThreadServices, const Animation& animation, float durationSeconds )
+{
+  typedef MessageValue1< Animation, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetDuration, durationSeconds );
+}
+
+inline void SetLoopingMessage( EventThreadServices& eventThreadServices, const Animation& animation, bool looping )
+{
+  typedef MessageValue1< Animation, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetLooping, looping );
+}
+
+inline void SetEndActionMessage( EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action )
+{
+  typedef MessageValue1< Animation, Dali::Animation::EndAction > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetEndAction, action );
+}
+
+inline void SetDisconnectActionMessage( EventThreadServices& eventThreadServices, const Animation& animation, Dali::Animation::EndAction action )
+{
+  typedef MessageValue1< Animation, Dali::Animation::EndAction > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetDisconnectAction, action );
+}
+
+inline void SetCurrentProgressMessage( EventThreadServices& eventThreadServices, const Animation& animation, float progress )
+{
+  typedef MessageValue1< Animation, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetCurrentProgress, progress );
+}
+
+inline void SetSpeedFactorMessage( EventThreadServices& eventThreadServices, const Animation& animation, float factor )
+{
+  typedef MessageValue1< Animation, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetSpeedFactor, factor );
+}
+
+inline void SetPlayRangeMessage( EventThreadServices& eventThreadServices, const Animation& animation, const Vector2& range )
+{
+  typedef MessageValue1< Animation, Vector2 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::SetPlayRange, range );
+}
+
+inline void PlayAnimationMessage( EventThreadServices& eventThreadServices, const Animation& animation )
+{
+  typedef Message< Animation > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::Play );
+}
+
+inline void PlayAnimationFromMessage( EventThreadServices& eventThreadServices, const Animation& animation, float progress )
+{
+  typedef MessageValue1< Animation,float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::PlayFrom, progress );
+}
+
+inline void PauseAnimationMessage( EventThreadServices& eventThreadServices, const Animation& animation )
+{
+  typedef Message< Animation > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::Pause );
+}
+
+inline void AddAnimatorMessage( EventThreadServices& eventThreadServices, const Animation& animation, AnimatorBase& animator )
+{
+  typedef MessageValue1< Animation, OwnerPointer<AnimatorBase> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &animation, &Animation::AddAnimator, &animator );
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_ANIMATION_H__
diff --git a/dali/internal/update/animation/scene-graph-animator.h b/dali/internal/update/animation/scene-graph-animator.h
new file mode 100644 (file)
index 0000000..e153b86
--- /dev/null
@@ -0,0 +1,1021 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/event/animation/key-frames-impl.h>
+#include <dali/internal/event/animation/path-impl.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/animation/time-period.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/radian.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Dali::Animation::Interpolation Interpolation;
+
+struct AnimatorFunctionBase;
+
+namespace SceneGraph
+{
+
+class AnimatorBase;
+
+typedef OwnerContainer< AnimatorBase* > AnimatorContainer;
+
+typedef AnimatorContainer::Iterator AnimatorIter;
+typedef AnimatorContainer::ConstIterator AnimatorConstIter;
+
+/**
+ * An abstract base class for Animators, which can be added to scene graph animations.
+ * Each animator changes a single property of an object in the scene graph.
+ */
+class AnimatorBase
+{
+public:
+
+  typedef float (*AlphaFunc)(float progress); ///< Definition of an alpha function
+
+  /**
+   * Constructor.
+   */
+  AnimatorBase()
+  : mDurationSeconds(1.0f),
+    mInitialDelaySeconds(0.0f),
+    mAlphaFunction(AlphaFunction::DEFAULT),
+    mDisconnectAction(Dali::Animation::BakeFinal),
+    mActive(false),
+    mEnabled(true),
+    mConnectedToSceneGraph(false)
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatorBase()
+  {
+  }
+
+  /**
+   * Called when Animator is added to the scene-graph in update-thread.
+   */
+  virtual void ConnectToSceneGraph() = 0;
+
+  /**
+   * Set the duration of the animator.
+   * @pre durationSeconds must be zero or greater; zero is useful when animating boolean values.
+   * @param [in] seconds Duration in seconds.
+   */
+  void SetDuration(float seconds)
+  {
+    DALI_ASSERT_DEBUG(seconds >= 0.0f);
+
+    mDurationSeconds = seconds;
+  }
+
+  /**
+   * Retrieve the duration of the animator.
+   * @return The duration in seconds.
+   */
+  float GetDuration()
+  {
+    return mDurationSeconds;
+  }
+
+  /**
+   * Set the delay before the animator should take effect.
+   * The default is zero i.e. no delay.
+   * @param [in] seconds The delay in seconds.
+   */
+  void SetInitialDelay(float seconds)
+  {
+    mInitialDelaySeconds = seconds;
+  }
+
+  /**
+   * Retrieve the initial delay of the animator.
+   * @return The delay in seconds.
+   */
+  float GetInitialDelay()
+  {
+    return mInitialDelaySeconds;
+  }
+
+  /**
+   * Set the alpha function for an animator.
+   * @param [in] alphaFunc The alpha function to apply to the animation progress.
+   */
+  void SetAlphaFunction(const AlphaFunction& alphaFunction)
+  {
+    mAlphaFunction = alphaFunction;
+  }
+
+  /**
+   * Retrieve the alpha function of an animator.
+   * @return The function.
+   */
+  AlphaFunction GetAlphaFunction() const
+  {
+    return mAlphaFunction;
+  }
+
+  /*
+   * Applies the alpha function to the specified progress
+   * @param[in] Current progress
+   * @return The progress after the alpha function has been aplied
+   */
+  float ApplyAlphaFunction( float progress ) const
+  {
+    float result = progress;
+
+    AlphaFunction::Mode alphaFunctionMode( mAlphaFunction.GetMode() );
+    if( alphaFunctionMode == AlphaFunction::BUILTIN_FUNCTION )
+    {
+      switch(mAlphaFunction.GetBuiltinFunction())
+      {
+        case AlphaFunction::DEFAULT:
+        case AlphaFunction::LINEAR:
+        {
+          break;
+        }
+        case AlphaFunction::REVERSE:
+        {
+          result = 1.0f-progress;
+          break;
+        }
+        case AlphaFunction::EASE_IN_SQUARE:
+        {
+          result = progress * progress;
+          break;
+        }
+        case AlphaFunction::EASE_OUT_SQUARE:
+        {
+          result = 1.0f - (1.0f-progress) * (1.0f-progress);
+          break;
+        }
+        case AlphaFunction::EASE_IN:
+        {
+          result = progress * progress * progress;
+          break;
+        }
+        case AlphaFunction::EASE_OUT:
+        {
+          result = (progress-1.0f) * (progress-1.0f) * (progress-1.0f) + 1.0f;
+          break;
+        }
+        case AlphaFunction::EASE_IN_OUT:
+        {
+          result = progress*progress*(3.0f-2.0f*progress);
+          break;
+        }
+        case AlphaFunction::EASE_IN_SINE:
+        {
+          result = -1.0f * cosf(progress * Math::PI_2) + 1.0f;
+          break;
+        }
+        case AlphaFunction::EASE_OUT_SINE:
+        {
+          result = sinf(progress * Math::PI_2);
+          break;
+        }
+        case AlphaFunction::EASE_IN_OUT_SINE:
+        {
+          result = -0.5f * (cosf(Math::PI * progress) - 1.0f);
+          break;
+        }
+        case AlphaFunction::BOUNCE:
+        {
+          result = sinf(progress * Math::PI);
+          break;
+        }
+        case AlphaFunction::SIN:
+        {
+          result = 0.5f - cosf(progress * 2.0f * Math::PI) * 0.5f;
+          break;
+        }
+        case AlphaFunction::EASE_OUT_BACK:
+        {
+          const float sqrt2 = 1.70158f;
+          progress -= 1.0f;
+          result = 1.0f + progress * progress * ( ( sqrt2 + 1.0f ) * progress + sqrt2 );
+          break;
+        }
+        case AlphaFunction::COUNT:
+        {
+          break;
+        }
+      }
+    }
+    else if(  alphaFunctionMode == AlphaFunction::CUSTOM_FUNCTION )
+    {
+      AlphaFunctionPrototype customFunction = mAlphaFunction.GetCustomFunction();
+      if( customFunction )
+      {
+        result = customFunction(progress);
+      }
+    }
+    else
+    {
+      //If progress is very close to 0 or very close to 1 we don't need to evaluate the curve as the result will
+      //be almost 0 or almost 1 respectively
+      if( ( progress > Math::MACHINE_EPSILON_1 ) && ((1.0f - progress) > Math::MACHINE_EPSILON_1) )
+      {
+        Dali::Vector4 controlPoints = mAlphaFunction.GetBezierControlPoints();
+
+        static const float tolerance = 0.001f;  //10 iteration max
+
+        //Perform a binary search on the curve
+        float lowerBound(0.0f);
+        float upperBound(1.0f);
+        float currentT(0.5f);
+        float currentX = EvaluateCubicBezier( controlPoints.x, controlPoints.z, currentT);
+        while( fabs( progress - currentX ) > tolerance )
+        {
+          if( progress > currentX )
+          {
+            lowerBound = currentT;
+          }
+          else
+          {
+            upperBound = currentT;
+          }
+          currentT = (upperBound+lowerBound)*0.5f;
+          currentX = EvaluateCubicBezier( controlPoints.x, controlPoints.z, currentT);
+        }
+        result = EvaluateCubicBezier( controlPoints.y, controlPoints.w, currentT);
+      }
+    }
+
+    return result;
+  }
+
+  /**
+   * Whether to bake the animation if attached property owner is disconnected.
+   * Property is only baked if the animator is active.
+   * @param [in] action The disconnect action.
+   */
+  void SetDisconnectAction( Dali::Animation::EndAction action )
+  {
+    mDisconnectAction = action;
+  }
+
+  /**
+   * Retrieve the disconnect action of an animator.
+   * @return The disconnect action.
+   */
+  Dali::Animation::EndAction GetDisconnectAction() const
+  {
+    return mDisconnectAction;
+  }
+
+  /**
+   * Whether the animator is active or not.
+   * @param [in] active The new active state.
+   * @post When the animator becomes active, it applies the disconnect-action if the property owner is then disconnected.
+   * @note When the property owner is disconnected, the active state is set to false.
+   */
+  void SetActive( bool active )
+  {
+    mActive = active;
+  }
+
+  /**
+   * Retrieve whether the animator has been set to active or not.
+   * @return The active state.
+   */
+  bool GetActive() const
+  {
+    return mActive;
+  }
+
+  /*
+   * Retrive wheter the animator's target object is valid and on the stage.
+   * @return The enabled state.
+   */
+  bool IsEnabled() const
+  {
+    return mEnabled;
+  }
+  /**
+   * Returns wheter the target object of the animator is still valid
+   * or has been destroyed.
+   * @return True if animator is orphan, false otherwise   *
+   * @note The SceneGraph::Animation will delete any orphan animator in its Update method.
+   */
+  virtual bool Orphan() = 0;
+
+  /**
+   * Update the scene object attached to the animator.
+   * @param[in] bufferIndex The buffer to animate.
+   * @param[in] progress A value from 0 to 1, where 0 is the start of the animation, and 1 is the end point.
+   * @param[in] bake Bake.
+   */
+  virtual void Update(BufferIndex bufferIndex, float progress, bool bake) = 0;
+
+protected:
+
+  /**
+   * Helper function to evaluate a cubic bezier curve assuming first point is at 0.0 and last point is at 1.0
+   * @param[in] p0 First control point of the bezier curve
+   * @param[in] p1 Second control point of the bezier curve
+   * @param[in] t A floating point value between 0.0 and 1.0
+   * @return Value of the curve at progress t
+   */
+  inline float EvaluateCubicBezier( float p0, float p1, float t ) const
+  {
+    float tSquare = t*t;
+    return 3.0f*(1.0f-t)*(1.0f-t)*t*p0 + 3.0f*(1.0f-t)*tSquare*p1 + tSquare*t;
+  }
+
+  float mDurationSeconds;
+  float mInitialDelaySeconds;
+
+  AlphaFunction mAlphaFunction;
+
+  Dali::Animation::EndAction mDisconnectAction;     ///< EndAction to apply when target object gets disconnected from the stage.
+  bool mActive:1;                                   ///< Animator is "active" while it's running.
+  bool mEnabled:1;                                  ///< Animator is "enabled" while its target object is valid and on the stage.
+  bool mConnectedToSceneGraph:1;                    ///< True if ConnectToSceneGraph() has been called in update-thread.
+};
+
+/**
+ * An animator for a specific property type PropertyType.
+ */
+template < typename PropertyType, typename PropertyAccessorType >
+class Animator : public AnimatorBase, public PropertyOwner::Observer
+{
+public:
+
+  /**
+   * Construct a new property animator.
+   * @param[in] property The animatable property; only valid while the Animator is attached.
+   * @param[in] animatorFunction The function used to animate the property.
+   * @param[in] alphaFunction The alpha function to apply.
+   * @param[in] timePeriod The time period of this animation.
+   * @return A newly allocated animator.
+   */
+  static AnimatorBase* New( const PropertyOwner& propertyOwner,
+                            const PropertyBase& property,
+                            AnimatorFunctionBase* animatorFunction,
+                            AlphaFunction alphaFunction,
+                            const TimePeriod& timePeriod )
+  {
+    typedef Animator< PropertyType, PropertyAccessorType > AnimatorType;
+
+    // The property was const in the actor-thread, but animators are used in the scene-graph thread.
+    AnimatorType* animator = new AnimatorType( const_cast<PropertyOwner*>( &propertyOwner ),
+                                               const_cast<PropertyBase*>( &property ),
+                                               animatorFunction );
+
+    animator->SetAlphaFunction( alphaFunction );
+    animator->SetInitialDelay( timePeriod.delaySeconds );
+    animator->SetDuration( timePeriod.durationSeconds );
+
+    return animator;
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Animator()
+  {
+    if (mPropertyOwner && mConnectedToSceneGraph)
+    {
+      mPropertyOwner->RemoveObserver(*this);
+    }
+
+    if( mAnimatorFunction )
+    {
+      delete mAnimatorFunction;
+    }
+  }
+
+  /**
+   * Called when Animator is added to the scene-graph in update-thread.
+   */
+  virtual void ConnectToSceneGraph()
+  {
+    mConnectedToSceneGraph = true;
+    mPropertyOwner->AddObserver(*this);
+  }
+
+  /**
+   * Called when mPropertyOwner is connected to the scene graph.
+   */
+  virtual void PropertyOwnerConnected( PropertyOwner& owner )
+  {
+    mEnabled = true;
+  }
+
+  /**
+   * Called when mPropertyOwner is disconnected from the scene graph.
+   */
+  virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
+  {
+    // If we are active, then bake the value if required
+    if ( mActive && mDisconnectAction != Dali::Animation::Discard )
+    {
+      // Bake to target-value if BakeFinal, otherwise bake current value
+      Update( bufferIndex, ( mDisconnectAction == Dali::Animation::Bake ? mCurrentProgress : 1.0f ), true );
+    }
+
+    mActive = false;
+    mEnabled = false;
+  }
+
+  /**
+   * Called shortly before mPropertyOwner is destroyed
+   */
+  virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
+  {
+    mPropertyOwner = NULL;
+    mPropertyAccessor.Reset();
+    mEnabled = false;
+  }
+
+  /**
+   * From AnimatorBase.
+   */
+  virtual void Update( BufferIndex bufferIndex, float progress, bool bake )
+  {
+    float alpha = ApplyAlphaFunction(progress);
+
+    const PropertyType& current = mPropertyAccessor.Get( bufferIndex );
+
+    const PropertyType result = (*mAnimatorFunction)( alpha, current );
+    if ( bake )
+    {
+      mPropertyAccessor.Bake( bufferIndex, result );
+    }
+    else
+    {
+      mPropertyAccessor.Set( bufferIndex, result );
+    }
+
+    mCurrentProgress = progress;
+  }
+
+  /**
+   * From AnimatorBase.
+   */
+  virtual bool Orphan()
+  {
+    return (mPropertyOwner == NULL);
+  }
+
+private:
+
+  /**
+   * Private constructor; see also Animator::New().
+   */
+  Animator( PropertyOwner* propertyOwner,
+            PropertyBase* property,
+            AnimatorFunctionBase* animatorFunction )
+  : mPropertyOwner( propertyOwner ),
+    mPropertyAccessor( property ),
+    mAnimatorFunction( animatorFunction ),
+    mCurrentProgress( 0.0f )
+  {
+    // WARNING - this object is created in the event-thread
+    // The scene-graph mPropertyOwner object cannot be observed here
+  }
+
+  // Undefined
+  Animator( const Animator& );
+
+  // Undefined
+  Animator& operator=( const Animator& );
+
+protected:
+
+  PropertyOwner* mPropertyOwner;
+  PropertyAccessorType mPropertyAccessor;
+
+  AnimatorFunctionBase* mAnimatorFunction;
+  float mCurrentProgress;
+};
+
+} // namespace SceneGraph
+
+/*
+ * AnimatorFunction base class.
+ * All update functions must inherit from AnimatorFunctionBase and overload the appropiate "()" operator
+ */
+struct AnimatorFunctionBase
+{
+  /**
+   * Constructor
+   */
+  AnimatorFunctionBase(){}
+
+  /*
+   * Virtual destructor (Intended as base class)
+   */
+  virtual ~AnimatorFunctionBase(){}
+
+  ///Stub "()" operators.
+  virtual bool operator()(float progress, const bool& property)
+  {
+    return property;
+  }
+
+  virtual float operator()(float progress, const int& property)
+  {
+    return property;
+  }
+
+  virtual float operator()(float progress, const unsigned int& property)
+  {
+    return property;
+  }
+
+  virtual float operator()(float progress, const float& property)
+  {
+    return property;
+  }
+
+  virtual Vector2 operator()(float progress, const Vector2& property)
+  {
+    return property;
+  }
+
+  virtual Vector3 operator()(float progress, const Vector3& property)
+  {
+    return property;
+  }
+
+  virtual Vector4 operator()(float progress, const Vector4& property)
+  {
+    return property;
+  }
+
+  virtual Quaternion operator()(float progress, const Quaternion& property)
+  {
+    return property;
+  }
+};
+
+// Update functions
+
+struct AnimateByInteger : public AnimatorFunctionBase
+{
+  AnimateByInteger(const int& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  float operator()(float alpha, const int& property)
+  {
+    return int(property + mRelative * alpha + 0.5f );
+  }
+
+  int mRelative;
+};
+
+struct AnimateToInteger : public AnimatorFunctionBase
+{
+  AnimateToInteger(const int& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  float operator()(float alpha, const int& property)
+  {
+    return int(property + ((mTarget - property) * alpha) + 0.5f);
+  }
+
+  int mTarget;
+};
+
+struct AnimateByFloat : public AnimatorFunctionBase
+{
+  AnimateByFloat(const float& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  float operator()(float alpha, const float& property)
+  {
+    return float(property + mRelative * alpha);
+  }
+
+  float mRelative;
+};
+
+struct AnimateToFloat : public AnimatorFunctionBase
+{
+  AnimateToFloat(const float& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  float operator()(float alpha, const float& property)
+  {
+    return float(property + ((mTarget - property) * alpha));
+  }
+
+  float mTarget;
+};
+
+struct AnimateByVector2 : public AnimatorFunctionBase
+{
+  AnimateByVector2(const Vector2& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  Vector2 operator()(float alpha, const Vector2& property)
+  {
+    return Vector2(property + mRelative * alpha);
+  }
+
+  Vector2 mRelative;
+};
+
+struct AnimateToVector2 : public AnimatorFunctionBase
+{
+  AnimateToVector2(const Vector2& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  Vector2 operator()(float alpha, const Vector2& property)
+  {
+    return Vector2(property + ((mTarget - property) * alpha));
+  }
+
+  Vector2 mTarget;
+};
+
+struct AnimateByVector3 : public AnimatorFunctionBase
+{
+  AnimateByVector3(const Vector3& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  Vector3 operator()(float alpha, const Vector3& property)
+  {
+    return Vector3(property + mRelative * alpha);
+  }
+
+  Vector3 mRelative;
+};
+
+struct AnimateToVector3 : public AnimatorFunctionBase
+{
+  AnimateToVector3(const Vector3& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  Vector3 operator()(float alpha, const Vector3& property)
+  {
+    return Vector3(property + ((mTarget - property) * alpha));
+  }
+
+  Vector3 mTarget;
+};
+
+struct AnimateByVector4 : public AnimatorFunctionBase
+{
+  AnimateByVector4(const Vector4& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  Vector4 operator()(float alpha, const Vector4& property)
+  {
+    return Vector4(property + mRelative * alpha);
+  }
+
+  Vector4 mRelative;
+};
+
+struct AnimateToVector4 : public AnimatorFunctionBase
+{
+  AnimateToVector4(const Vector4& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  Vector4 operator()(float alpha, const Vector4& property)
+  {
+    return Vector4(property + ((mTarget - property) * alpha));
+  }
+
+  Vector4 mTarget;
+};
+
+struct AnimateByOpacity : public AnimatorFunctionBase
+{
+  AnimateByOpacity(const float& relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  Vector4 operator()(float alpha, const Vector4& property)
+  {
+    Vector4 result(property);
+    result.a += mRelative * alpha;
+
+    return result;
+  }
+
+  float mRelative;
+};
+
+struct AnimateToOpacity : public AnimatorFunctionBase
+{
+  AnimateToOpacity(const float& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  Vector4 operator()(float alpha, const Vector4& property)
+  {
+    Vector4 result(property);
+    result.a = property.a + ((mTarget - property.a) * alpha);
+
+    return result;
+  }
+
+  float mTarget;
+};
+
+struct AnimateByBoolean : public AnimatorFunctionBase
+{
+  AnimateByBoolean(bool relativeValue)
+  : mRelative(relativeValue)
+  {
+  }
+
+  bool operator()(float alpha, const bool& property)
+  {
+    // Alpha is not useful here, just keeping to the same template as other update functors
+    return bool(alpha >= 1.0f ? (property || mRelative) : property);
+  }
+
+  bool mRelative;
+};
+
+struct AnimateToBoolean : public AnimatorFunctionBase
+{
+  AnimateToBoolean(bool targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  bool operator()(float alpha, const bool& property)
+  {
+    // Alpha is not useful here, just keeping to the same template as other update functors
+    return bool(alpha >= 1.0f ? mTarget : property);
+  }
+
+  bool mTarget;
+};
+
+struct RotateByAngleAxis : public AnimatorFunctionBase
+{
+  RotateByAngleAxis(const Radian& angleRadians, const Vector3& axis)
+  : mAngleRadians( angleRadians ),
+    mAxis(axis.x, axis.y, axis.z)
+  {
+  }
+
+  Quaternion operator()(float alpha, const Quaternion& rotation)
+  {
+    if (alpha > 0.0f)
+    {
+      return rotation * Quaternion(mAngleRadians * alpha, mAxis);
+    }
+
+    return rotation;
+  }
+
+  Radian mAngleRadians;
+  Vector3 mAxis;
+};
+
+struct RotateToQuaternion : public AnimatorFunctionBase
+{
+  RotateToQuaternion(const Quaternion& targetValue)
+  : mTarget(targetValue)
+  {
+  }
+
+  Quaternion operator()(float alpha, const Quaternion& rotation)
+  {
+    return Quaternion::Slerp(rotation, mTarget, alpha);
+  }
+
+  Quaternion mTarget;
+};
+
+
+struct KeyFrameBooleanFunctor : public AnimatorFunctionBase
+{
+  KeyFrameBooleanFunctor(KeyFrameBooleanPtr keyFrames)
+  : mKeyFrames(keyFrames)
+  {
+  }
+
+  bool operator()(float progress, const bool& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
+    }
+    return property;
+  }
+
+  KeyFrameBooleanPtr mKeyFrames;
+};
+
+struct KeyFrameIntegerFunctor : public AnimatorFunctionBase
+{
+  KeyFrameIntegerFunctor(KeyFrameIntegerPtr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
+  {
+  }
+
+  float operator()(float progress, const int& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, mInterpolation);
+    }
+    return property;
+  }
+
+  KeyFrameIntegerPtr mKeyFrames;
+  Interpolation mInterpolation;
+};
+
+struct KeyFrameNumberFunctor : public AnimatorFunctionBase
+{
+  KeyFrameNumberFunctor(KeyFrameNumberPtr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
+  {
+  }
+
+  float operator()(float progress, const float& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, mInterpolation);
+    }
+    return property;
+  }
+
+  KeyFrameNumberPtr mKeyFrames;
+  Interpolation mInterpolation;
+};
+
+struct KeyFrameVector2Functor : public AnimatorFunctionBase
+{
+  KeyFrameVector2Functor(KeyFrameVector2Ptr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
+  {
+  }
+
+  Vector2 operator()(float progress, const Vector2& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, mInterpolation);
+    }
+    return property;
+  }
+
+  KeyFrameVector2Ptr mKeyFrames;
+  Interpolation mInterpolation;
+};
+
+
+struct KeyFrameVector3Functor : public AnimatorFunctionBase
+{
+  KeyFrameVector3Functor(KeyFrameVector3Ptr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
+  {
+  }
+
+  Vector3 operator()(float progress, const Vector3& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, mInterpolation);
+    }
+    return property;
+  }
+
+  KeyFrameVector3Ptr mKeyFrames;
+  Interpolation mInterpolation;
+};
+
+struct KeyFrameVector4Functor : public AnimatorFunctionBase
+{
+  KeyFrameVector4Functor(KeyFrameVector4Ptr keyFrames, Interpolation interpolation)
+  : mKeyFrames(keyFrames),mInterpolation(interpolation)
+  {
+  }
+
+  Vector4 operator()(float progress, const Vector4& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, mInterpolation);
+    }
+    return property;
+  }
+
+  KeyFrameVector4Ptr mKeyFrames;
+  Interpolation mInterpolation;
+};
+
+struct KeyFrameQuaternionFunctor : public AnimatorFunctionBase
+{
+  KeyFrameQuaternionFunctor(KeyFrameQuaternionPtr keyFrames)
+  : mKeyFrames(keyFrames)
+  {
+  }
+
+  Quaternion operator()(float progress, const Quaternion& property)
+  {
+    if(mKeyFrames->IsActive(progress))
+    {
+      return mKeyFrames->GetValue(progress, Dali::Animation::Linear);
+    }
+    return property;
+  }
+
+  KeyFrameQuaternionPtr mKeyFrames;
+};
+
+struct PathPositionFunctor : public AnimatorFunctionBase
+{
+  PathPositionFunctor( PathPtr path )
+  : mPath(path)
+  {
+  }
+
+  Vector3 operator()(float progress, const Vector3& property)
+  {
+    return mPath->SamplePosition(progress );
+  }
+
+  PathPtr mPath;
+};
+
+struct PathRotationFunctor : public AnimatorFunctionBase
+{
+  PathRotationFunctor( PathPtr path, const Vector3& forward )
+  : mPath(path),
+    mForward( forward )
+  {
+    mForward.Normalize();
+  }
+
+  Quaternion operator()(float progress, const Quaternion& property)
+  {
+    Vector3 tangent( mPath->SampleTangent(progress) );
+    return Quaternion( mForward, tangent );
+  }
+
+  PathPtr mPath;
+  Vector3 mForward;
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_ANIMATOR_H__
diff --git a/dali/internal/update/animation/scene-graph-constraint-base.cpp b/dali/internal/update/animation/scene-graph-constraint-base.cpp
new file mode 100644 (file)
index 0000000..85bf625
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/animation/scene-graph-constraint.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+#ifdef DEBUG_ENABLED
+  unsigned int ConstraintBase::mCurrentInstanceCount = 0;
+  unsigned int ConstraintBase::mTotalInstanceCount   = 0;
+#endif
+
+ConstraintBase::ConstraintBase( PropertyOwnerContainer& ownerSet )
+: mRemoveAction( Dali::Constraint::DEFAULT_REMOVE_ACTION ),
+  mFirstApply( true ),
+  mDisconnected( true ),
+  mObservedOwners( ownerSet )
+{
+#ifdef DEBUG_ENABLED
+  ++mCurrentInstanceCount;
+  ++mTotalInstanceCount;
+#endif
+}
+
+ConstraintBase::~ConstraintBase()
+{
+  if ( !mDisconnected )
+  {
+    StopObservation();
+  }
+
+#ifdef DEBUG_ENABLED
+  --mCurrentInstanceCount;
+#endif
+}
+
+void ConstraintBase::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( false );
+}
+
+unsigned int ConstraintBase::GetCurrentInstanceCount()
+{
+#ifdef DEBUG_ENABLED
+  return mCurrentInstanceCount;
+#else
+  return 0u;
+#endif
+}
+
+unsigned int ConstraintBase::GetTotalInstanceCount()
+{
+#ifdef DEBUG_ENABLED
+  return mTotalInstanceCount;
+#else
+  return 0u;
+#endif
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/animation/scene-graph-constraint-base.h b/dali/internal/update/animation/scene-graph-constraint-base.h
new file mode 100644 (file)
index 0000000..1df4546
--- /dev/null
@@ -0,0 +1,236 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/animation/scene-graph-constraint-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< Dali::Constraint::RemoveAction >
+: public BasicType< Dali::Constraint::RemoveAction > {};
+
+namespace SceneGraph
+{
+
+typedef Dali::Vector<PropertyOwner*>     PropertyOwnerContainer;
+typedef PropertyOwnerContainer::Iterator PropertyOwnerIter;
+
+/**
+ * An abstract base class for Constraints.
+ * This can be used to constrain a property of a scene-object, after animations have been applied.
+ */
+class ConstraintBase : public PropertyOwner, public PropertyOwner::Observer
+{
+public:
+
+  typedef Dali::Constraint::RemoveAction RemoveAction;
+
+  /**
+   * Constructor
+   */
+  ConstraintBase( PropertyOwnerContainer& ownerContainer );
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~ConstraintBase();
+
+  /**
+   * Initialize the constraint.
+   * This should by called by a scene-object, when the constraint is connected.
+   */
+  void OnConnect()
+  {
+    StartObservation();
+
+    mDisconnected = false;
+  }
+
+  /**
+   * @copydoc Dali::Constraint::SetRemoveAction()
+   */
+  void SetRemoveAction( RemoveAction action )
+  {
+    mRemoveAction = action;
+  }
+
+  /**
+   * @copydoc Dali::Constraint::GetRemoveAction()
+   */
+  RemoveAction GetRemoveAction() const
+  {
+    return mRemoveAction;
+  }
+
+  /**
+   * Constrain the associated scene object.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  virtual void Apply( BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Helper for internal test cases; only available for debug builds.
+   * @return The current number of Constraint instances in existence.
+   */
+  static unsigned int GetCurrentInstanceCount();
+
+  /**
+   * Helper for internal test cases; only available for debug builds.
+   * @return The total number of Constraint instances created during the Dali core lifetime.
+   */
+  static unsigned int GetTotalInstanceCount();
+
+private:
+
+  /**
+   * Helper to start observing property owners
+   */
+  void StartObservation()
+  {
+    const PropertyOwnerIter end =  mObservedOwners.End();
+    for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
+    {
+      (*iter)->AddObserver( *this );
+    }
+  }
+
+  /**
+   * Helper to stop observing property owners
+   */
+  void StopObservation()
+  {
+    const PropertyOwnerIter end =  mObservedOwners.End();
+    for( PropertyOwnerIter iter = mObservedOwners.Begin(); end != iter; ++iter )
+    {
+      (*iter)->RemoveObserver( *this );
+    }
+
+    mObservedOwners.Clear();
+  }
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerConnected()
+   */
+  virtual void PropertyOwnerConnected( PropertyOwner& owner )
+  {
+  }
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerDisconnected()
+   */
+  virtual void PropertyOwnerDisconnected( BufferIndex bufferIndex, PropertyOwner& owner )
+  {
+    if ( !mDisconnected )
+    {
+      // Stop observing property owners
+      StopObservation();
+
+      // Notification for derived class
+      OnDisconnect();
+
+      mDisconnected = true;
+    }
+  }
+
+  /**
+   * @copydoc PropertyOwner::Observer::PropertyOwnerDestroyed()
+   */
+  virtual void PropertyOwnerDestroyed( PropertyOwner& owner )
+  {
+    if ( !mDisconnected )
+    {
+      // Discard pointer to destroyed property owner. Otherwise StopObservation() would crash when trying to remove
+      //the constraint from the destroyed PropertyOwner's observers list
+      PropertyOwnerIter iter = std::find( mObservedOwners.Begin(), mObservedOwners.End(), &owner );
+      if( mObservedOwners.End() != iter )
+      {
+        mObservedOwners.Erase( iter );
+      }
+
+      // Stop observing the rest of property owners
+      StopObservation();
+
+      // Notification for derived class
+      OnDisconnect();
+
+      mDisconnected = true;
+
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+  /**
+   * Notify the derived class to disconnect from property owners
+   */
+  virtual void OnDisconnect() = 0;
+
+protected:
+
+  RemoveAction mRemoveAction;
+
+  bool mFirstApply   : 1;
+  bool mDisconnected : 1;
+
+private:
+
+  PropertyOwnerContainer mObservedOwners; ///< A set of pointers to each observed object. Not owned.
+
+#ifdef DEBUG_ENABLED
+  static unsigned int mCurrentInstanceCount;  ///< The current number of Constraint instances in existence.
+  static unsigned int mTotalInstanceCount;    ///< The total number of Constraint instances created during the Dali core lifetime.
+#endif
+};
+
+// Messages for ConstraintBase
+
+inline void  SetRemoveActionMessage( EventThreadServices& eventThreadServices, const ConstraintBase& constraint, Dali::Constraint::RemoveAction removeAction )
+{
+  typedef MessageValue1< ConstraintBase, Dali::Constraint::RemoveAction > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &constraint, &ConstraintBase::SetRemoveAction, removeAction );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_BASE_H__
diff --git a/dali/internal/update/animation/scene-graph-constraint-declarations.h b/dali/internal/update/animation/scene-graph-constraint-declarations.h
new file mode 100644 (file)
index 0000000..60039db
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_DECLARATIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class ConstraintBase;
+
+typedef OwnerContainer< ConstraintBase* > ConstraintOwnerContainer;
+typedef ConstraintOwnerContainer::Iterator ConstraintIter;
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_DECLARATIONS_H__
diff --git a/dali/internal/update/animation/scene-graph-constraint.h b/dali/internal/update/animation/scene-graph-constraint.h
new file mode 100644 (file)
index 0000000..50a9a70
--- /dev/null
@@ -0,0 +1,175 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/signals/callback.h>
+#include <dali/internal/event/animation/property-constraint-ptr.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Used to constrain a property of a scene-object.
+ * The constraint function takes another scene-object property as an input.
+ */
+template < class PropertyType, typename PropertyAccessorType >
+class Constraint : public ConstraintBase
+{
+public:
+
+  typedef typename PropertyConstraintPtr< PropertyType >::Type ConstraintFunctionPtr;
+
+  /**
+   * Create a new scene-graph constraint.
+   * @param[in] targetProperty The target property.
+   * @param[in] ownerSet A set of property owners; func is connected to the properties provided by these objects.
+   * @param[in] func The function to calculate the final constrained value.
+   * @return A smart-pointer to a newly allocated constraint.
+   */
+  static ConstraintBase* New( const PropertyBase& targetProperty,
+                              PropertyOwnerContainer& ownerContainer,
+                              ConstraintFunctionPtr func )
+  {
+    // Scene-graph thread can edit these objects
+    PropertyBase& property = const_cast< PropertyBase& >( targetProperty );
+
+    return new Constraint< PropertyType, PropertyAccessorType >( property,
+                                                                 ownerContainer,
+                                                                 func );
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~Constraint()
+  {
+  }
+
+  /**
+   * Query whether the constraint needs to be applied. If a constraint depends on a set of properties,
+   * then it should be applied when any of those properties have changed.
+   */
+  bool ApplyNeeded()
+  {
+    if ( mFirstApply )
+    {
+      mFirstApply = false;
+      return true;
+    }
+
+    if ( ! mTargetProperty.IsClean() ||
+           mFunc->InputsChanged() )
+    {
+      return true;
+    }
+
+    // We don't need to reapply constraint if none of the properties changed
+    return false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::ConstraintBase::Apply()
+   */
+  virtual void Apply( BufferIndex updateBufferIndex )
+  {
+    if ( mDisconnected )
+    {
+      return; // Early-out when property owners have been disconnected
+    }
+
+    if ( mFunc->InputsInitialized() &&
+         ApplyNeeded() )
+    {
+      PropertyType current = mTargetProperty.Get( updateBufferIndex );
+      mFunc->Apply( updateBufferIndex, current );
+
+      // Optionally bake the final value
+      if ( Dali::Constraint::Bake == mRemoveAction )
+      {
+        mTargetProperty.Bake( updateBufferIndex, current );
+      }
+      else
+      {
+        mTargetProperty.Set( updateBufferIndex, current );
+      }
+
+      INCREASE_COUNTER(PerformanceMonitor::CONSTRAINTS_APPLIED);
+    }
+    else
+    {
+      INCREASE_COUNTER(PerformanceMonitor::CONSTRAINTS_SKIPPED);
+    }
+  }
+
+private:
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::Constraint::New()
+   */
+  Constraint( PropertyBase& targetProperty,
+              PropertyOwnerContainer& ownerContainer,
+              ConstraintFunctionPtr func )
+  : ConstraintBase( ownerContainer ),
+    mTargetProperty( &targetProperty ),
+    mFunc( func )
+  {
+  }
+
+  // Undefined
+  Constraint( const Constraint& constraint );
+
+  // Undefined
+  Constraint& operator=( const Constraint& rhs );
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::ConstraintBase::OnDisconnect()
+   */
+  virtual void OnDisconnect()
+  {
+    // Discard target object/property pointers
+    mTargetProperty.Reset();
+    mFunc = NULL;
+  }
+
+protected:
+
+  PropertyAccessorType mTargetProperty; ///< Raw-pointer to the target property. Not owned.
+
+  ConstraintFunctionPtr mFunc;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_CONSTRAINT_H__
diff --git a/dali/internal/update/common/animatable-property.h b/dali/internal/update/common/animatable-property.h
new file mode 100644 (file)
index 0000000..a05d545
--- /dev/null
@@ -0,0 +1,2202 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_ANIMATABLE_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_ANIMATABLE_PROPERTY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Dirty flags record whether an animatable property has changed.
+ * In the frame following a change, the property is reset to a base value.
+ *
+ * If the property was "Baked", then the base value matches the (double-buffered) value from the previous frame.
+ * Therefore when reset, the property is flagged as "clean".
+ *
+ * However if the property was only "Set" (and not "Baked"), then typically the base value and previous value will not match.
+ * In this case the reset operation is equivalent to a "Bake", and the value is considered "dirty" for an additional frame.
+ */
+static const unsigned int CLEAN_FLAG = 0x00; ///< Indicates that the value did not change in this, or the previous frame
+static const unsigned int BAKED_FLAG = 0x01; ///< Indicates that the value was Baked during the previous frame
+static const unsigned int SET_FLAG   = 0x02; ///< Indicates that the value was Set during the previous frame
+
+template <class T>
+class AnimatableProperty;
+
+/**
+ * Base class to reduce code size from the templates.
+ */
+class AnimatablePropertyBase : public PropertyBase
+{
+public:
+
+  /**
+   * Constructor, initialize the dirty flag
+   */
+  AnimatablePropertyBase()
+  : PropertyBase(),
+    mDirtyFlags( BAKED_FLAG )
+  {}
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatablePropertyBase()
+  {}
+
+protected: // for derived classes
+
+  /**
+   * Flag that the property has been Set during the current frame.
+   */
+  void OnSet()
+  {
+    mDirtyFlags = SET_FLAG;
+  }
+
+  /**
+   * Flag that the property has been Baked during the current frame.
+   */
+  void OnBake()
+  {
+    mDirtyFlags = BAKED_FLAG;
+  }
+
+public: // From PropertyBase
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return ( CLEAN_FLAG == mDirtyFlags );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true; // Animatable properties are always valid
+  }
+
+protected: // so that ResetToBaseValue can set it directly
+
+  unsigned int mDirtyFlags; ///< Flag whether value changed during previous 2 frames
+
+};
+
+
+/**
+ * An boolean animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<bool> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( bool initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<bool>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetBoolean()
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, bool value)
+  {
+    // check if the value actually changed to avoid dirtying nodes unnecessarily
+    if( mValue[bufferIndex] != value )
+    {
+      mValue[bufferIndex] = value;
+
+      OnSet();
+    }
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, bool delta)
+  {
+    // check if the value actually changed to avoid dirtying nodes unnecessarily
+    // false + false does not change value, true + false does not either
+    if( delta && !mValue[bufferIndex] )
+    {
+      mValue[bufferIndex] += delta;
+
+      OnSet();
+    }
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  bool& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const bool& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  bool& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const bool& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, bool value)
+  {
+    // bake has to check the base value as current buffer value can be correct by constraint or something else
+    if( mBaseValue != value )
+    {
+      mBaseValue = value;
+      mValue[bufferIndex] = value;
+
+      OnBake();
+    }
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, bool delta)
+  {
+    mValue[bufferIndex] += delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<bool> mValue; ///< The double-buffered property value
+  bool mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+
+/**
+ * An integer animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<int> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( int initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<int>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetInteger()
+   */
+  virtual const int& GetInteger( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, int value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, int delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  int& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const int& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  int& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const int& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, int value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, int delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Sets both double-buffered values & the base value.
+   * This should only be used when the owning object has not been connected to the scene-graph.
+   * @param[in] value The new property value.
+   */
+  void SetInitial(const int& value)
+  {
+    mValue[0]  = value;
+    mValue[1]  = mValue[0];
+    mBaseValue = mValue[0];
+  }
+
+  /**
+   * Change both double-buffered values & the base value by a relative amount.
+   * This should only be used when the owning object has not been connected to the scene-graph.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetInitialRelative(const int& delta)
+  {
+    mValue[0] = mValue[0] + delta;
+    mValue[1] = mValue[0];
+    mBaseValue = mValue[0];
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<int> mValue; ///< The double-buffered property value
+  int mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+/**
+ * An float animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<float> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( float initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<float>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetFloat()
+   */
+  virtual const float& GetFloat( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  float& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const float& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  float& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const float& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Sets both double-buffered values & the base value.
+   * This should only be used when the owning object has not been connected to the scene-graph.
+   * @param[in] value The new property value.
+   */
+  void SetInitial(const float& value)
+  {
+    mValue[0]  = value;
+    mValue[1]  = mValue[0];
+    mBaseValue = mValue[0];
+  }
+
+  /**
+   * Change both double-buffered values & the base value by a relative amount.
+   * This should only be used when the owning object has not been connected to the scene-graph.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetInitialRelative(const float& delta)
+  {
+    mValue[0] = mValue[0] + delta;
+    mValue[1] = mValue[0];
+    mBaseValue = mValue[0];
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<float> mValue; ///< The double-buffered property value
+  float mBaseValue;             ///< Reset to this base value at the beginning of each frame
+};
+
+/**
+ * An Vector2 animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Vector2> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Vector2& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector2>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector2()
+   */
+  virtual const Vector2& GetVector2( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Vector2& value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new X value.
+   */
+  void SetX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new Y value.
+   */
+  void SetY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Vector2& delta)
+  {
+    mValue[bufferIndex] += delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void SetXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x += delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void SetYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y += delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Vector2& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Vector2& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector2& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector2& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Vector2& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = value;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the X value & base X value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+    mBaseValue.x = value;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the Y value & base Y value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+    mBaseValue.y = value;
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Vector2& delta)
+  {
+    mValue[bufferIndex] += delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the X value & base X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void BakeXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x += delta;
+    mBaseValue.x = mValue[bufferIndex].x;
+
+    OnBake();
+  }
+
+  /**
+   * Change the Y value & base Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void BakeYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y += delta;
+    mBaseValue.y = mValue[bufferIndex].y;
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Vector2> mValue; ///< The double-buffered property value
+  Vector2 mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+/**
+ * A Vector3 animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Vector3> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   */
+  AnimatableProperty()
+  : mValue(),
+    mBaseValue()
+  {
+  }
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Vector3& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new X value.
+   */
+  void SetX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new Y value.
+   */
+  void SetY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new Z value.
+   */
+  void SetZ(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].z = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Vector3& delta)
+  {
+    mValue[bufferIndex] += delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void SetXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x += delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void SetYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y += delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the Z value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The Z value will change by this amount.
+   */
+  void SetZRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].z += delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Vector3& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Vector3& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector3& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector3& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = value;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the X value & base X value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+    mBaseValue.x = value;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the Y value & base Y value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+    mBaseValue.y = value;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the Z value & base Z value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeZ(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].z = value;
+    mBaseValue.z = value;
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Vector3& delta)
+  {
+    mValue[bufferIndex] += delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelativeMultiply(BufferIndex bufferIndex, const Vector3& delta)
+  {
+    mValue[bufferIndex] *= delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the X value & base X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void BakeXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x += delta;
+    mBaseValue.x = mValue[bufferIndex].x;
+
+    OnBake();
+  }
+
+  /**
+   * Change the Y value & base Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void BakeYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y += delta;
+    mBaseValue.y = mValue[bufferIndex].y;
+
+    OnBake();
+  }
+
+  /**
+   * Change the Z value & base Z value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The Z value will change by this amount.
+   */
+  void BakeZRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].z += delta;
+    mBaseValue.z = mValue[bufferIndex].z;
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Vector3> mValue; ///< The double-buffered property value
+  Vector3 mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+/**
+ * A Vector4 animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Vector4> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Vector4& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector4>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector4()
+   */
+  virtual const Vector4& GetVector4( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Vector4& value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the X value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new X value.
+   */
+  void SetX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the Y value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new Y value.
+   */
+  void SetY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the Z value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new Z value.
+   */
+  void SetZ(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].z = value;
+
+    OnSet();
+  }
+
+  /**
+   * Set the W value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new W value.
+   */
+  void SetW(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].w = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Vector4& delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void SetXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x = mValue[bufferIndex].x + delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void SetYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y = mValue[bufferIndex].y + delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the Z value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The Z value will change by this amount.
+   */
+  void SetZRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].z = mValue[bufferIndex].z + delta;
+
+    OnSet();
+  }
+
+  /**
+   * Change the W value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The W value will change by this amount.
+   */
+  void SetWRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].w = mValue[bufferIndex].w + delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Vector4& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Vector4& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Vector4& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector4& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Vector4& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Set both the X value & base X value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeX(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].x = value;
+    mBaseValue.x = mValue[bufferIndex].x;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the Y value & base Y value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeY(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].y = value;
+    mBaseValue.y = mValue[bufferIndex].y;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the Z value & base Z value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeZ(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].z = value;
+    mBaseValue.z = mValue[bufferIndex].z;
+
+    OnBake();
+  }
+
+  /**
+   * Set both the W value & base W value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void BakeW(BufferIndex bufferIndex, float value)
+  {
+    mValue[bufferIndex].w = value;
+    mBaseValue.w = mValue[bufferIndex].w;
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Vector4& delta)
+  {
+    mValue[bufferIndex] = mValue[bufferIndex] + delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the X value & base X value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The X value will change by this amount.
+   */
+  void BakeXRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].x = mValue[bufferIndex].x + delta;
+    mBaseValue.x = mValue[bufferIndex].x;
+
+    OnBake();
+  }
+
+  /**
+   * Change the Y value & base Y value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The Y value will change by this amount.
+   */
+  void BakeYRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].y = mValue[bufferIndex].y + delta;
+    mBaseValue.y = mValue[bufferIndex].y;
+
+    OnBake();
+  }
+
+  /**
+   * Change the Z value & base Z value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The Z value will change by this amount.
+   */
+  void BakeZRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].z = mValue[bufferIndex].z + delta;
+    mBaseValue.z = mValue[bufferIndex].z;
+
+    OnBake();
+  }
+
+  /**
+   * Change the W value & base W value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The W value will change by this amount.
+   */
+  void BakeWRelative(BufferIndex bufferIndex, float delta)
+  {
+    mValue[bufferIndex].w = mValue[bufferIndex].w + delta;
+    mBaseValue.w = mValue[bufferIndex].w;
+
+    OnBake();
+  }
+
+  /**
+   * Sets both double-buffered W values & the base W value.
+   * This should only be used when the owning object has not been connected to the scene-graph.
+   * @param[in] value The new W value.
+   */
+  void SetWInitial(float value)
+  {
+    mValue[0].w  = value;
+    mValue[1].w  = mValue[0].w;
+    mBaseValue.w = mValue[0].w;
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Vector4> mValue; ///< The double-buffered property value
+  Vector4 mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+/**
+ * An Quaternion animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Quaternion> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   */
+  AnimatableProperty()
+  : mValue(),
+    mBaseValue()
+  {
+  }
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Quaternion& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Quaternion>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    mValue[bufferIndex] = value;
+
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Quaternion& delta)
+  {
+    mValue[bufferIndex] *= delta;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Quaternion& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Quaternion& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Quaternion& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Quaternion& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = value;
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Quaternion& delta)
+  {
+    mValue[bufferIndex] *= delta;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Quaternion> mValue; ///< The double-buffered property value
+  Quaternion mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+/**
+ * A Matrix animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Matrix> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Matrix& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetMatrix()
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Matrix& value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Matrix& delta)
+  {
+    Matrix temp;
+    Matrix::Multiply(temp, mValue[bufferIndex], delta);
+    mValue[bufferIndex] = temp;
+
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Matrix& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Matrix& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Matrix& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Matrix& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Matrix& delta)
+  {
+    Matrix temp;
+    Matrix::Multiply(temp, mValue[bufferIndex], delta);
+    mValue[bufferIndex] = temp;
+    mBaseValue = temp;
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Matrix> mValue; ///< The double-buffered property value
+  Matrix mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+/**
+ * A Matrix3 animatable property of a scene-graph object.
+ */
+template <>
+class AnimatableProperty<Matrix3> : public AnimatablePropertyBase
+{
+public:
+
+  /**
+   * Create an animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  AnimatableProperty( const Matrix3& initialValue )
+  : mValue( initialValue ),
+    mBaseValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~AnimatableProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::ResetToBaseValue()
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex)
+  {
+    if (CLEAN_FLAG != mDirtyFlags)
+    {
+      mValue[updateBufferIndex] = mBaseValue;
+
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetMatrix3()
+   */
+  virtual const Matrix3& GetMatrix3( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Matrix3& value)
+  {
+    mValue[bufferIndex] = value;
+    OnSet();
+  }
+
+  /**
+   * Change the property value by a relative amount.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] delta The property will change by this amount.
+   */
+  void SetRelative(BufferIndex bufferIndex, const Matrix3& delta)
+  {
+    Matrix3 temp;
+    Matrix3::Multiply(temp, mValue[bufferIndex], delta);
+    mValue[bufferIndex] = temp;
+    OnSet();
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  Matrix3& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::AnimatableProperty::Get()
+   */
+  const Matrix3& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  Matrix3& operator[](size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix3& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Set both the property value & base value.
+   * @param[in] bufferIndex The buffer to write for the property value.
+   * @param[in] value The new property value.
+   */
+  void Bake(BufferIndex bufferIndex, const Matrix3& value)
+  {
+    mValue[bufferIndex] = value;
+    mBaseValue = mValue[bufferIndex];
+
+    OnBake();
+  }
+
+  /**
+   * Change the property value & base value by a relative amount.
+   * @param[in] bufferIndex The buffer to write for the local property value.
+   * @param[in] delta The property will change by this amount.
+   */
+  void BakeRelative(BufferIndex bufferIndex, const Matrix3& delta)
+  {
+    Matrix3 temp;
+    Matrix3::Multiply(temp, mValue[bufferIndex], delta);
+    mValue[bufferIndex] = temp;
+    mBaseValue = temp;
+
+    OnBake();
+  }
+
+private:
+
+  // Undefined
+  AnimatableProperty(const AnimatableProperty& property);
+
+  // Undefined
+  AnimatableProperty& operator=(const AnimatableProperty& rhs);
+
+private:
+
+  DoubleBuffered<Matrix3> mValue; ///< The double-buffered property value
+  Matrix3 mBaseValue;             ///< Reset to this base value at the beginning of each frame
+
+};
+
+} // namespace SceneGraph
+
+// Messages for AnimatableProperty<T>
+
+template <class T>
+void BakeMessage( EventThreadServices& eventThreadServices,
+                  const SceneGraph::AnimatableProperty<T>& property,
+                  typename ParameterType< T >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, T > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::Bake,
+                        newValue );
+}
+
+template <class T>
+void BakeRelativeMessage( EventThreadServices& eventThreadServices,
+                          const SceneGraph::AnimatableProperty<T>& property,
+                          const T& delta )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, const T& > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::BakeRelative,
+                         delta );
+}
+
+template <class T>
+void SetXComponentMessage( EventThreadServices& eventThreadServices,
+                           const SceneGraph::AnimatableProperty<T>& property,
+                           typename ParameterType< float >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::BakeX,
+                        newValue );
+}
+
+template <class T>
+void SetYComponentMessage( EventThreadServices& eventThreadServices,
+                           const SceneGraph::AnimatableProperty<T>& property,
+                           typename ParameterType< float >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::BakeY,
+                        newValue );
+}
+
+template <class T>
+void SetZComponentMessage( EventThreadServices& eventThreadServices,
+                           const SceneGraph::AnimatableProperty<T>& property,
+                           typename ParameterType< float >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::BakeZ,
+                        newValue );
+}
+
+template <class T>
+void SetWComponentMessage( EventThreadServices& eventThreadServices,
+                           const SceneGraph::AnimatableProperty<T>& property,
+                           typename ParameterType< float >::PassingType newValue )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::AnimatableProperty<T>, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &property,
+                        &SceneGraph::AnimatableProperty<T>::BakeW,
+                        newValue );
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_ANIMATABLE_PROPERTY_H__
diff --git a/dali/internal/update/common/discard-queue.cpp b/dali/internal/update/common/discard-queue.cpp
new file mode 100644 (file)
index 0000000..f08e8af
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/common/discard-queue.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/gl-resources/gl-resource-owner.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+DiscardQueue::DiscardQueue( RenderQueue& renderQueue )
+: mRenderQueue( renderQueue )
+{
+}
+
+DiscardQueue::~DiscardQueue()
+{
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, Node* node )
+{
+  DALI_ASSERT_DEBUG( NULL != node );
+
+  // The GL resources will now be freed in frame N
+  // The Update for frame N+1 may occur in parallel with the rendering of frame N
+  // Queue the node for destruction in frame N+2
+  if ( 0u == updateBufferIndex )
+  {
+    mNodeQueue0.PushBack( node );
+  }
+  else
+  {
+    mNodeQueue1.PushBack( node );
+  }
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, NodeAttachment* attachment )
+{
+  DALI_ASSERT_DEBUG( NULL != attachment );
+
+  // The GL resources will now be freed in Render frame N
+  // The Update for frame N+1 may occur in parallel with the rendering of frame N
+  // Queue the attachment for destruction in Update frame N+2
+  if ( 0u == updateBufferIndex )
+  {
+    mAttachmentQueue0.PushBack( attachment );
+  }
+  else
+  {
+    mAttachmentQueue1.PushBack( attachment );
+  }
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, Geometry* geometry )
+{
+  DALI_ASSERT_DEBUG( NULL != geometry );
+
+  // The GL resources will now be freed in frame N
+  // The Update for frame N+1 may occur in parallel with the rendering of frame N
+  // Queue the node for destruction in frame N+2
+  if ( 0u == updateBufferIndex )
+  {
+    mGeometryQueue0.PushBack( geometry );
+  }
+  else
+  {
+    mGeometryQueue1.PushBack( geometry );
+  }
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, Material* material )
+{
+  DALI_ASSERT_DEBUG( NULL != material );
+
+  // The GL resources will now be freed in frame N
+  // The Update for frame N+1 may occur in parallel with the rendering of frame N
+  // Queue the node for destruction in frame N+2
+  if ( 0u == updateBufferIndex )
+  {
+    mMaterialQueue0.PushBack( material );
+  }
+  else
+  {
+    mMaterialQueue1.PushBack( material );
+  }
+}
+
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, Shader* shader )
+{
+  DALI_ASSERT_DEBUG( NULL != shader );
+
+  // Programs are cached for the lifetime of DALi so no need for GL cleanup for shader for now.
+
+  // The GL resources will now be freed in frame N
+  // The Update for frame N+1 may occur in parallel with the rendering of frame N
+  // Queue the node for destruction in frame N+2
+  if ( 0u == updateBufferIndex )
+  {
+    mShaderQueue0.PushBack( shader );
+  }
+  else
+  {
+    mShaderQueue1.PushBack( shader );
+  }
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, Sampler* sampler )
+{
+  DALI_ASSERT_DEBUG( NULL != sampler );
+
+  if ( 0u == updateBufferIndex )
+  {
+    mSamplerQueue0.PushBack( sampler );
+  }
+  else
+  {
+    mSamplerQueue1.PushBack( sampler );
+  }
+}
+
+void DiscardQueue::Add( BufferIndex updateBufferIndex, PropertyBuffer* propertyBuffer )
+{
+  DALI_ASSERT_DEBUG( NULL != propertyBuffer );
+
+  if ( 0u == updateBufferIndex )
+  {
+    mPropertyBufferQueue0.PushBack( propertyBuffer );
+  }
+  else
+  {
+    mPropertyBufferQueue1.PushBack( propertyBuffer );
+  }
+}
+
+void DiscardQueue::Clear( BufferIndex updateBufferIndex )
+{
+  // Destroy some discarded objects; these should no longer own any GL resources
+
+  if ( 0u == updateBufferIndex )
+  {
+    mNodeQueue0.Clear();
+    mAttachmentQueue0.Clear();
+    mShaderQueue0.Clear();
+    mGeometryQueue0.Clear();
+    mMaterialQueue0.Clear();
+    mSamplerQueue0.Clear();
+    mPropertyBufferQueue0.Clear();
+  }
+  else
+  {
+    mNodeQueue1.Clear();
+    mAttachmentQueue1.Clear();
+    mShaderQueue1.Clear();
+    mGeometryQueue1.Clear();
+    mMaterialQueue1.Clear();
+    mSamplerQueue1.Clear();
+    mPropertyBufferQueue1.Clear();
+  }
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/discard-queue.h b/dali/internal/update/common/discard-queue.h
new file mode 100644 (file)
index 0000000..d47f20c
--- /dev/null
@@ -0,0 +1,171 @@
+#ifndef __DALI_INTERNAL_DISCARD_QUEUE_H__
+#define __DALI_INTERNAL_DISCARD_QUEUE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+#include <dali/internal/update/node-attachments/node-attachment-declarations.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Texture;
+
+namespace SceneGraph
+{
+
+class Node;
+class RenderQueue;
+class Shader;
+
+
+/**
+ * DiscardQueue is used to cleanup nodes & resources when no longer in use.
+ * Unwanted objects are added here during UpdateManager::Update().
+ * When added, messages will be sent to clean-up GL resources in the next Render.
+ * The Update for frame N+1 may occur in parallel with the rendering of frame N.
+ * Therefore objects queued for destruction in frame N, are destroyed frame N+2.
+ */
+class DiscardQueue
+{
+public:
+
+  typedef OwnerContainer< Shader* > ShaderQueue;
+  typedef OwnerContainer< Geometry* > GeometryQueue;
+  typedef OwnerContainer< Material* > MaterialQueue;
+  typedef OwnerContainer< Sampler* > SamplerQueue;
+  typedef OwnerContainer< PropertyBuffer* > PropertyBufferQueue;
+
+  /**
+   * Create a new DiscardQueue.
+   * @param[in] renderQueue Used to send GL clean-up messages for the next Render.
+   */
+  DiscardQueue( RenderQueue& renderQueue );
+
+  /**
+   * Non-virtual destructor; DiscardQueue is not suitable as a base class.
+   */
+  ~DiscardQueue();
+
+  /**
+   * Adds an unwanted Node and its children to the discard queue.
+   * If necessary, a message will be sent to clean-up GL resources in the next Render.
+   * @pre This method is not thread-safe, and should only be called from the update-thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] node The discarded node; DiscardQueue takes ownership.
+   */
+  void Add( BufferIndex updateBufferIndex, Node* node );
+
+  /**
+   * Adds an unwanted NodeAttachment to the discard queue.
+   * If necessary, a message will be sent to clean-up GL resources in the next Render.
+   * @pre This method is not thread-safe, and should only be called from the update-thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] attachment The discarded attachment; DiscardQueue takes ownership.
+   */
+  void Add( BufferIndex updateBufferIndex, NodeAttachment* attachment );
+
+  /**
+   * Adds an unwanted geometry to the discard queue.
+   * A message will be sent to clean up GL resources in the next Render
+   */
+  void Add( BufferIndex updateBufferIndex, Geometry* geometry );
+
+  /**
+   * Adds an unwanted material to the discard queue.
+   * A message will be sent to clean up GL resources in the next Render.
+   */
+  void Add( BufferIndex updateBufferIndex, PropertyBuffer* material );
+
+  /**
+   * Adds an unwanted material to the discard queue.
+   * A message will be sent to clean up GL resources in the next Render.
+   */
+  void Add( BufferIndex updateBufferIndex, Material* material );
+
+  /**
+   * Adds an unwanted material to the discard queue.
+   * A message will be sent to clean up GL resources in the next Render.
+   */
+  void Add( BufferIndex updateBufferIndex, Sampler* material );
+
+  /**
+   * Adds an unwanted shader to the discard queue.
+   * A message will be sent to clean-up GL resources in the next Render.
+   * @pre This method is not thread-safe, and should only be called from the update-thread.
+   * @param[in] bufferIndex The current update buffer index.
+   * @param[in] shader The shader to queue; DiscardQueue takes ownership.
+   */
+  void Add( BufferIndex bufferIndex, Shader* shader );
+
+  /**
+   * Release the nodes which were queued in the frame N-2.
+   * @pre This method should be called (once) at the beginning of every Update.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void Clear( BufferIndex updateBufferIndex );
+
+private:
+
+  // Undefined
+  DiscardQueue( const DiscardQueue& );
+
+  // Undefined
+  DiscardQueue& operator=( const DiscardQueue& rhs );
+
+private:
+
+  RenderQueue& mRenderQueue; ///< Used to send GL clean-up messages for the next Render.
+
+  // Messages are queued here when the update buffer index == 0
+  NodeOwnerContainer           mNodeQueue0;
+  NodeAttachmentOwnerContainer mAttachmentQueue0;
+  ShaderQueue                  mShaderQueue0;
+  GeometryQueue                mGeometryQueue0;
+  MaterialQueue                mMaterialQueue0;
+  SamplerQueue                 mSamplerQueue0;
+  PropertyBufferQueue          mPropertyBufferQueue0;
+
+  // Messages are queued here when the update buffer index == 1
+  NodeOwnerContainer           mNodeQueue1;
+  NodeAttachmentOwnerContainer mAttachmentQueue1;
+  ShaderQueue                  mShaderQueue1;
+  GeometryQueue                mGeometryQueue1;
+  MaterialQueue                mMaterialQueue1;
+  SamplerQueue                 mSamplerQueue1;
+  PropertyBufferQueue          mPropertyBufferQueue1;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_DISCARD_QUEUE_H__
diff --git a/dali/internal/update/common/double-buffered-property.h b/dali/internal/update/common/double-buffered-property.h
new file mode 100644 (file)
index 0000000..0b23260
--- /dev/null
@@ -0,0 +1,376 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/type-abstraction.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace DoubleBufferedPropertyFlags
+{
+/**
+ * Dirty flags record whether a doubleBuffered property has changed.
+ * In the frame following a change, the property is copied from the most recent
+ * buffer to the old buffer.
+ */
+static const unsigned int CLEAN_FLAG  = 0x00; ///< Indicates that the value did not change in this, or the previous frame
+static const unsigned int COPIED_FLAG = 0x01; ///< Indicates that the value was copied during the previous frame
+static const unsigned int SET_FLAG    = 0x02; ///< Indicates that the value was Set during the previous frame
+}
+
+/**
+ * Base class to reduce code size from the templates.
+ */
+class DoubleBufferedPropertyBase : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Constructor, initialize the dirty flag
+   */
+  DoubleBufferedPropertyBase()
+  : PropertyInputImpl(),
+    mDirtyFlags( DoubleBufferedPropertyFlags::COPIED_FLAG )
+  {}
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedPropertyBase()
+  {}
+
+  /**
+   * Auto-age the property: if it was set the previous frame,
+   * then copy the value into the current frame's buffer.
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex ) = 0;
+
+
+protected: // for derived classes
+  /**
+   * Flag that the property has been Set during the current frame.
+   */
+  void OnSet()
+  {
+    mDirtyFlags = DoubleBufferedPropertyFlags::SET_FLAG;
+  }
+
+public: // From PropertyBase
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   */
+  virtual bool InputChanged() const
+  {
+    return ( DoubleBufferedPropertyFlags::CLEAN_FLAG != mDirtyFlags );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true; // DoubleBuffered properties are always valid
+  }
+
+protected: // so that ResetToBaseValue can set it directly
+
+  unsigned int mDirtyFlags; ///< Flag whether value changed during previous 2 frames
+
+};
+
+/**
+ * A doubleBuffered property of a scene-graph object.
+ */
+template <class T>
+class DoubleBufferedPropertyImpl : public DoubleBufferedPropertyBase
+{
+public:
+  /**
+   * Create an doubleBuffered property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  DoubleBufferedPropertyImpl( typename ParameterType<T>::PassingType initialValue )
+  : mValue( initialValue )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~DoubleBufferedPropertyImpl()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<T>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::DoubleBufferedPropertyBase::CopyPrevious()
+   */
+  virtual void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if( DoubleBufferedPropertyFlags::SET_FLAG == mDirtyFlags)
+    {
+      mValue[ updateBufferIndex ] = mValue[ 1-updateBufferIndex ];
+      mDirtyFlags = ( mDirtyFlags >> 1 );
+    }
+  }
+
+  /**
+   * Set the property value. This will persist for the current frame, and will
+   * be copied to the other buffer next frame (unless it is set again)
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, typename ParameterType<T>::PassingType value )
+  {
+    // check if the value actually changed to avoid dirtying nodes unnecessarily
+    if( mValue[bufferIndex] != value )
+    {
+      mValue[bufferIndex] = value;
+
+      OnSet();
+    }
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::DoubleBufferedProperty::Get()
+   */
+  const T& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const T& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+protected:
+  DoubleBuffered<T> mValue; ///< The double-buffered property value
+
+private:  // Undefined
+  DoubleBufferedPropertyImpl(const DoubleBufferedPropertyImpl& property);
+  DoubleBufferedPropertyImpl& operator=(const DoubleBufferedPropertyImpl& rhs);
+
+};
+
+template<typename T>
+class DoubleBufferedProperty;
+
+template<>
+class DoubleBufferedProperty<bool> : public DoubleBufferedPropertyImpl<bool>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( bool value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetBoolean
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<int> : public DoubleBufferedPropertyImpl<int>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( int value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetInteger
+   */
+  virtual const int& GetInteger( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<float> : public DoubleBufferedPropertyImpl<float>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( float value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetFloat
+   */
+  virtual const float& GetFloat( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Vector2> : public DoubleBufferedPropertyImpl<Vector2>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Vector2& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetVector2
+   */
+  virtual const Vector2& GetVector2( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Vector3> : public DoubleBufferedPropertyImpl<Vector3>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Vector3& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetVector3
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Vector4> : public DoubleBufferedPropertyImpl<Vector4>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Vector4& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetVector4
+   */
+  virtual const Vector4& GetVector4( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Quaternion> : public DoubleBufferedPropertyImpl<Quaternion>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Quaternion& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetQuaternion
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Matrix3> : public DoubleBufferedPropertyImpl<Matrix3>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Matrix3& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetMatrix3
+   */
+  virtual const Matrix3& GetMatrix3( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+template<>
+class DoubleBufferedProperty<Matrix> : public DoubleBufferedPropertyImpl<Matrix>
+{
+public:
+  /**
+   * Constructor
+   */
+  DoubleBufferedProperty( const Matrix& value ) : DoubleBufferedPropertyImpl( value ) {};
+
+  /**
+   * copydoc PropertyInputImpl::GetMatrix
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    return mValue[bufferIndex];
+  }
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_PROPERTY_H__
diff --git a/dali/internal/update/common/double-buffered.h b/dali/internal/update/common/double-buffered.h
new file mode 100644 (file)
index 0000000..412e49c
--- /dev/null
@@ -0,0 +1,229 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// The number of buffers per scene-graph property
+static const unsigned int NUM_SCENE_GRAPH_BUFFERS = 2;
+
+// Buffer index used when reading off-stage values
+static const unsigned int ARBITRARY_OFF_STAGE_BUFFER = 0;
+
+namespace SceneGraph
+{
+
+/**
+ * Templated class for a double-buffered value.
+ */
+template <typename T>
+class DoubleBuffered
+{
+public:
+
+  DoubleBuffered()
+  : mValue1(),
+    mValue2()
+  {
+  }
+
+  DoubleBuffered(const T& val)
+  : mValue1(val),
+    mValue2(val)
+  {
+  }
+
+  inline T& operator[](const size_t i)
+  {
+    DALI_ASSERT_DEBUG(i < NUM_SCENE_GRAPH_BUFFERS);
+
+    return *(&mValue1+i);
+  }
+
+  inline const T& operator[](const size_t i) const
+  {
+    DALI_ASSERT_DEBUG(i < NUM_SCENE_GRAPH_BUFFERS);
+
+    return *(&mValue1+i);
+  }
+
+private:
+
+  // Undefined
+  DoubleBuffered<T>(const DoubleBuffered<T>&);
+
+  // Undefined
+  DoubleBuffered<T>& operator=(const DoubleBuffered<T>& rhs);
+
+private:
+
+  T mValue1;
+  T mValue2;
+};
+
+/**
+ * @brief Specialization for owner-pointer
+ *
+ * This class takes ownership of the pointers and releases the memory when the pointer
+ * is no longer used by either buffer
+ */
+template <typename T>
+class DoubleBuffered< OwnerPointer< T > >
+{
+public:
+
+  /**
+   * Class that deals with setting a value
+   */
+  class Setter
+  {
+  public:
+    /**
+     * @brief Assignment operator to that a value that will later
+     * be set in the correct buffer index of the object referenced by the setter.
+     */
+    Setter& operator=( T* value )
+    {
+      mValue = value;
+      return *this;
+    }
+
+    ~Setter()
+    {
+      mObject.Set( mIndex, mValue );
+    }
+
+  private:
+    Setter( DoubleBuffered& object,
+            size_t i,
+            T* value )
+    : mObject( object ),
+      mIndex( i ),
+      mValue( value )
+    {
+    }
+
+    Setter( const Setter& rhs )
+    : mObject( rhs.mObject ),
+      mIndex( rhs.mIndex ),
+      mValue( rhs.mValue )
+    {
+    }
+
+    DoubleBuffered& mObject; ///< Double-buffered object that will be changed
+    const size_t mIndex;                          ///< Buffer index that will be changed
+    T* mValue;                                    ///< Value of the pointer
+
+    friend class DoubleBuffered;
+  };
+
+  DoubleBuffered()
+  : mValue1( NULL ),
+    mValue2( NULL )
+  {
+  }
+
+  DoubleBuffered(T* val)
+  : mValue1( val ),
+    mValue2( val )
+  {
+  }
+
+  ~DoubleBuffered()
+  {
+    if( mValue2 != mValue1 )
+    {
+      delete mValue2;
+    }
+    delete mValue1;
+  }
+
+  void Set( size_t i, T* value )
+  {
+    T*& current = *(&mValue1 + i);
+    T*& previous = *(&mValue1 + 1u-i);
+
+    if( current != value && current != previous )
+    {
+      delete current;
+    }
+    current = value;
+  }
+
+  Setter operator[](size_t i)
+  {
+    return Setter( *this, i, *(&mValue1+i) );
+  }
+
+  const T* operator[](size_t i) const
+  {
+    DALI_ASSERT_DEBUG(i < NUM_SCENE_GRAPH_BUFFERS);
+
+    return *(&mValue1+i);
+  }
+
+  /**
+   * Auto-age the property: if it was set the previous frame,
+   * then copy the value into the current frame's buffer.
+   */
+  void CopyPrevious( size_t i )
+  {
+    DALI_ASSERT_DEBUG(i < NUM_SCENE_GRAPH_BUFFERS);
+
+    T*& current = *(&mValue1 + i);
+    T*& previous = *(&mValue1 + 1u-i);
+
+    if( current != previous )
+    {
+      delete current;
+    }
+
+    current = previous;
+  }
+
+private:
+
+  // Undefined
+  DoubleBuffered(const DoubleBuffered&);
+
+  // Undefined
+  DoubleBuffered& operator=(const DoubleBuffered& rhs);
+
+private:
+
+  T* mValue1;
+  T* mValue2;
+
+};
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_DOUBLE_BUFFERED_H__
diff --git a/dali/internal/update/common/inherited-property.h b/dali/internal/update/common/inherited-property.h
new file mode 100644 (file)
index 0000000..ca50648
--- /dev/null
@@ -0,0 +1,703 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_INHERITED_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_INHERITED_PROPERTY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * An inherited Vector3 property.
+ */
+class InheritedVector3 : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an inherited Vector3.
+   */
+  InheritedVector3()
+  : mValue(),
+    mInheritedFlag( false ),
+    mReinheritedFlag( true )
+  {
+  }
+
+  /**
+   * Create an inherited Vector3.
+   * @param [in] initialValue The initial value of the property.
+   */
+  InheritedVector3( const Vector3& initialValue )
+  : mValue( initialValue ),
+    mInheritedFlag( false ),
+    mReinheritedFlag( true )
+  {
+  }
+  /**
+   * Virtual destructor.
+   */
+  virtual ~InheritedVector3()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  /**
+   * Called once per Update (only) if the property did not need to be re-inherited.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if ( mReinheritedFlag )
+    {
+      mValue[updateBufferIndex] = mValue[updateBufferIndex ? 0 : 1];
+
+      mReinheritedFlag = false;
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return ( false == mReinheritedFlag );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    // A constraint cannot use the property until it has been inherited (at least once).
+    return mInheritedFlag;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return !IsClean();
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputVector3()
+   */
+  virtual const Vector3& GetConstraintInputVector3( BufferIndex bufferIndex ) const
+  {
+    // For inherited properties, constraints work with the value from the previous frame.
+    // This is because constraints are applied to position etc, before world-position is calculated.
+    BufferIndex eventBufferIndex = bufferIndex ? 0u : 1u;
+
+    return mValue[ eventBufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Vector3& value)
+  {
+    mValue[bufferIndex] = value;
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+
+    mReinheritedFlag = true;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Vector3& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Vector3& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector3& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+
+  // Undefined
+  InheritedVector3(const InheritedVector3& property);
+
+  // Undefined
+  InheritedVector3& operator=(const InheritedVector3& rhs);
+
+private:
+
+  DoubleBuffered<Vector3> mValue; ///< The double-buffered property value
+
+  bool mInheritedFlag   :1; ///< Flag whether the value has ever been inherited
+  bool mReinheritedFlag :1; ///< Flag whether value was re-inherited in previous frame
+};
+
+/**
+ * An inherited Color property.
+ */
+class InheritedColor : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an inherited property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  InheritedColor( const Vector4& initialValue )
+  : mValue( initialValue ),
+    mInheritedFlag( false ),
+    mReinheritedFlag( true )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~InheritedColor()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector4>();
+  }
+
+  /**
+   * Called once per Update (only) if the property did not need to be re-inherited.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if ( mReinheritedFlag )
+    {
+      mValue[updateBufferIndex] = mValue[updateBufferIndex ? 0 : 1];
+
+      mReinheritedFlag = false;
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return ( false == mReinheritedFlag );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    // A constraint cannot use the property until it has been inherited (at least once).
+    return mInheritedFlag;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return !IsClean();
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector4()
+   */
+  virtual const Vector4& GetVector4( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputVector4()
+   */
+  virtual const Vector4& GetConstraintInputVector4( BufferIndex bufferIndex ) const
+  {
+    // For inherited properties, constraints work with the value from the previous frame.
+    // This is because constraints are applied to position etc, before world-position is calculated.
+    BufferIndex eventBufferIndex = bufferIndex ? 0u : 1u;
+
+    return mValue[ eventBufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Vector4& value)
+  {
+    mValue[bufferIndex] = Clamp( value, 0.0f, 1.0f ); // color values are clamped between 0 and 1
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+    mReinheritedFlag = true;
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] r The new red value.
+   * @param[in] g The new green value.
+   * @param[in] b The new blue value.
+   * @param[in] a The new alpha value.
+   */
+  void Set(BufferIndex bufferIndex, float r, float g, float b, float a )
+  {
+    mValue[bufferIndex].r = Clamp( r, 0.0f, 1.0f ); // color values are clamped between 0 and 1
+    mValue[bufferIndex].g = Clamp( g, 0.0f, 1.0f ); // color values are clamped between 0 and 1
+    mValue[bufferIndex].b = Clamp( b, 0.0f, 1.0f ); // color values are clamped between 0 and 1
+    mValue[bufferIndex].a = Clamp( a, 0.0f, 1.0f ); // color values are clamped between 0 and 1
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+    mReinheritedFlag = true;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Vector4& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Vector4& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Vector4& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+
+  // Undefined
+  InheritedColor(const InheritedColor& property);
+  // Undefined
+  InheritedColor& operator=(const InheritedColor& rhs);
+
+private:
+
+  DoubleBuffered<Vector4> mValue; ///< The double-buffered property value
+
+  bool mInheritedFlag   :1; ///< Flag whether the value has ever been inherited
+  bool mReinheritedFlag :1; ///< Flag whether value was re-inherited in previous frame
+};
+
+/**
+ * An inherited Quaternion property.
+ */
+class InheritedQuaternion : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an inherited property.
+   */
+  InheritedQuaternion()
+  : mValue(),
+    mInheritedFlag( false ),
+    mReinheritedFlag( true )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~InheritedQuaternion()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Quaternion>();
+  }
+
+  /**
+   * Called once per Update (only) if the property did not need to be re-inherited.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if ( mReinheritedFlag )
+    {
+      mValue[updateBufferIndex] = mValue[updateBufferIndex ? 0 : 1];
+
+      mReinheritedFlag = false;
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return ( false == mReinheritedFlag );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    // A constraint cannot use the property until it has been inherited (at least once).
+    return mInheritedFlag;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return !IsClean();
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetConstraintInputQuaternion()
+   */
+  virtual const Quaternion& GetConstraintInputQuaternion( BufferIndex bufferIndex ) const
+  {
+    // For inherited properties, constraints work with the value from the previous frame.
+    // This is because constraints are applied to position etc, before world-position is calculated.
+    BufferIndex eventBufferIndex = bufferIndex ? 0u : 1u;
+
+    return mValue[ eventBufferIndex ];
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Quaternion& value)
+  {
+    mValue[bufferIndex] = value;
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+
+    mReinheritedFlag = true;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Quaternion& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Quaternion& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Quaternion& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+private:
+
+  // Undefined
+  InheritedQuaternion(const InheritedQuaternion& property);
+
+  // Undefined
+  InheritedQuaternion& operator=(const InheritedQuaternion& rhs);
+
+private:
+
+  DoubleBuffered<Quaternion> mValue; ///< The double-buffered property value
+
+  bool mInheritedFlag   :1;   ///< Flag whether the value has ever been inherited
+  bool mReinheritedFlag :1;   ///< Flag whether value was re-inherited in previous frame
+};
+
+/**
+ * An inherited Matrix property.
+ */
+class InheritedMatrix : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an inherited property.
+   */
+  InheritedMatrix()
+  : mValue(),
+    mInheritedFlag( false ),
+    mReinheritedFlag( true )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~InheritedMatrix()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Matrix>();
+  }
+
+  /**
+   * Called once per Update (only) if the property did not need to be re-inherited.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPrevious( BufferIndex updateBufferIndex )
+  {
+    if ( mReinheritedFlag )
+    {
+      mValue[updateBufferIndex] = mValue[updateBufferIndex ? 0 : 1];
+
+      mReinheritedFlag = false;
+    }
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return ( false == mReinheritedFlag );
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    // A constraint cannot use the property until it has been inherited (at least once).
+    return mInheritedFlag;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return !IsClean();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetMatrix()
+   */
+  virtual const Matrix& GetMatrix( BufferIndex bufferIndex ) const
+  {
+    return mValue[ bufferIndex ];
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetConstraintInputMatrix()
+   */
+  virtual const Matrix& GetConstraintInputMatrix( BufferIndex bufferIndex ) const
+  {
+    // For inherited properties, constraints work with the value from the previous frame.
+    // This is because constraints are applied to position etc, before world-position is calculated.
+    BufferIndex eventBufferIndex = bufferIndex ? 0u : 1u;
+
+    return mValue[ eventBufferIndex ];
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion() const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_QUATERNION_VALUE;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetQuaternion()
+   */
+  virtual const Quaternion& GetQuaternion( BufferIndex bufferIndex ) const
+  {
+    DALI_ASSERT_ALWAYS( false && "Property type mismatch" );
+    return DUMMY_QUATERNION_VALUE;
+  }
+
+  /**
+   * Set the property value. This will only persist for the current frame; the property
+   * will be reset with the base value, at the beginning of the next frame.
+   * @param[in] bufferIndex The buffer to write.
+   * @param[in] value The new property value.
+   */
+  void Set(BufferIndex bufferIndex, const Matrix& value)
+  {
+    mValue[bufferIndex] = value;
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+
+    mReinheritedFlag = true;
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  Matrix& Get(size_t bufferIndex)
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * @copydoc Dali::SceneGraph::PropertyInterface::Get()
+   */
+  const Matrix& Get(size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  /**
+   * Retrieve the property value.
+   * @param[in] bufferIndex The buffer to read.
+   * @return The property value.
+   */
+  const Matrix& operator[](size_t bufferIndex) const
+  {
+    return mValue[bufferIndex];
+  }
+
+  void SetDirty(size_t bufferIndex)
+  {
+    mReinheritedFlag = true;
+
+    // The value has been inherited for the first time
+    mInheritedFlag = true;
+  }
+
+private:
+
+  // Undefined
+  InheritedMatrix(const InheritedMatrix& property);
+
+  // Undefined
+  InheritedMatrix& operator=(const InheritedMatrix& rhs);
+
+private:
+
+  DoubleBuffered<Matrix> mValue; ///< The double-buffered property value
+
+  bool mInheritedFlag   :1;   ///< Flag whether the value has ever been inherited
+  bool mReinheritedFlag :1;   ///< Flag whether value was re-inherited in previous frame
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_INHERITED_PROPERTY_H__
diff --git a/dali/internal/update/common/property-base.cpp b/dali/internal/update/common/property-base.cpp
new file mode 100644 (file)
index 0000000..18504e0
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/common/property-base.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+PropertyBase::PropertyBase()
+{
+}
+
+PropertyBase::~PropertyBase()
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-base.h b/dali/internal/update/common/property-base.h
new file mode 100644 (file)
index 0000000..a66db11
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BASE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BASE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h>
+#include <dali/internal/common/type-abstraction.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Polymorphic base class for scene-graph properties, held by Nodes etc.
+ */
+class PropertyBase : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Default constructor.
+   */
+  PropertyBase();
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyBase();
+
+  /**
+   * Reset the property to a base value; only required if the property is animated.
+   * @param [in] currentBufferIndex The current buffer index.
+   */
+  virtual void ResetToBaseValue(BufferIndex updateBufferIndex) = 0;
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   */
+  virtual bool InputChanged() const
+  {
+    return !IsClean();
+  }
+
+  /**
+   * Query whether the property has changed.
+   * @return True if the property has not changed.
+   */
+  virtual bool IsClean() const = 0;
+
+private:
+
+  // Undefined
+  PropertyBase(const PropertyBase& property);
+
+  // Undefined
+  PropertyBase& operator=(const PropertyBase& rhs);
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BASE_H__
diff --git a/dali/internal/update/common/property-boolean.h b/dali/internal/update/common/property-boolean.h
new file mode 100644 (file)
index 0000000..b166e83
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_BOOLEAN_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_BOOLEAN_PROPERTY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * A Boolean non-animatable property.
+ */
+class PropertyBoolean : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an non-animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  PropertyBoolean( bool initialValue )
+  : mValue( initialValue ),
+    mDirtyFlag( true )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyBoolean()
+  {
+  }
+
+  /**
+   * Clear the dirty flag
+   */
+  void Clear()
+  {
+    mDirtyFlag = false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<bool>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   */
+  virtual bool InputChanged() const
+  {
+    return mDirtyFlag;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetBoolean()
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    return mValue;
+  }
+
+  /**
+   * Flag that the property has been Set during the current frame.
+   */
+  void OnSet()
+  {
+    mDirtyFlag = true;
+  }
+
+private:
+
+  // Undefined
+  PropertyBoolean(const PropertyBoolean& property);
+
+  // Undefined
+  PropertyBoolean& operator=(const PropertyBoolean& rhs);
+
+public:
+  bool mValue; ///< The property value
+
+private:
+  bool mDirtyFlag;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_BOOLEAN_PROPERTY_H__
diff --git a/dali/internal/update/common/property-condition-functions.cpp b/dali/internal/update/common/property-condition-functions.cpp
new file mode 100644 (file)
index 0000000..9422c88
--- /dev/null
@@ -0,0 +1,394 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/internal/update/common/property-condition-functions.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+// LessThan ///////////////////////////////////////////////////////////////////
+
+ConditionFunction LessThan::GetFunction(Property::Type valueType)
+{
+  ConditionFunction function = NULL;
+
+  switch(valueType)
+  {
+    case Property::BOOLEAN:
+    {
+      function = LessThan::EvalBoolean;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      function = LessThan::EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = LessThan::EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = LessThan::EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = LessThan::EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = LessThan::EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = LessThan::EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool LessThan::EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetBoolean() < arg0);
+}
+
+bool LessThan::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const int arg0 = arg[0];
+  return (value.GetInteger() < arg0);
+}
+
+bool LessThan::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetFloat() < arg0);
+}
+
+bool LessThan::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector2().LengthSquared() < arg0 * arg0);
+}
+
+bool LessThan::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector3().LengthSquared() < arg0 * arg0);
+}
+
+bool LessThan::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector4().LengthSquared() < arg0 * arg0);
+}
+
+bool LessThan::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+// GreaterThan ///////////////////////////////////////////////////////////////////
+
+ConditionFunction GreaterThan::GetFunction(Property::Type valueType)
+{
+  ConditionFunction function = NULL;
+
+  switch(valueType)
+  {
+    case Property::BOOLEAN:
+    {
+      function = GreaterThan::EvalBoolean;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      function = GreaterThan::EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = GreaterThan::EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = GreaterThan::EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = GreaterThan::EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = GreaterThan::EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = GreaterThan::EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool GreaterThan::EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetBoolean() > arg0);
+}
+
+bool GreaterThan::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const int arg0 = arg[0];
+  return (value.GetInteger() > arg0);
+}
+
+bool GreaterThan::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetFloat() > arg0);
+}
+
+bool GreaterThan::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector2().LengthSquared() > arg0 * arg0);
+}
+
+bool GreaterThan::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector3().LengthSquared() > arg0 * arg0);
+}
+
+bool GreaterThan::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float arg0 = arg[0];
+  return (value.GetVector4().LengthSquared() > arg0 * arg0);
+}
+
+bool GreaterThan::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+// Inside /////////////////////////////////////////////////////////////////////
+
+ConditionFunction Inside::GetFunction(Property::Type valueType)
+{
+  ConditionFunction function = NULL;
+
+  switch(valueType)
+  {
+    case Property::BOOLEAN:
+    {
+      function = Inside::EvalBoolean;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      function = Inside::EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = Inside::EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = Inside::EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = Inside::EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = Inside::EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = Inside::EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool Inside::EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const bool valueBoolean = value.GetBoolean();
+  return ( (valueBoolean > arg[0]) && (valueBoolean < arg[1]) );
+}
+
+bool Inside::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const int valueInteger = value.GetInteger();
+  return ( (valueInteger > arg[0]) && (valueInteger < arg[1]) );
+}
+
+bool Inside::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float valueFloat = value.GetFloat();
+  return ( (valueFloat > arg[0]) && (valueFloat < arg[1]) );
+}
+
+bool Inside::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector2().LengthSquared();
+  return ( (length2 > arg[0]*arg[0]) && (length2 < arg[1]*arg[1]) );
+}
+
+bool Inside::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector3().LengthSquared();
+  return ( (length2 > arg[0]*arg[0]) && (length2 < arg[1]*arg[1]) );
+}
+
+bool Inside::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector4().LengthSquared();
+  return ( (length2 > arg[0]*arg[0]) && (length2 < arg[1]*arg[1]) );
+}
+
+bool Inside::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+// Outside ////////////////////////////////////////////////////////////////////
+
+ConditionFunction Outside::GetFunction(Property::Type valueType)
+{
+  ConditionFunction function = NULL;
+
+  switch(valueType)
+  {
+    case Property::BOOLEAN:
+    {
+      function = Outside::EvalBoolean;
+      break;
+    }
+    case Property::INTEGER:
+    {
+      function = Outside::EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = Outside::EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = Outside::EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = Outside::EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = Outside::EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = Outside::EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool Outside::EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const bool valueBoolean = value.GetBoolean();
+  return ( (valueBoolean < arg[0]) || (valueBoolean > arg[1]) );
+}
+
+bool Outside::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const int valueInteger = value.GetInteger();
+  return ( (valueInteger < arg[0]) || (valueInteger > arg[1]) );
+}
+
+bool Outside::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float valueFloat = value.GetFloat();
+  return ( (valueFloat < arg[0]) || (valueFloat > arg[1]) );
+}
+
+bool Outside::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector2().LengthSquared();
+  return ( (length2 < arg[0]*arg[0]) || (length2 > arg[1]*arg[1]) );
+}
+
+bool Outside::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector3().LengthSquared();
+  return ( (length2 < arg[0]*arg[0]) || (length2 > arg[1]*arg[1]) );
+}
+
+bool Outside::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float length2 = value.GetVector4().LengthSquared();
+  return ( (length2 < arg[0]*arg[0]) || (length2 > arg[1]*arg[1]) );
+}
+
+bool Outside::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-condition-functions.h b/dali/internal/update/common/property-condition-functions.h
new file mode 100644 (file)
index 0000000..a45685f
--- /dev/null
@@ -0,0 +1,383 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_FUNCTIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-value.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+
+// OTHER CONDITITION INCLUDES
+#include <dali/internal/update/common/property-condition-step-functions.h>
+#include <dali/internal/update/common/property-condition-variable-step-functions.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Object;
+class PropertyNotification;
+
+namespace SceneGraph
+{
+
+// LessThan ///////////////////////////////////////////////////////////////////
+
+/**
+ * LessThan condition class,
+ * Checks if a Property is "Less Than" the argument:
+ *
+ * bool       => false (0.0) or true (1.0) is less than arg0.
+ * float      => value is less than arg0.
+ * Vector2    => 2 dimensional length of vector is less than arg0.
+ * Vector3    => 3 dimensional length of vector is less than arg0.
+ * Vector4    => 4 dimensional length of vector is less than arg0.
+ * Default    => return false.
+ */
+class LessThan
+{
+
+public:
+
+  /**
+   * @return function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction(Property::Type valueType);
+
+private:
+
+  /**
+   * Checks if bool is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+// GreaterThan ////////////////////////////////////////////////////////////////
+
+/**
+ * GreaterThan condition class,
+ * Checks if a Property is "Greater Than" the argument:
+ *
+ * bool       => false (0.0) or true (1.0) is greater than arg0.
+ * float      => value is greater than arg0.
+ * Vector2    => 2 dimensional length of vector is greater than arg0.
+ * Vector3    => 3 dimensional length of vector is greater than arg0.
+ * Vector4    => 4 dimensional length of vector is greater than arg0.
+ * Default    => return false.
+ */
+class GreaterThan
+{
+
+public:
+
+  /**
+   * @returns function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction(Property::Type valueType);
+
+private:
+
+  /**
+   * Checks if bool is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is GreaterThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types.
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+// Inside /////////////////////////////////////////////////////////////////////
+
+/**
+ * Inside condition class,
+ * Checks if a Property is "Inside" the two arguments:
+ *
+ * bool       => false (0.0) or true (1.0) is inside arg0.
+ * float      => value is between arg0 and arg1.
+ * Vector2    => 2 dimensional length of vector is between arg0 and arg1.
+ * Vector3    => 3 dimensional length of vector is between arg0 and arg1.
+ * Vector4    => 4 dimensional length of vector is between arg0 and arg1.
+ * Default    => return false.
+ */
+class Inside
+{
+
+public:
+
+  /**
+   * @return function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction(Property::Type valueType);
+
+private:
+
+  /**
+   * Checks if bool is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is Inside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types.
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+// Outside ////////////////////////////////////////////////////////////////////
+
+/**
+ * Outside condition class,
+ * Checks if a Property is "Outside" the two arguments:
+ *
+ * bool       => false (0.0) or true (1.0) is outside arg0.
+ * float      => value is outside arg0 and arg1.
+ * Vector2    => 2 dimensional length of vector is outside arg0 and arg1.
+ * Vector3    => 3 dimensional length of vector is outside arg0 and arg1.
+ * Vector4    => 4 dimensional length of vector is outside arg0 and arg1.
+ * Default    => return false.
+ */
+class Outside
+{
+
+public:
+
+  /**
+   * @return function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction(Property::Type valueType);
+
+private:
+
+  /**
+   * Checks if bool is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalBoolean( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types.
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_FUNCTIONS_H__
diff --git a/dali/internal/update/common/property-condition-step-functions.cpp b/dali/internal/update/common/property-condition-step-functions.cpp
new file mode 100644 (file)
index 0000000..a32981d
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/internal/update/common/property-condition-step-functions.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+const int ARGINDEX_REF_VALUE = 0;
+const int ARGINDEX_STEP_SIZE = 1;
+const int ARGINDEX_CURRENT_STEP = 2;
+
+} // namespace
+
+ConditionFunction Step::GetFunction(Property::Type valueType)
+{
+  ConditionFunction function = NULL;
+
+  switch(valueType)
+  {
+    case Property::INTEGER:
+    {
+      function = EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool Step::Evaluate( const float propertyValue, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float refValue = arg[ARGINDEX_REF_VALUE];
+  const float step = arg[ARGINDEX_STEP_SIZE];
+  const int currentStep = static_cast<int>(arg[ARGINDEX_CURRENT_STEP]);
+  const float distance = (propertyValue - refValue);
+  // step is actual 1.0f / step so can multiply instead of dividing
+  const int newStep = static_cast<int>(floorf(distance * step));
+
+  if( newStep != currentStep )
+  {
+    // in new section
+    arg[ARGINDEX_CURRENT_STEP] = static_cast<float>(newStep);
+    return true;
+  }
+  return false;
+}
+
+
+bool Step::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = static_cast<float>( value.GetInteger() );
+  return Evaluate( propertyValue, arg );
+}
+
+bool Step::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetFloat();
+  return Evaluate( propertyValue, arg );
+}
+bool Step::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetVector2().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool Step::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  float propertyValue = value.GetVector3().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool Step::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetVector4().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool Step::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-condition-step-functions.h b/dali/internal/update/common/property-condition-step-functions.h
new file mode 100644 (file)
index 0000000..00a9ee2
--- /dev/null
@@ -0,0 +1,118 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_STEP_FUNCTIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_STEP_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-value.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Object;
+class PropertyNotification;
+
+namespace SceneGraph
+{
+
+/**
+ * Step condition class,
+ * Checks if a Property has stepped a certain amount from the reference point
+ *
+ * float      => value has stepped arg1 amount from arg0.
+ * Vector2    => 2 dimensional length of vector has stepped arg1 amount from arg0.
+ * Vector3    => 3 dimensional length of vector has stepped arg1 amount from arg0.
+ * Vector4    => 4 dimensional length of vector has stepped arg1 amount from arg0.
+ * Default    => return false.
+ */
+class Step
+{
+
+public:
+
+  /**
+   * @return function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction( Property::Type valueType );
+
+private:
+
+  static bool Evaluate( const float propertyValue, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types.
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_STEP_FUNCTIONS_H__
diff --git a/dali/internal/update/common/property-condition-variable-step-functions.cpp b/dali/internal/update/common/property-condition-variable-step-functions.cpp
new file mode 100644 (file)
index 0000000..60fca7b
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/internal/update/common/property-condition-variable-step-functions.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+const int ARGINDEX_STEP_INDEX = 0;
+const int ARGINDEX_LIST_SIZE = 1;
+const int ARGINDEX_LIST_START = 2;
+
+}
+
+ConditionFunction VariableStep::GetFunction( Property::Type valueType )
+{
+  ConditionFunction function = NULL;
+
+  switch( valueType )
+  {
+    case Property::INTEGER:
+    {
+      function = EvalInteger;
+      break;
+    }
+    case Property::FLOAT:
+    {
+      function = EvalFloat;
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      function = EvalVector2;
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      function = EvalVector3;
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      function = EvalVector4;
+      break;
+    }
+    default:
+    {
+      function = EvalDefault;
+      break;
+    }
+  } // end switch
+
+  return function;
+}
+
+bool VariableStep::Evaluate( const float propertyValue, PropertyNotification::RawArgumentContainer& arg )
+{
+  const int currentIndex = arg[ARGINDEX_STEP_INDEX];
+  const int numSteps = arg[ARGINDEX_LIST_SIZE];
+  const float first = arg[ARGINDEX_LIST_START];
+  const float last = arg[ARGINDEX_LIST_START + (numSteps - 1)];
+  const bool ascending = (last > first) ? true : false;
+  int newIndex = currentIndex;
+
+  // avoid loop if property currently not within any of the range values
+  if( ascending )
+  {
+    if( propertyValue < first )
+    {
+      newIndex = -1;
+    }
+    else if( propertyValue >= last )
+    {
+      newIndex = numSteps - 1;
+    }
+  }
+  else
+  {
+    // increments are in negative direction
+    if( propertyValue > first )
+    {
+      newIndex = -1;
+    }
+    else if( propertyValue <= last )
+    {
+      newIndex = numSteps - 1;
+    }
+  }
+  int i = 0;
+  for( i = 0 ; i < numSteps - 1 ; ++i )
+  {
+    const float arg1 = arg[ARGINDEX_LIST_START + i];
+    const float arg2 = arg[ARGINDEX_LIST_START + (i + 1)];
+    if( ascending )
+    {
+      if( ( propertyValue >= arg1 )
+          && ( propertyValue < arg2 ) )
+      {
+        newIndex = i;
+        break;
+      }
+    }
+    else
+    {
+      // increments are in negative direction
+      if( ( propertyValue > arg2 )
+          && ( propertyValue <= arg1 ) )
+      {
+        newIndex = i;
+        break;
+      }
+    }
+  }
+  if( newIndex != currentIndex )
+  {
+    // have changed to new step
+    arg[ARGINDEX_STEP_INDEX] = static_cast<float>(newIndex);
+    return true;
+  }
+  return false;
+}
+
+bool VariableStep::EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = static_cast<float>( value.GetInteger() );
+  return Evaluate( propertyValue, arg );
+}
+
+bool VariableStep::EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetFloat();
+  return Evaluate( propertyValue, arg );
+}
+
+bool VariableStep::EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetVector2().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool VariableStep::EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  float propertyValue = value.GetVector3().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool VariableStep::EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  const float propertyValue = value.GetVector4().LengthSquared();
+  return Evaluate( propertyValue, arg );
+}
+
+bool VariableStep::EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg )
+{
+  return false;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-condition-variable-step-functions.h b/dali/internal/update/common/property-condition-variable-step-functions.h
new file mode 100644 (file)
index 0000000..412f283
--- /dev/null
@@ -0,0 +1,123 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_VARIABLE_STEP_FUNCTIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_VARIABLE_STEP_FUNCTIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-value.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Object;
+class PropertyNotification;
+
+namespace SceneGraph
+{
+
+/**
+ * VariableStep condition class,
+ * Uses a list of values, this condition notifies when the Property crosses between different values
+ *
+ * float      => value has stepped arg1 amount from arg0.
+ * Vector2    => 2 dimensional length of vector has stepped arg1 amount from arg0.
+ * Vector3    => 3 dimensional length of vector has stepped arg1 amount from arg0.
+ * Vector4    => 4 dimensional length of vector has stepped arg1 amount from arg0.
+ * Default    => return false.
+ */
+class VariableStep
+{
+
+public:
+
+  /**
+   * @return function pointer to the correct condition function, based on
+   * the type of value being examined.
+   */
+  static ConditionFunction GetFunction( Property::Type valueType );
+
+private:
+
+  /**
+   * Helper function used to evaluate our property
+   *
+   *
+   */
+  static bool Evaluate( const float propertyValue, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if integer is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalInteger( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if float is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFloat( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector2.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector2( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector3.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector3( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Checks if Vector4.Length() is Outside
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalVector4( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+  /**
+   * Default check for other types.
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalDefault( const Dali::PropertyInput& value, PropertyNotification::RawArgumentContainer& arg );
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_CONDITION_VARIABLE_STEP_FUNCTIONS_H__
diff --git a/dali/internal/update/common/property-owner-messages.cpp b/dali/internal/update/common/property-owner-messages.cpp
new file mode 100644 (file)
index 0000000..9cc7014
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/common/property-owner-messages.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+// Messages for a property owner
+
+PropertyOwnerMessageBase::PropertyOwnerMessageBase()
+{
+}
+
+PropertyOwnerMessageBase::~PropertyOwnerMessageBase()
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-owner-messages.h b/dali/internal/update/common/property-owner-messages.h
new file mode 100644 (file)
index 0000000..0b4e23b
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_MESSAGES_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_MESSAGES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/property-input-impl.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <string>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class UniformMap;
+class PropertyOwner;
+
+// Property Messages for PropertyOwner
+
+/**
+ * A base class for property owner property messages.
+ * (For future optimization - see NodeMessageBase & Node.SetActive())
+ */
+class PropertyOwnerMessageBase : public MessageBase
+{
+public:
+
+  /**
+   * Create a message.
+   */
+  PropertyOwnerMessageBase();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PropertyOwnerMessageBase();
+
+private:
+
+  // Undefined
+  PropertyOwnerMessageBase(const PropertyOwnerMessageBase&);
+  PropertyOwnerMessageBase& operator=(const PropertyOwnerMessageBase& rhs);
+};
+
+/**
+ * Templated message which bakes a property.
+ */
+template< typename P >
+class AnimatablePropertyMessage : public PropertyOwnerMessageBase
+{
+public:
+
+  typedef void(AnimatableProperty<P>::*MemberFunction)( BufferIndex, typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The scene object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] sceneObject The property owner scene object
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const PropertyOwner* sceneObject,
+                    const AnimatableProperty<P>* property,
+                    MemberFunction member,
+                    typename ParameterType< P >::PassingType value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( AnimatablePropertyMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) AnimatablePropertyMessage( sceneObject, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~AnimatablePropertyMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The property owner is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] sceneObject the property owner scene object
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  AnimatablePropertyMessage( const PropertyOwner* sceneObject,
+                             const AnimatableProperty<P>* property,
+                             MemberFunction member,
+                             typename ParameterType< P >::PassingType value )
+  : PropertyOwnerMessageBase(),
+    mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
+    mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+
+  PropertyOwner* mSceneObject;
+  AnimatableProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  typename ParameterType< P >::HolderType mParam;
+};
+
+/**
+ * Templated message which bakes a property.
+ */
+template< typename P >
+class AnimatablePropertyComponentMessage : public PropertyOwnerMessageBase
+{
+public:
+
+  typedef void(AnimatableProperty<P>::*MemberFunction)( BufferIndex, float );
+
+  /**
+   * Send a message.
+   * @note The scene object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The service object used for sending messages to the scene graph
+   * @param[in] sceneObject The property owner scene object
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const PropertyOwner* sceneObject,
+                    const AnimatableProperty<P>* property,
+                    MemberFunction member,
+                    float value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( AnimatablePropertyComponentMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) AnimatablePropertyComponentMessage( sceneObject, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~AnimatablePropertyComponentMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The scene object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] sceneObject The property owner scene object
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+  */
+  AnimatablePropertyComponentMessage( const PropertyOwner* sceneObject,
+                                      const AnimatableProperty<P>* property,
+                                      MemberFunction member,
+                                      float value )
+  : PropertyOwnerMessageBase(),
+    mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
+    mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+  PropertyOwner* mSceneObject;
+  AnimatableProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  float mParam;
+};
+
+
+/**
+ * Template class for sending messages to double buffered properties in a PropertyOwner
+ */
+template< typename P >
+class DoubleBufferedPropertyMessage : public PropertyOwnerMessageBase
+{
+public:
+
+  typedef void(DoubleBufferedProperty<P>::*MemberFunction)( BufferIndex, typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The scene object is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] sceneObject The property owner scene object
+   * @param[in] property The property to set.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const PropertyOwner* sceneObject,
+                    const DoubleBufferedProperty<P>* property,
+                    MemberFunction member,
+                    typename ParameterType< P >::PassingType value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( DoubleBufferedPropertyMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) DoubleBufferedPropertyMessage( sceneObject, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~DoubleBufferedPropertyMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    DALI_ASSERT_DEBUG( mProperty && "Message does not have an object" );
+    (mProperty->*mMemberFunction)( updateBufferIndex,
+                                   ParameterType< P >::PassObject( mParam ) );
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The property owner is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] sceneObject the property owner scene object
+   * @param[in] property The property to set.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  DoubleBufferedPropertyMessage( const PropertyOwner* sceneObject,
+                                 const DoubleBufferedProperty<P>* property,
+                                 MemberFunction member,
+                                 typename ParameterType< P >::PassingType value )
+  : PropertyOwnerMessageBase(),
+    mSceneObject( const_cast< PropertyOwner* >( sceneObject ) ),
+    mProperty( const_cast< DoubleBufferedProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+  PropertyOwner* mSceneObject;
+  DoubleBufferedProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  typename ParameterType< P >::HolderType mParam;
+};
+
+
+// Messages for PropertyOwner
+
+inline void InstallCustomPropertyMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, PropertyBase* property )
+{
+  typedef MessageValue1< PropertyOwner, OwnerPointer<PropertyBase> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &owner, &PropertyOwner::InstallCustomProperty, property );
+}
+
+inline void ApplyConstraintMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, ConstraintBase& constraint )
+{
+  typedef MessageValue1< PropertyOwner, OwnerPointer<ConstraintBase> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &owner, &PropertyOwner::ApplyConstraint, &constraint );
+}
+
+inline void RemoveConstraintMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, const ConstraintBase& constConstraint )
+{
+  // The update-thread can modify this object.
+  ConstraintBase& constraint = const_cast< ConstraintBase& >( constConstraint );
+
+  typedef MessageValue1< PropertyOwner, ConstraintBase* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &owner, &PropertyOwner::RemoveConstraint, &constraint );
+}
+
+inline void AddUniformMapMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, UniformPropertyMapping* map )
+{
+  typedef MessageValue1< PropertyOwner, OwnerPointer< UniformPropertyMapping > > LocalType;
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+  new (slot) LocalType( &owner, &PropertyOwner::AddUniformMapping, map );
+}
+
+inline void RemoveUniformMapMessage( EventThreadServices& eventThreadServices, const PropertyOwner& owner, const std::string& uniformName )
+{
+  typedef MessageValue1< PropertyOwner, std::string > LocalType;
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+  new (slot) LocalType( &owner, &PropertyOwner::RemoveUniformMapping, uniformName );
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_MESSAGES_H__
diff --git a/dali/internal/update/common/property-owner.cpp b/dali/internal/update/common/property-owner.cpp
new file mode 100644 (file)
index 0000000..ec3d17a
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/common/property-owner.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+PropertyOwner* PropertyOwner::New()
+{
+  return new PropertyOwner();
+}
+
+PropertyOwner::~PropertyOwner()
+{
+  Destroy();
+}
+
+void PropertyOwner::AddObserver(Observer& observer)
+{
+  //Check for duplicates in debug builds
+  DALI_ASSERT_DEBUG( mObservers.End() == std::find( mObservers.Begin(), mObservers.End(), &observer ) );
+
+  mObservers.PushBack( &observer );
+}
+
+void PropertyOwner::RemoveObserver(Observer& observer)
+{
+  // Find the observer...
+  const ConstObserverIter endIter =  mObservers.End();
+  for( ObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  {
+    if( (*iter) == &observer)
+    {
+      // erase it
+      mObservers.Erase(iter);
+      break;
+    }
+  }
+}
+
+bool PropertyOwner::IsObserved()
+{
+  return mObservers.Count() != 0u;
+}
+
+void PropertyOwner::Destroy()
+{
+  // Notification for observers
+  const ConstObserverIter endIter = mObservers.End();
+  for( ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  {
+    (*iter)->PropertyOwnerDestroyed(*this);
+  }
+
+  mObservers.Clear();
+
+  // Remove all constraints when disconnected from scene-graph
+  mConstraints.Clear();
+}
+
+void PropertyOwner::ConnectToSceneGraph()
+{
+  // Notification for observers
+  const ConstObserverIter endIter = mObservers.End();
+  for( ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  {
+    (*iter)->PropertyOwnerConnected( *this );
+  }
+}
+
+void PropertyOwner::DisconnectFromSceneGraph( BufferIndex updateBufferIndex )
+{
+  // Notification for observers
+  const ConstObserverIter endIter = mObservers.End();
+  for( ConstObserverIter iter = mObservers.Begin(); iter != endIter; ++iter)
+  {
+    (*iter)->PropertyOwnerDisconnected( updateBufferIndex, *this );
+  }
+
+  // Remove all constraints when disconnected from scene-graph
+  mConstraints.Clear();
+}
+
+void PropertyOwner::InstallCustomProperty(PropertyBase* property)
+{
+  DALI_ASSERT_DEBUG( NULL != property );
+
+  mCustomProperties.PushBack( property );
+}
+
+void PropertyOwner::ResetToBaseValues( BufferIndex updateBufferIndex )
+{
+  // Reset custom properties
+  const OwnedPropertyIter endIter = mCustomProperties.End();
+  for ( OwnedPropertyIter iter = mCustomProperties.Begin(); endIter != iter; ++iter )
+  {
+    (*iter)->ResetToBaseValue( updateBufferIndex );
+  }
+
+  // Notification for derived classes, to reset default properties
+  ResetDefaultProperties( updateBufferIndex );
+}
+
+ConstraintOwnerContainer& PropertyOwner::GetConstraints()
+{
+  return mConstraints;
+}
+
+void PropertyOwner::ApplyConstraint( ConstraintBase* constraint )
+{
+  mConstraints.PushBack( constraint );
+
+  constraint->OnConnect();
+}
+
+void PropertyOwner::RemoveConstraint( ConstraintBase* constraint )
+{
+  const ConstraintIter constraintEndIter = mConstraints.End();
+  for( ConstraintIter iter = mConstraints.Begin(); constraintEndIter != iter; ++iter )
+  {
+    if ( *iter == constraint )
+    {
+      mConstraints.Erase( iter );
+      return; // We're finished
+    }
+  }
+
+  // Should not come here
+  DALI_ASSERT_DEBUG( false && "Constraint missing in RemoveConstraint" );
+}
+
+PropertyOwner::PropertyOwner()
+{
+}
+
+void PropertyOwner::AddUniformMapping( UniformPropertyMapping* map )
+{
+  mUniformMaps.Add( map );
+}
+
+void PropertyOwner::RemoveUniformMapping( const std::string& uniformName )
+{
+  mUniformMaps.Remove( uniformName );
+}
+
+const UniformMap& PropertyOwner::GetUniformMap() const
+{
+  return mUniformMaps;
+}
+
+void PropertyOwner::AddUniformMapObserver( UniformMap::Observer& observer )
+{
+  mUniformMaps.AddObserver( observer );
+}
+
+void PropertyOwner::RemoveUniformMapObserver( UniformMap::Observer& observer )
+{
+  mUniformMaps.RemoveObserver( observer );
+}
+
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/property-owner.h b/dali/internal/update/common/property-owner.h
new file mode 100644 (file)
index 0000000..01ff3dd
--- /dev/null
@@ -0,0 +1,253 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/update/animation/scene-graph-constraint-declarations.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class PropertyOwner;
+
+typedef OwnerContainer< PropertyBase* > OwnedPropertyContainer;
+typedef OwnedPropertyContainer::Iterator  OwnedPropertyIter;
+
+/**
+ * An update-thread object which own properties.
+ * This allows observers to track the lifetime of the object & its properties.
+ */
+class PropertyOwner
+{
+public:
+
+  class Observer
+  {
+  public:
+
+    /**
+     * Called when the observable object is connected to the scene graph.
+     * @param[in] owner A reference to the connected PropertyOwner
+     */
+    virtual void PropertyOwnerConnected( PropertyOwner& owner ) = 0;
+
+    /**
+     * Called when the observable object is disconnected from the scene graph.
+     * @param[in] currentBufferIndex The buffer to reset.
+     * @param[in] owner A reference to the disconnected PropertyOwner
+     */
+    virtual void PropertyOwnerDisconnected( BufferIndex updateBufferIndex, PropertyOwner& owner ) = 0;
+
+    /**
+     * Called shortly before the observable object is destroyed.
+     *
+     * @note Cleanup should be done in both this and PropertyOwnerDisconnected as PropertyOwnerDisconnected
+     * may not be called (i.e. when shutting down).
+     */
+    virtual void PropertyOwnerDestroyed( PropertyOwner& owner ) = 0;
+  };
+
+  /**
+   * Create a property owner.
+   * @return A newly allocated object.
+   */
+  static PropertyOwner* New();
+
+  /**
+   * Virtual destructor; this is intended as a base class.
+   */
+  virtual ~PropertyOwner();
+
+  /**
+   * Add an observer.
+   * The observer is responsible for calling RemoveObserver(*this) during its own destruction.
+   * Connecting an actor-side object as an observer is not allowed, due to thread-safety issues.
+   * @param[in] observer The observer.
+   */
+  void AddObserver(Observer& observer);
+
+  /**
+   * Remove an observer.
+   * @param[in] observer The observer.
+   */
+  void RemoveObserver(Observer& observer);
+
+  /**
+   * This method can be used to determine if there is an animation or
+   * constraint that is using this property owner.
+   * @return true if there are observers.
+   */
+  bool IsObserved();
+
+  /**
+   * Called just before destruction to disconnect all observers and remove constraints.
+   * This occurs when the object is in the process of being destroyed.
+   */
+  void Destroy();
+
+  /**
+   * Notify all observers that the object has been connected
+   * This occurs when the object is connected to the scene-graph during UpdateManager::Update().
+   */
+  void ConnectToSceneGraph();
+
+  /**
+   * Notify all observers that the object has been disconnected and remove constraints.
+   * This occurs when the object is disconnected from the scene-graph during UpdateManager::Update().
+   * @param[in] currentBufferIndex The current update buffer.
+   */
+  void DisconnectFromSceneGraph( BufferIndex updateBufferIndex );
+
+  /**
+   * Install a custom property.
+   * @post The PropertyOwner takes ownership of the property.
+   * @param[in] property A pointer to a newly allocated property.
+   */
+  void InstallCustomProperty(PropertyBase* property);
+
+  /**
+   * Retrieve the custom properties owned by the object.
+   * @return A container of properties.
+   */
+  OwnedPropertyContainer& GetCustomProperties()
+  {
+    return mCustomProperties;
+  }
+
+  /**
+   * Retrieve the custom properties owned by the object.
+   * @return A container of properties.
+   */
+  const OwnedPropertyContainer& GetCustomProperties() const
+  {
+    return mCustomProperties;
+  }
+
+  /**
+   * Reset animatable properties to the corresponding base values.
+   * @param[in] currentBufferIndex The buffer to reset.
+   * @post The ResetDefaultProperties method is called, during which derived classes can reset default properties.
+   */
+  void ResetToBaseValues( BufferIndex updateBufferIndex );
+
+  // Constraints
+
+  /**
+   * Apply a constraint.
+   * @param[in] constraint The constraint to apply.
+   */
+  void ApplyConstraint( ConstraintBase* constraint );
+
+  /**
+   * Begin removal of constraints.
+   * @param[in] constraint The constraint to remove.
+   */
+  void RemoveConstraint( ConstraintBase* constraint );
+
+  /**
+   * Retrieve the constraints that are currently applied.
+   * @return A container of constraints.
+   */
+  ConstraintOwnerContainer& GetConstraints();
+
+  /**
+   * @copydoc UniformMap::Add
+   */
+  void AddUniformMapping( UniformPropertyMapping* map );
+
+  /**
+   * @copydoc UniformMap::Remove
+   */
+  void RemoveUniformMapping( const std::string& uniformName );
+
+  /**
+   * Get the mappings table
+   */
+  const UniformMap& GetUniformMap() const;
+
+  /**
+   * @copydoc UniformMap::AddUniformMapObserver
+   */
+  void AddUniformMapObserver( UniformMap::Observer& observer );
+
+  /**
+   * @copydoc UniformMap::RemoveUniformMapObserver
+   */
+  void RemoveUniformMapObserver( UniformMap::Observer& observer );
+
+
+protected:
+
+  /**
+   * Protected constructor.
+   */
+  PropertyOwner();
+
+private:
+
+  // Undefined
+  PropertyOwner(const PropertyOwner&);
+
+  // Undefined
+  PropertyOwner& operator=(const PropertyOwner& rhs);
+
+  /**
+   * Called after ResetToBaseValues; derived classes should reset any default properties.
+   * @param[in] currentBufferIndex The buffer to reset.
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex ) {}
+
+protected:
+
+  OwnedPropertyContainer mCustomProperties; ///< Properties provided with InstallCustomProperty()
+  UniformMap mUniformMaps; ///< Container of owned uniform maps
+
+private:
+
+  typedef Dali::Vector<PropertyOwner::Observer*> ObserverContainer;
+  typedef ObserverContainer::Iterator ObserverIter;
+  typedef ObserverContainer::ConstIterator ConstObserverIter;
+
+  ObserverContainer mObservers; ///< Container of observer raw-pointers (not owned)
+
+  ConstraintOwnerContainer mConstraints; ///< Container of owned constraints
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_OWNER_H__
diff --git a/dali/internal/update/common/property-vector3.h b/dali/internal/update/common/property-vector3.h
new file mode 100644 (file)
index 0000000..463ff28
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_VECTOR3_PROPERTY_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_VECTOR3_PROPERTY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * A Vector3 non-animatable property.
+ */
+class PropertyVector3 : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create an non-animatable property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  PropertyVector3( Vector3 initialValue )
+  : mValue( initialValue ),
+    mDirtyFlag( true )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~PropertyVector3()
+  {
+  }
+
+  /**
+   * Clear the dirty flag
+   */
+  void Clear()
+  {
+    mDirtyFlag = false;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get<Vector3>();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   */
+  virtual bool InputChanged() const
+  {
+    return mDirtyFlag;
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector3()
+   */
+  virtual const Vector3& GetVector3( BufferIndex bufferIndex ) const
+  {
+    return mValue;
+  }
+
+  /**
+   * Flag that the property has been Set during the current frame.
+   */
+  void OnSet()
+  {
+    mDirtyFlag = true;
+  }
+
+private:
+
+  // Undefined
+  PropertyVector3(const PropertyVector3& property);
+
+  // Undefined
+  PropertyVector3& operator=(const PropertyVector3& rhs);
+
+public:
+
+  Vector3 mValue; ///< The property value
+
+private:
+
+  bool mDirtyFlag;
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_VECTOR3_PROPERTY_H__
diff --git a/dali/internal/update/common/scene-graph-buffers.cpp b/dali/internal/update/common/scene-graph-buffers.cpp
new file mode 100644 (file)
index 0000000..c6e6161
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+BufferIndex SceneGraphBuffers::INITIAL_EVENT_BUFFER_INDEX  = 0u;
+BufferIndex SceneGraphBuffers::INITIAL_UPDATE_BUFFER_INDEX = 1u;
+
+SceneGraphBuffers::SceneGraphBuffers()
+: mEventBufferIndex(INITIAL_EVENT_BUFFER_INDEX),
+  mUpdateBufferIndex(INITIAL_UPDATE_BUFFER_INDEX)
+{
+}
+
+SceneGraphBuffers::~SceneGraphBuffers()
+{
+}
+
+void SceneGraphBuffers::Swap()
+{
+  mUpdateBufferIndex = __sync_fetch_and_xor( &mEventBufferIndex, 1 );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/scene-graph-buffers.h b/dali/internal/update/common/scene-graph-buffers.h
new file mode 100644 (file)
index 0000000..b9fb6e0
--- /dev/null
@@ -0,0 +1,91 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_BUFFERS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_BUFFERS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Node values (position etc.) are double-buffered.  A SceneGraphBuffers object
+ * can be used to keep track of which buffers are being written or read.
+ */
+class SceneGraphBuffers
+{
+public:
+
+  static BufferIndex INITIAL_EVENT_BUFFER_INDEX;  // 0
+  static BufferIndex INITIAL_UPDATE_BUFFER_INDEX; // 1
+
+  /**
+   * Create a SceneGraphBuffers object.
+   */
+  SceneGraphBuffers();
+
+  /**
+   * Non-virtual destructor; not intended as a base class.
+   */
+  ~SceneGraphBuffers();
+
+  /**
+   * Retrieve the current event-buffer index.
+   * @return The buffer index.
+   */
+  BufferIndex GetEventBufferIndex() const { return mEventBufferIndex; }
+
+  /**
+   * Retrieve the current update-buffer index.
+   * @return The buffer index.
+   */
+  BufferIndex GetUpdateBufferIndex() const { return mUpdateBufferIndex; }
+
+  /**
+   * Swap the Event & Update buffer indices.
+  */
+  void Swap();
+
+private:
+
+  // Undefined
+  SceneGraphBuffers(const SceneGraphBuffers&);
+
+  // Undefined
+  SceneGraphBuffers& operator=(const SceneGraphBuffers& rhs);
+
+private:
+
+  BufferIndex mEventBufferIndex;  ///< 0 or 1 (opposite of mUpdateBufferIndex)
+  BufferIndex mUpdateBufferIndex; ///< 0 or 1 (opposite of mEventBufferIndex)
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_BUFFERS_H__
diff --git a/dali/internal/update/common/scene-graph-connection-change-propagator.cpp b/dali/internal/update/common/scene-graph-connection-change-propagator.cpp
new file mode 100644 (file)
index 0000000..aa52424
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scene-graph-connection-change-propagator.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+ConnectionChangePropagator::ConnectionChangePropagator()
+{
+}
+
+ConnectionChangePropagator::~ConnectionChangePropagator()
+{
+}
+
+void ConnectionChangePropagator::Add(Observer& observer)
+{
+  bool foundObserver = false;
+  for( ObserversIterator iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    if( *iter == &observer )
+    {
+      foundObserver = true;
+      break;
+    }
+  }
+  if( !foundObserver )
+  {
+    mObservers.PushBack( &observer );
+  }
+}
+
+void ConnectionChangePropagator::Remove(Observer& observer)
+{
+  for( ObserversIterator iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    if( *iter == &observer )
+    {
+      mObservers.Erase(iter);
+      return;
+    }
+  }
+}
+
+void ConnectionChangePropagator::ConnectionsChanged(PropertyOwner& object)
+{
+  // Inform observers that the object's children have changed
+  for( ObserversIterator iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    Observer* observer = (*iter);
+    observer->ConnectionsChanged( object );
+  }
+}
+
+void ConnectionChangePropagator::ConnectedUniformMapChanged()
+{
+  // Inform observers that the object's uniform map has changed
+  for( ObserversIterator iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    Observer* observer = (*iter);
+    observer->ConnectedUniformMapChanged();
+  }
+}
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/update/common/scene-graph-connection-change-propagator.h b/dali/internal/update/common/scene-graph-connection-change-propagator.h
new file mode 100644 (file)
index 0000000..37c1c9c
--- /dev/null
@@ -0,0 +1,97 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_CONNECTION_CHANGE_PROPAGATOR_H
+#define DALI_INTERNAL_SCENE_GRAPH_CONNECTION_CHANGE_PROPAGATOR_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class PropertyOwner;
+
+/**
+ * This class maintains a list of observers that are informed when
+ * it's owner changes it's connections.
+ */
+class ConnectionChangePropagator
+{
+public:
+  class Observer
+  {
+  public:
+    /**
+     * Inform the observer of the object that it's connections have changed
+     * @param[in] object The connection owner
+     */
+    virtual void ConnectionsChanged(PropertyOwner& object) = 0;
+
+    /**
+     * Inform the observer of the object that a connected object has
+     * changed it's uniform map in some way.
+     */
+    virtual void ConnectedUniformMapChanged() = 0;
+  };
+
+  /**
+   * Constructor
+   */
+  ConnectionChangePropagator();
+
+  /**
+   * Destructor
+   */
+  ~ConnectionChangePropagator();
+
+  /**
+   * Add an observer
+   */
+  void Add(Observer& observer);
+
+  /**
+   * Remove an observer
+   */
+  void Remove(Observer& observer);
+
+  /**
+   * Inform the observers that the connections to the object have changed
+   * @param[in] object The connection owner
+   */
+  void ConnectionsChanged(PropertyOwner& object);
+
+  /**
+   * Inform the observers that the uniform map of this or a connected object
+   * has changed.
+   */
+  void ConnectedUniformMapChanged();
+
+private:
+  typedef Dali::Vector<Observer*> Observers;
+  typedef Observers::Iterator ObserversIterator;
+
+  Observers mObservers;
+};
+
+
+} // SceneGraph
+} // Internal
+} // Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_CONNECTION_CHANGE_PROPAGATOR_H
diff --git a/dali/internal/update/common/scene-graph-property-buffer.cpp b/dali/internal/update/common/scene-graph-property-buffer.cpp
new file mode 100644 (file)
index 0000000..c3fd74b
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+PropertyBuffer::PropertyBuffer()
+: mBufferData(NULL),
+  mDataChanged(false),
+  mSize(0u)
+{
+}
+
+PropertyBuffer::~PropertyBuffer()
+{
+}
+
+void PropertyBuffer::SetFormat( PropertyBufferMetadata::Format* format )
+{
+  mFormat = format;
+}
+
+void PropertyBuffer::SetSize( BufferIndex bufferIndex, unsigned int size )
+{
+  mSize.Set(bufferIndex, size);
+}
+
+void PropertyBuffer::SetData(  BufferIndex bufferIndex, PropertyBufferDataProvider::BufferType* data )
+{
+  mBufferData[bufferIndex] = data;
+  mDataChanged[bufferIndex] = true;
+}
+
+void PropertyBuffer::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void PropertyBuffer::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+bool PropertyBuffer::HasDataChanged( BufferIndex bufferIndex ) const
+{
+  return mDataChanged[ bufferIndex ];
+}
+
+unsigned int PropertyBuffer::GetAttributeCount( BufferIndex bufferIndex ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+  return mFormat->components.size();
+}
+
+const std::string& PropertyBuffer::GetAttributeName( BufferIndex bufferIndex, unsigned int index ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+  return mFormat->components[index].name;
+}
+
+size_t PropertyBuffer::GetAttributeSize( BufferIndex bufferIndex, unsigned int index ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+
+  return mFormat->components[index].size;
+}
+
+Property::Type PropertyBuffer::GetAttributeType( BufferIndex bufferIndex, unsigned int index ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+
+  return mFormat->components[index].type;
+}
+
+size_t PropertyBuffer::GetAttributeOffset( BufferIndex bufferIndex, unsigned int index ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+
+  return mFormat->components[index].offset;
+}
+
+const PropertyBufferDataProvider::BufferType& PropertyBuffer::GetData( BufferIndex bufferIndex ) const
+{
+  DALI_ASSERT_DEBUG( mBufferData[bufferIndex] && "Should have some data.");
+
+  return *mBufferData[bufferIndex];
+}
+
+std::size_t PropertyBuffer::GetDataSize( BufferIndex bufferIndex ) const
+{
+  DALI_ASSERT_DEBUG( mFormat && "Format should be set ");
+
+  return mFormat->size * mSize[ bufferIndex ];
+}
+
+
+std::size_t PropertyBuffer::GetElementSize( BufferIndex bufferIndex ) const
+{
+  return mFormat->size;
+}
+
+unsigned int PropertyBuffer::GetElementCount( BufferIndex bufferIndex ) const
+{
+  return mSize[bufferIndex];
+}
+
+unsigned int PropertyBuffer::GetGpuBufferId( BufferIndex bufferIndex ) const
+{
+  //TODO: MESH_REWORK fix this
+  DALI_ASSERT_DEBUG(false && "FIX THIS");
+
+  return 0;
+}
+
+void PropertyBuffer::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  // Age the double buffered properties
+  mSize.CopyPrevious(updateBufferIndex);
+
+  // Update double buffered value
+  mBufferData.CopyPrevious(updateBufferIndex);
+
+  // The flag should be reset each frame
+  mDataChanged[updateBufferIndex] = false;
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/update/common/scene-graph-property-buffer.h b/dali/internal/update/common/scene-graph-property-buffer.h
new file mode 100644 (file)
index 0000000..0f82433
--- /dev/null
@@ -0,0 +1,227 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_H
+#define DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/render/data-providers/property-buffer-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class SceneController;
+
+namespace PropertyBufferMetadata
+{
+/**
+ * Structure that holds name and size of a component in the PropertyBuffer.
+ */
+struct Component
+{
+  std::string name;
+  unsigned int offset;
+  unsigned int size;
+  Property::Type type;
+};
+
+/**
+ * Structure that holds the meta-data of the format of PropertyBuffer.
+ */
+struct Format
+{
+  std::vector<Component> components;
+  unsigned int size;
+};
+
+} // PropertyBufferMetadata
+
+class PropertyBuffer : public PropertyOwner, public PropertyBufferDataProvider
+{
+public:
+
+  /**
+   * Constructor
+   */
+  PropertyBuffer();
+
+  /**
+   * Destructor
+   */
+  virtual ~PropertyBuffer();
+
+  /**
+   * @brief Set the format of the buffer
+   *
+   * This function takes ownership of the pointer
+   *
+   * @param[in] format The format for the PropertyBuffer
+   */
+  void SetFormat( PropertyBufferMetadata::Format* format );
+
+  /**
+   * @brief Set the data of the PropertyBuffer
+   *
+   * This function takes ownership of the pointer
+   *
+   * @param[in] bufferIndex Index for double buffered values
+   * @param[in] data The new data of the PropertyBuffer
+   */
+  void SetData( BufferIndex bufferIndex, PropertyBufferDataProvider::BufferType* data );
+
+  /**
+   * @brief Set the number of elements
+   *
+   * @param[in] bufferIndex Index for double buffered values
+   * @param[in] size The number of elements
+   */
+  void SetSize( BufferIndex bufferIndex, unsigned int size );
+
+  /**
+   * @brief Connect the object to the scene graph
+   *
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * @brief Disconnect the object from the scene graph
+   */
+  void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+public: // PropertyBufferDataProvider
+
+  /**
+   * @copydoc PropertyBufferDataProvider::HasDataChanged( BufferIndex bufferIndex )
+   */
+  virtual bool HasDataChanged( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::HasDataChanged( BufferIndex bufferIndex )
+   */
+  virtual unsigned int GetAttributeCount( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetAttributeName( BufferIndex bufferIndex, unsigned int index )
+   */
+  virtual const std::string& GetAttributeName( BufferIndex bufferIndex, unsigned int index ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetAttributeSize( BufferIndex bufferIndex, unsigned int index )
+   */
+  virtual size_t GetAttributeSize( BufferIndex bufferIndex, unsigned int index ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetAttributeType( BufferIndex bufferIndex, unsigned int index )
+   */
+  virtual Property::Type GetAttributeType( BufferIndex bufferIndex, unsigned int index ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetAttributeOffset( BufferIndex bufferIndex, unsigned int index )
+   */
+  virtual size_t GetAttributeOffset( BufferIndex bufferIndex, unsigned int index ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetData( BufferIndex bufferIndex )
+   */
+  virtual const PropertyBufferDataProvider::BufferType& GetData( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetDataSize( BufferIndex bufferIndex )
+   */
+  virtual size_t GetDataSize( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetElementSize( BufferIndex bufferIndex )
+   */
+  virtual size_t GetElementSize( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetElementCount( BufferIndex bufferIndex )
+   */
+  virtual unsigned int GetElementCount( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc PropertyBufferDataProvider::GetGpuBufferId
+   */
+  virtual unsigned int GetGpuBufferId( BufferIndex bufferIndex ) const;
+
+protected: // From PropertyOwner
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+private:
+  OwnerPointer<PropertyBufferMetadata::Format> mFormat; ///< Format of the buffer
+
+  DoubleBuffered< OwnerPointer<PropertyBufferDataProvider::BufferType> > mBufferData; ///< Data
+  DoubleBuffered< bool > mDataChanged; ///< Flag to know if data has changed in a frame
+
+  DoubleBufferedProperty<int>  mSize; ///< Number of Elements in the buffer
+};
+
+inline void SetFormatMessage( EventThreadServices& eventThreadServices,
+                              const PropertyBuffer& propertyBuffer,
+                              PropertyBufferMetadata::Format* format )
+{
+  typedef MessageValue1< PropertyBuffer, OwnerPointer<PropertyBufferMetadata::Format> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &propertyBuffer, &PropertyBuffer::SetFormat, format );
+}
+
+inline void SetSizeMessage( EventThreadServices& eventThreadServices,
+                            const PropertyBuffer& propertyBuffer,
+                            unsigned int size )
+{
+  typedef MessageDoubleBuffered1 < PropertyBuffer, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &propertyBuffer, &PropertyBuffer::SetSize, size );
+}
+
+inline void SetDataMessage( EventThreadServices& eventThreadServices,
+                            const PropertyBuffer& propertyBuffer,
+                            PropertyBuffer::BufferType* data )
+{
+  typedef MessageDoubleBuffered1< PropertyBuffer, OwnerPointer<PropertyBuffer::BufferType> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &propertyBuffer, &PropertyBuffer::SetData, data );
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_PROPERTY_BUFFER_H
diff --git a/dali/internal/update/common/scene-graph-property-notification.cpp b/dali/internal/update/common/scene-graph-property-notification.cpp
new file mode 100644 (file)
index 0000000..012b537
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/animation/property-constraint.h>
+#include <dali/internal/event/animation/property-input-accessor.h>
+#include <dali/internal/event/animation/property-input-indexer.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+#include <dali/internal/update/common/property-condition-functions.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+PropertyNotification* PropertyNotification::New(Object& object,
+                                                Property::Index propertyIndex,
+                                                Property::Type propertyType,
+                                                int componentIndex,
+                                                ConditionType condition,
+                                                RawArgumentContainer& arguments,
+                                                NotifyMode notifyMode)
+{
+  return new PropertyNotification( object, propertyIndex, propertyType, componentIndex, condition, arguments, notifyMode );
+}
+
+
+PropertyNotification::PropertyNotification(Object& object,
+                                           Property::Index propertyIndex,
+                                           Property::Type propertyType,
+                                           int componentIndex,
+                                           ConditionType condition,
+                                           RawArgumentContainer& arguments,
+                                           NotifyMode notifyMode)
+: mObject(&object),
+  mPropertyIndex(propertyIndex),
+  mPropertyType(propertyType),
+  mProperty(NULL),
+  mComponentIndex(componentIndex),
+  mConditionType(condition),
+  mArguments(arguments),
+  mValid(false),
+  mNotifyMode( Dali::PropertyNotification::Disabled )
+{
+  SetNotifyMode(notifyMode);
+
+  switch(mConditionType)
+  {
+    case PropertyCondition::LessThan:
+    {
+      mConditionFunction = LessThan::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::GreaterThan:
+    {
+      mConditionFunction = GreaterThan::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::Inside:
+    {
+      mConditionFunction = Inside::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::Outside:
+    {
+      mConditionFunction = Outside::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::Step:
+    {
+      mConditionFunction = Step::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::VariableStep:
+    {
+      mConditionFunction = VariableStep::GetFunction(mPropertyType);
+      break;
+    }
+    case PropertyCondition::False:
+    {
+      mConditionFunction = PropertyNotification::EvalFalse;
+      break;
+    }
+  }
+
+  mProperty = mObject->GetSceneObjectInputProperty( mPropertyIndex );
+  int internalComponentIndex = mObject->GetPropertyComponentIndex(mPropertyIndex);
+  if( internalComponentIndex != Property::INVALID_COMPONENT_INDEX )
+  {
+    // override the one passed in
+    mComponentIndex = internalComponentIndex;
+  }
+}
+
+PropertyNotification::~PropertyNotification()
+{
+}
+
+bool PropertyNotification::EvalFalse( const Dali::PropertyInput& value, RawArgumentContainer& arg )
+{
+  return false;
+}
+
+void PropertyNotification::SetNotifyMode( NotifyMode notifyMode )
+{
+  mNotifyMode = notifyMode;
+}
+
+bool PropertyNotification::Check( BufferIndex bufferIndex )
+{
+  bool notifyRequired = false;
+  bool currentValid = false;
+
+  if ( Property::INVALID_COMPONENT_INDEX != mComponentIndex )
+  {
+    // Evaluate Condition
+    const PropertyInputAccessor component( mProperty, mComponentIndex );
+    const PropertyInputIndexer< PropertyInputAccessor > input( bufferIndex, &component );
+    currentValid = mConditionFunction(input, mArguments);
+  }
+  else
+  {
+    // Evaluate Condition
+    const PropertyInputIndexer< PropertyInputImpl > input( bufferIndex, mProperty );
+    currentValid = mConditionFunction(input, mArguments);
+  }
+
+  if( mValid != currentValid
+      || (currentValid && ((mConditionType == PropertyCondition::Step)
+                        || (mConditionType == PropertyCondition::VariableStep))) )
+  {
+    mValid = currentValid;
+    //  means don't notify so notifyRequired stays false
+    switch( mNotifyMode )
+    {
+      case Dali::PropertyNotification::Disabled:
+      {
+        // notify never, already initialized to false
+        break;
+      }
+      case Dali::PropertyNotification::NotifyOnTrue:
+      {
+        notifyRequired = mValid; // notify if value is true
+        break;
+      }
+      case Dali::PropertyNotification::NotifyOnFalse:
+      {
+        notifyRequired = !mValid; // notify when its false
+        break;
+      }
+      case Dali::PropertyNotification::NotifyOnChanged:
+      {
+        notifyRequired = true; // notify whenever changed
+        break;
+      }
+    }
+  }
+
+  return notifyRequired;
+}
+
+bool PropertyNotification::GetValidity() const
+{
+  return mValid;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/common/scene-graph-property-notification.h b/dali/internal/update/common/scene-graph-property-notification.h
new file mode 100644 (file)
index 0000000..6681fbb
--- /dev/null
@@ -0,0 +1,162 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_NOTIFICATION_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_NOTIFICATION_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-notification.h>
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/update/common/property-base.h>
+#include <dali/internal/common/owner-container.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class Object;
+class PropertyNotification;
+
+namespace SceneGraph
+{
+
+class PropertyNotification;
+
+typedef OwnerContainer< PropertyNotification* > PropertyNotificationContainer;
+typedef PropertyNotificationContainer::Iterator PropertyNotificationIter;
+typedef PropertyNotificationContainer::ConstIterator PropertyNotificationConstIter;
+typedef bool(*ConditionFunction)(const Dali::PropertyInput& value, Dali::Internal::PropertyNotification::RawArgumentContainer& args);
+
+/**
+ * PropertyNotifications are used to inspect properties of scene graph objects, as part of a scene
+ * managers "update" phase. When a condition has been met the application receives a notification signal.
+ */
+class PropertyNotification
+{
+public:
+
+  typedef Dali::PropertyNotification::NotifyMode NotifyMode;
+  typedef Dali::Internal::PropertyNotification::ConditionType ConditionType;
+  typedef Dali::Internal::PropertyNotification::RawArgumentContainer RawArgumentContainer;
+  typedef const void *(*GetPropertyFunction)( const SceneGraph::PropertyBase*, int );
+
+  /**
+   * Construct a new PropertyNotification
+   * @param[in] object The event-object for a scene-graph object to inspect.
+   * @param[in] propertyIndex The index of a property provided by the object.
+   * @param[in] propertyType The type of property we're inspecting.
+   * @param[in] componentIndex Index to the component of a complex property such as a Vector
+   * @param[in] condition The condition type (e.g. LessThan, GreaterThan...)
+   * @param[in] arguments The arguments which accompany the condition.
+   * @param[in] notifyMode The notification mode setting
+   * @return A new PropertyNotification object.
+   */
+  static PropertyNotification* New(Object& object,
+                                   Property::Index propertyIndex,
+                                   Property::Type propertyType,
+                                   int componentIndex,
+                                   ConditionType condition,
+                                   RawArgumentContainer& arguments,
+                                   NotifyMode notifyMode);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PropertyNotification();
+
+  /**
+   * Sets Notify Mode, whether to notify if the condition is true
+   * and if the condition is false.
+   *
+   * @param[in] notifyMode The notification mode setting
+   */
+  void SetNotifyMode( NotifyMode notifyMode );
+
+  /**
+   * Check this property notification condition,
+   * and if true then dispatch notification.
+   * @param[in] bufferIndex The current update buffer index.
+   * @return Whether the validity of this notification has changed.
+   */
+  bool Check( BufferIndex bufferIndex );
+
+  /**
+   * Returns the validity of the last condition check
+   *
+   * @return the validity
+   */
+  bool GetValidity() const;
+
+protected:
+
+  /**
+   * Construct the PropertyNotification
+   * @param[in] object The event-object for a scene-graph object to inspect.
+   * @param[in] propertyIndex The index of a property provided by the object.
+   * @param[in] propertyType The type of property we're inspecting.
+   * @param[in] componentIndex Index to the component of a complex property such as a Vector
+   * @param[in] condition The condition type (e.g. LessThan, GreaterThan...)
+   * @param[in] arguments The arguments which accompany the condition.
+   * @param[in] notifyMode The notification mode setting
+   */
+  PropertyNotification(Object& object,
+                       Property::Index propertyIndex,
+                       Property::Type propertyType,
+                       int componentIndex,
+                       ConditionType condition,
+                       RawArgumentContainer& arguments,
+                       NotifyMode notifyMode);
+
+private:
+
+  /**
+   * Checks if bool is LessThan
+   * @param[in] value The value being examined.
+   * @param[in] arg The supplied arguments for the condition.
+   * @return Condition result (true if condition met, false if not)
+   */
+  static bool EvalFalse( const Dali::PropertyInput& value, Dali::Internal::PropertyNotification::RawArgumentContainer& arg );
+
+  // Undefined
+  PropertyNotification(const PropertyNotification&);
+
+  // Undefined
+  PropertyNotification& operator=(const PropertyNotification& rhs);
+
+protected:
+
+  Object* mObject;                              ///< Not owned by the property notification. Valid until ObjectDestroyed() is called.
+  Property::Index mPropertyIndex;               ///< The index of this property.
+  Property::Type mPropertyType;                 ///< The type of property this is.
+  const PropertyInputImpl* mProperty;           ///< The scene graph property
+  int mComponentIndex;                          ///< Used for accessing float components of Vector3/4
+  ConditionType mConditionType;                 ///< The ConditionType
+  RawArgumentContainer mArguments;              ///< The arguments.
+  bool mValid;                                  ///< Whether this property notification is currently valid or not.
+  NotifyMode mNotifyMode;                       ///< Whether to notify on invalid and/or valid
+  ConditionFunction mConditionFunction;         ///< The Condition Function pointer to be evaluated.
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROPERTY_NOTIFICATION_H__
diff --git a/dali/internal/update/common/uniform-map.cpp b/dali/internal/update/common/uniform-map.cpp
new file mode 100644 (file)
index 0000000..a1400e5
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "uniform-map.h"
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+UniformMap::UniformMap()
+{
+}
+
+UniformMap::~UniformMap()
+{
+  // Nothing to do - let the owner container delete the maps
+}
+
+void UniformMap::AddObserver( Observer& observer )
+{
+  bool foundObserver = false;
+  for( ObserversIter iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    if( *iter == &observer )
+    {
+      foundObserver = true;
+      break;
+    }
+  }
+  if( !foundObserver )
+  {
+    mObservers.PushBack( &observer );
+  }
+}
+
+void UniformMap::RemoveObserver( Observer& observer )
+{
+  for( ObserversIter iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    if( *iter == &observer )
+    {
+      mObservers.Erase(iter);
+      return;
+    }
+  }
+}
+
+void UniformMap::MappingChanged()
+{
+  for( ObserversIter iter = mObservers.Begin(); iter != mObservers.End(); ++iter )
+  {
+    Observer* observer = (*iter);
+    observer->UniformMappingsChanged( *this );
+  }
+}
+
+// @todo MESH_REWORK Benchmark and test
+// The uniform map can never grow beyond the limits of GL - so really, the
+// map size is likely to be small; if retaining an unsorted map proves to be
+// slow, then it should be changed to perform an insertion sort.
+void UniformMap::Add( UniformPropertyMapping* newMap )
+{
+  UniformPropertyMapping::Hash nameHash = CalculateHash( newMap->uniformName );
+
+  bool found = false;
+
+  for( UniformMapIter iter = mUniformMaps.Begin() ;
+       iter != mUniformMaps.End() ;
+       ++iter )
+  {
+    UniformPropertyMapping* map = *iter;
+    if( map->uniformNameHash == nameHash )
+    {
+      if( map->uniformName == newMap->uniformName )
+      {
+        found = true;
+        // Mapping already exists - update it.
+        map->propertyPtr = newMap->propertyPtr;
+        break;
+      }
+    }
+  }
+
+  if( found == false )
+  {
+    // Take ownership of the new map
+    mUniformMaps.PushBack(newMap);
+  }
+
+  MappingChanged();
+}
+
+void UniformMap::Remove( const std::string& uniformName )
+{
+  UniformPropertyMapping::Hash nameHash = CalculateHash( uniformName );
+
+  bool found=false;
+
+  for( UniformMapIter iter = mUniformMaps.Begin() ;
+       iter != mUniformMaps.End() ;
+       ++iter )
+  {
+    UniformPropertyMapping* map = *iter;
+    if( map->uniformNameHash == nameHash )
+    {
+      if( map->uniformName == uniformName )
+      {
+        mUniformMaps.Erase( iter );
+        found = true;
+        break;
+      }
+    }
+  }
+
+  if( found )
+  {
+    MappingChanged();
+  }
+}
+
+const PropertyInputImpl* UniformMap::Find( const std::string& uniformName )
+{
+  UniformPropertyMapping::Hash nameHash = CalculateHash( uniformName );
+
+  for( UniformMapIter iter = mUniformMaps.Begin() ;
+       iter != mUniformMaps.End() ;
+       ++iter )
+  {
+    UniformPropertyMapping* map = *iter;
+    if( map->uniformNameHash == nameHash )
+    {
+      if( map->uniformName == uniformName )
+      {
+        return map->propertyPtr;
+      }
+    }
+  }
+  return NULL;
+}
+
+unsigned int UniformMap::Count() const
+{
+  return mUniformMaps.Count();
+}
+
+const UniformPropertyMapping& UniformMap::operator[]( unsigned int index ) const
+{
+  return *mUniformMaps[index];
+}
+
+} // SceneGraph
+} // Internal
+} // Dali
diff --git a/dali/internal/update/common/uniform-map.h b/dali/internal/update/common/uniform-map.h
new file mode 100644 (file)
index 0000000..1814bb7
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_H
+#define DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/common/hash.h>
+#include <dali/internal/common/owner-container.h>
+
+#include <string>
+
+namespace Dali
+{
+namespace Internal
+{
+class PropertyInputImpl;
+
+namespace SceneGraph
+{
+
+/**
+ * The uniform map is used to map a uniform name to a property value.
+ */
+class UniformPropertyMapping
+{
+public:
+  typedef unsigned long Hash;
+
+  /**
+   * Constructor
+   */
+  UniformPropertyMapping( const std::string& theUniformName, const PropertyInputImpl* thePropertyPtr )
+  : propertyPtr( thePropertyPtr ),
+    uniformName( theUniformName ),
+    uniformNameHash( Dali::CalculateHash( theUniformName ) )
+  {
+  }
+
+  UniformPropertyMapping()
+  : propertyPtr( NULL ),
+    uniformName( "" ),
+    uniformNameHash( 0 )
+  {
+  }
+
+
+  const PropertyInputImpl* propertyPtr;
+  std::string uniformName;
+  Hash uniformNameHash;
+};
+
+/**
+ * The UniformMap class is used to map uniform names to property values. It is available
+ * in all of the classes responsible for rendering:
+ * Actor, Renderer, Geometry, PropertyBuffer, Material, Sampler, Shader.
+ *
+ * It can be observed for changes to the mapping table.
+ */
+class UniformMap
+{
+public:
+  class Observer
+  {
+  public:
+    virtual void UniformMappingsChanged(const UniformMap& mappings) = 0;
+  };
+
+  /**
+   * Constructor
+   */
+  UniformMap();
+
+  /**
+   * Destructor
+   */
+  ~UniformMap();
+
+  /**
+   * Add an observer that watches for changes in the mappings
+   */
+  void AddObserver( Observer& observer );
+
+  /**
+   * Remove an observer
+   */
+  void RemoveObserver( Observer& observer );
+
+  /**
+   * Add a map to the mappings table.
+   */
+  void Add( UniformPropertyMapping* map );
+
+  /**
+   * Remove a map from the mappings table
+   */
+  void Remove( const std::string& uniformName );
+
+  /**
+   * Find a property given the uniform name.
+   * @return The address of the property if it's in the map, or NULL otherwise.
+   */
+  const PropertyInputImpl* Find( const std::string& uniformName );
+
+  /**
+   * Get the count of uniforms in the map
+   * @return The number of uniform mappings
+   */
+  unsigned int Count() const;
+
+  /**
+   * @pre index must be in the range 0 :: Count()-1
+   * @param[in] index The index of the element to fetch
+   * @return reference to the element in the map
+   */
+  const UniformPropertyMapping& operator[]( unsigned int index ) const;
+
+private:
+  /**
+   * Helper to call the observers when the mappings have changed
+   */
+  void MappingChanged();
+
+private:
+  typedef OwnerContainer< UniformPropertyMapping* > UniformMapContainer;
+  typedef UniformMapContainer::Iterator UniformMapIter;
+  typedef Dali::Vector< Observer* > Observers;
+  typedef Observers::Iterator ObserversIter;
+
+  UniformMapContainer mUniformMaps; // Owner container of uniform maps
+
+  Observers mObservers;
+};
+
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_UNIFORM_MAP_H
diff --git a/dali/internal/update/controllers/render-message-dispatcher.cpp b/dali/internal/update/controllers/render-message-dispatcher.cpp
new file mode 100644 (file)
index 0000000..ec1a2eb
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderMessageDispatcher::RenderMessageDispatcher( RenderManager& renderManager, RenderQueue& renderQueue, const SceneGraphBuffers& buffers )
+: mRenderManager( renderManager ),
+  mRenderQueue( renderQueue ),
+  mBuffers( buffers )
+{
+}
+
+RenderMessageDispatcher::~RenderMessageDispatcher()
+{
+}
+
+void RenderMessageDispatcher::AddRenderer( Renderer& renderer )
+{
+  typedef MessageValue1< RenderManager, Renderer* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::AddRenderer, &renderer );
+}
+
+void RenderMessageDispatcher::RemoveRenderer( Renderer& renderer )
+{
+  typedef MessageValue1< RenderManager, Renderer* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::RemoveRenderer, &renderer );
+}
+
+void RenderMessageDispatcher::AddGeometry( RenderGeometry& renderGeometry )
+{
+  typedef MessageValue1< RenderManager, RenderGeometry* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::AddGeometry, &renderGeometry );
+}
+
+void RenderMessageDispatcher::RemoveGeometry( RenderGeometry& renderGeometry )
+{
+  typedef MessageValue1< RenderManager, RenderGeometry* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::RemoveGeometry, &renderGeometry );
+}
+
+void RenderMessageDispatcher::AddPropertyBuffer( RenderGeometry& renderGeometry, PropertyBufferDataProvider* propertyBuffer, GpuBuffer::Target target, GpuBuffer::Usage usage )
+{
+  typedef MessageValue4< RenderManager, RenderGeometry*, PropertyBufferDataProvider*, GpuBuffer::Target, GpuBuffer::Usage > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::AddPropertyBuffer, &renderGeometry, propertyBuffer, target, usage );
+}
+
+void RenderMessageDispatcher::RemovePropertyBuffer( RenderGeometry& renderGeometry, PropertyBufferDataProvider* propertyBuffer )
+{
+  typedef MessageValue2< RenderManager, RenderGeometry*, PropertyBufferDataProvider* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::RemovePropertyBuffer, &renderGeometry, propertyBuffer );
+}
+
+void RenderMessageDispatcher::AddRenderTracker( RenderTracker& renderTracker )
+{
+  typedef MessageValue1< RenderManager, RenderTracker* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::AddRenderTracker, &renderTracker );
+}
+
+void RenderMessageDispatcher::RemoveRenderTracker( RenderTracker& renderTracker )
+{
+  typedef MessageValue1< RenderManager, RenderTracker* > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mRenderQueue.ReserveMessageSlot( mBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mRenderManager, &RenderManager::RemoveRenderTracker, &renderTracker );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/controllers/render-message-dispatcher.h b/dali/internal/update/controllers/render-message-dispatcher.h
new file mode 100644 (file)
index 0000000..7980606
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_MESSAGE_DISPATCHER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_MESSAGE_DISPATCHER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/render/gl-resources/gpu-buffer.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class MessageBase;
+
+namespace SceneGraph
+{
+class Renderer;
+class RenderManager;
+class RenderQueue;
+class RenderTracker;
+class RenderGeometry;
+class PropertyBufferDataProvider;
+/**
+ * A utility class for sending messages to the render-thread.
+ */
+class RenderMessageDispatcher
+{
+public:
+
+  /**
+   * Constructor
+   */
+  RenderMessageDispatcher( RenderManager& renderManager, RenderQueue& renderQueue, const SceneGraphBuffers& buffers );
+
+  /**
+   * Destructor
+   */
+  virtual ~RenderMessageDispatcher();
+
+  /**
+   * Add a Renderer.
+   * @param[in] renderer The renderer to add.
+   * @post renderer ownership is transferred.
+   */
+  void AddRenderer( Renderer& renderer );
+
+  /**
+   * Remove a Renderer.
+   * @param[in] renderer The renderer to remove.
+   * @post renderer will be destroyed in the next Render.
+   */
+  void RemoveRenderer( Renderer& renderer );
+
+  /**
+   * Add a Geometry
+   * @param[in] renderGeometry The geometry to add.
+   * @post RenderGeometry ownership is transferred.
+   */
+  void AddGeometry( RenderGeometry& renderGeometry );
+
+  /**
+   * Remove a Geometry.
+   * @param[in] renderGeometry The geometry to remove.
+   * @post RenderGeometry will be destroyed in the next Render.
+   */
+  void RemoveGeometry( RenderGeometry& renderGeometry );
+
+  /**
+   * Add a PropertyBuffer.
+   * @param[in] renderGeometry The geometry
+   * @param[in] propertyBuffer The PropertyBuffer
+   * @param[in] target Specifies the type of the buffer
+   * @param[in] usage Specifies how will the buffer be used
+   */
+  void AddPropertyBuffer( RenderGeometry& renderGeometry, PropertyBufferDataProvider* propertyBuffer, GpuBuffer::Target target, GpuBuffer::Usage usage );
+
+  /**
+   * Remove a PropertyBuffer.
+   * @param[in] renderGeometry The geometry
+   * @param[in] propertyBuffer The PropertyBuffer
+   * @post PropertyBuffer will be destroyed in the next Render.
+   */
+  void RemovePropertyBuffer( RenderGeometry& renderGeometry, PropertyBufferDataProvider* propertyBuffer );
+
+  /**
+   * Add a Render tracker.
+   * @param[in] renderTracker The render tracker to add.
+   * @post ownership is transferred
+   */
+  void AddRenderTracker( RenderTracker& renderTracker );
+
+  /**
+   * Remove a Render tracker.
+   * @param[in] renderTracker The render tracker to add.
+   * @post render tracker will be destroyed in the next Render pass.
+   */
+  void RemoveRenderTracker( RenderTracker& renderTracker );
+
+private:
+
+  RenderManager& mRenderManager;
+  RenderQueue& mRenderQueue;
+
+  const SceneGraphBuffers& mBuffers;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDERER_DISPATCHER_H__
diff --git a/dali/internal/update/controllers/scene-controller-impl.cpp b/dali/internal/update/controllers/scene-controller-impl.cpp
new file mode 100644 (file)
index 0000000..eab7d85
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/controllers/scene-controller-impl.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+SceneControllerImpl::SceneControllerImpl( RenderMessageDispatcher& renderMessageDispatcher,
+                                          RenderQueue& renderQueue,
+                                          DiscardQueue& discardQueue,
+                                          TextureCache& textureCache,
+                                          CompleteStatusManager& completeStatusManager )
+: mRenderMessageDispatcher( renderMessageDispatcher ),
+  mRenderQueue( renderQueue ),
+  mDiscardQueue( discardQueue ),
+  mTextureCache( textureCache ),
+  mCompleteStatusManager( completeStatusManager )
+{
+}
+
+SceneControllerImpl::~SceneControllerImpl()
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/controllers/scene-controller-impl.h b/dali/internal/update/controllers/scene-controller-impl.h
new file mode 100644 (file)
index 0000000..059cbc1
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_IMPL_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_IMPL_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/controllers/scene-controller.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * concrete implementation of the scene controller interface
+ */
+class SceneControllerImpl: public SceneController
+{
+
+public:
+
+  /**
+   * Constructor
+   * @param[in] context  dali context
+   * @param[in] rendererDispatcher Used for passing ownership of renderers to the render-thread.
+   * @param[in] renderQueue  The renderQueue
+   * @param[in] discardQueue The discardQueue
+   * @param[in] completeStatusTracker The resource complete status tracker
+   * @param[in] defaultShader to use for renderable attachments
+   */
+  SceneControllerImpl( RenderMessageDispatcher& renderMessageDispatcher,
+                       RenderQueue& renderQueue,
+                       DiscardQueue& discardQueue,
+                       TextureCache& textureCache,
+                       CompleteStatusManager& completeStatusManager );
+
+  /**
+   * Destructor
+   */
+  virtual ~SceneControllerImpl();
+
+public:  // from SceneController
+
+  /**
+   * @copydoc SceneController::GetRenderMessageDispatcher()
+   */
+  virtual RenderMessageDispatcher& GetRenderMessageDispatcher() { return mRenderMessageDispatcher; }
+
+  /**
+   * @copydoc SceneController::GetRenderQueue()
+   */
+  virtual RenderQueue& GetRenderQueue() { return mRenderQueue; }
+
+  /**
+   * @copydoc SceneController::GetDiscardQueue()
+   */
+  virtual DiscardQueue& GetDiscardQueue() { return mDiscardQueue; }
+
+  /**
+   * @copydoc SceneController::GetTextureCache()
+   */
+  virtual TextureCache& GetTextureCache() { return mTextureCache; }
+
+  /**
+   * @copydoc SceneController::GetCompleteStatusManager()
+   */
+  virtual CompleteStatusManager& GetCompleteStatusManager() { return mCompleteStatusManager;  }
+
+private:
+
+  // Undefined copy constructor.
+  SceneControllerImpl( const SceneControllerImpl& );
+
+  // Undefined assignment operator.
+  SceneControllerImpl& operator=( const SceneControllerImpl& );
+
+private:
+
+  RenderMessageDispatcher& mRenderMessageDispatcher;    ///< Used for passing messages to the render-thread
+  RenderQueue&             mRenderQueue;           ///< render queue
+  DiscardQueue&            mDiscardQueue;          ///< discard queue
+  TextureCache&            mTextureCache;          ///< texture cache
+  CompleteStatusManager&   mCompleteStatusManager; ///< Complete Status manager
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_IMPL_H__
diff --git a/dali/internal/update/controllers/scene-controller.h b/dali/internal/update/controllers/scene-controller.h
new file mode 100644 (file)
index 0000000..247f273
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Internal
+{
+class CompleteStatusManager;
+
+namespace SceneGraph
+{
+
+class CameraController;
+class RenderMessageDispatcher;
+class RenderQueue;
+class DiscardQueue;
+class TextureCache;
+
+/**
+ * Abstract interface for the scene controller
+ */
+class SceneController
+{
+public:
+
+  /**
+   * Constructor
+   */
+  SceneController()
+  {
+  }
+
+  /**
+   * Destructor
+   */
+  virtual ~SceneController()
+  {
+  }
+
+  /**
+   * Return the render message dispatcher
+   * @return A reference to the render message dispatcher
+   */
+  virtual RenderMessageDispatcher& GetRenderMessageDispatcher() = 0;
+
+  /**
+   * Return the render queue
+   * @return A reference to the render queue
+   */
+  virtual RenderQueue& GetRenderQueue() = 0;
+
+  /**
+   * Return the discard queue
+   * @return A reference to the discard queue
+   */
+  virtual DiscardQueue& GetDiscardQueue() = 0;
+
+  /**
+   * Return the texture cache
+   * TODO: Remove this method when renderer's & shader's second stage initialization
+   * is done by RenderManager rather than by the attachments in the Update thread.
+   * DO NOT USE THIS IN THE UPDATE THREAD!
+   * @return A reference to the texture cache
+   */
+  virtual TextureCache& GetTextureCache() = 0;
+
+  /**
+   * Return the CompleteStatusManager
+   * @return a reference to the complete status manager
+   */
+  virtual CompleteStatusManager& GetCompleteStatusManager() = 0;
+
+private:
+
+  // Undefined copy constructor.
+  SceneController( const SceneController& );
+
+  // Undefined assignment operator.
+  SceneController& operator=( const SceneController& );
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_SCENE_CONTROLLER_H__
diff --git a/dali/internal/update/gestures/gesture-properties.h b/dali/internal/update/gestures/gesture-properties.h
new file mode 100644 (file)
index 0000000..4a277f2
--- /dev/null
@@ -0,0 +1,196 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_GESTURE_PROPERTIES_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_GESTURE_PROPERTIES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-types.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/event/common/property-input-impl.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * A template for a read only properties used by Gestures.
+ */
+template < class T >
+class GestureProperty : public PropertyInputImpl
+{
+public:
+
+  /**
+   * Create a read-only gesture property.
+   * @param [in] initialValue The initial value of the property.
+   */
+  GestureProperty( const T& initialValue )
+  : mValue( initialValue ),
+    mInputChanged( false )
+  {
+  }
+
+  /**
+   * Create a read-only gesture property.
+   */
+  GestureProperty()
+  : mValue(),
+    mInputChanged( false )
+  {
+  }
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~GestureProperty()
+  {
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::GetType()
+   */
+  virtual Dali::Property::Type GetType() const
+  {
+    return Dali::PropertyTypes::Get< T >();
+  }
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyBase::IsClean()
+   */
+  virtual bool IsClean() const
+  {
+    return !InputChanged();
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputInitialized()
+   */
+  virtual bool InputInitialized() const
+  {
+    // A constraint cannot use the property until it has been inherited (at least once).
+    return true;
+  }
+
+  /**
+   * @copydoc Dali::Internal::PropertyInputImpl::InputChanged()
+   * @note A constraint can only receive the inherited property from the previous frame.
+   */
+  virtual bool InputChanged() const
+  {
+    return mInputChanged;
+  }
+
+  /**
+   * @brief Resets mInputChanged back to false
+   */
+  void Reset()
+  {
+    mInputChanged = false;
+  }
+
+  /**
+   * Set the property value.
+   * @param[in] value The new property value.
+   */
+  void Set(const T& value)
+  {
+    mValue = value;
+    mInputChanged = true;
+  }
+
+  /**
+   * Get the property value.
+   * @return The property value.
+   */
+  const T& Get() const
+  {
+    return mValue;
+  }
+
+private:
+
+  // Undefined
+  GestureProperty(const GestureProperty& property);
+
+  // Undefined
+  GestureProperty& operator=(const GestureProperty& rhs);
+
+protected:
+
+  T mValue;             ///< The property value
+  bool mInputChanged:1; ///< Whether the property has been modified
+};
+
+/**
+ * A read only Vector2 property used by Gestures.
+ */
+class GesturePropertyVector2 : public GestureProperty< Vector2 >
+{
+public:
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~GesturePropertyVector2()
+  {
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetVector2()
+   */
+  virtual const Vector2& GetVector2( BufferIndex bufferIndex ) const
+  {
+    return mValue;
+  }
+};
+
+/**
+ * A read only bool property used by Gestures.
+ */
+class GesturePropertyBool : public GestureProperty< bool >
+{
+public:
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~GesturePropertyBool()
+  {
+  }
+
+  /**
+   * @copydoc Dali::PropertyInput::GetBoolean()
+   */
+  virtual const bool& GetBoolean( BufferIndex bufferIndex ) const
+  {
+    return mValue;
+  }
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_GESTURE_PROPERTIES_H__
diff --git a/dali/internal/update/gestures/pan-gesture-profiling.cpp b/dali/internal/update/gestures/pan-gesture-profiling.cpp
new file mode 100644 (file)
index 0000000..02044fd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/gestures/pan-gesture-profiling.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+void PanGestureProfiling::PrintData() const
+{
+  PrintData( mRawData,      "RAW" );
+  PrintData( mLatestData,   "LATEST" );
+  PrintData( mAveragedData, "AVERAGED" );
+}
+
+void PanGestureProfiling::PrintData( const PanPositionContainer& dataContainer, const char * const prefix ) const
+{
+  const PanPositionContainer::const_iterator endIter = dataContainer.end();
+  for ( PanPositionContainer::const_iterator iter = dataContainer.begin(); iter != endIter; ++iter )
+  {
+    DALI_LOG_UPDATE_STATUS( "%s, %u, %.2f, %.2f, displacement: %.2f, %.2f, velocity: %.2f, %.2f, state: %d\n", prefix, iter->time, iter->position.x, iter->position.y, iter->displacement.x, iter->displacement.y, iter->velocity.x, iter->velocity.y, iter->state );
+  }
+}
+
+void PanGestureProfiling::ClearData()
+{
+  mRawData.clear();
+  mLatestData.clear();
+  mAveragedData.clear();
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/gestures/pan-gesture-profiling.h b/dali/internal/update/gestures/pan-gesture-profiling.h
new file mode 100644 (file)
index 0000000..0ab89b1
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __DALI_INTERNAL_PAN_GESTURE_PROFILING_H__
+#define __DALI_INTERNAL_PAN_GESTURE_PROFILING_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+struct PanGestureProfiling
+{
+  struct Position
+  {
+    Position( unsigned int time, Vector2 position, Vector2 displacement, Vector2 velocity, int state )
+    : time( time ), position( position ), displacement( displacement ), velocity( velocity ), state( state )
+    {
+    }
+
+    unsigned int time;
+    Vector2 position;
+    Vector2 displacement;
+    Vector2 velocity;
+    int state;
+  };
+
+  typedef std::vector< PanGestureProfiling::Position > PanPositionContainer;
+
+  void PrintData() const;
+
+  void PrintData( const PanPositionContainer& dataContainer, const char * const prefix ) const;
+
+  void ClearData();
+
+  PanPositionContainer mRawData;
+  PanPositionContainer mLatestData;
+  PanPositionContainer mAveragedData;
+};
+
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_PAN_GESTURE_PROFILING_H__
diff --git a/dali/internal/update/gestures/scene-graph-pan-gesture.cpp b/dali/internal/update/gestures/scene-graph-pan-gesture.cpp
new file mode 100644 (file)
index 0000000..58be2b6
--- /dev/null
@@ -0,0 +1,1298 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+
+// EXTERNAL INCLUDES
+#include <cmath>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/gestures/pan-gesture-profiling.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+// TODO: Experimental - for changing in code only:
+const bool         TEST_TUNE_ENABLE_OVERSHOOT_PROTECTION   = false;
+
+// Internal defaults:
+const int          MAX_GESTURE_AGE                         = 200;    ///< maximum age of a gesture before disallowing its use in algorithm TODO: Possibly make this configurable.
+const float        ACCELERATION_THRESHOLD                  = 0.1f;   ///< minimum pan velocity change to trigger dynamic change of prediction amount.
+const float        OUTPUT_TIME_DIFFERENCE                  = ( 1000.0f / 60.0f ); ///< This is used to optionally override actual times if they make results worse.
+const float        ACCELERATION_SMOOTHING                  = 0.44f;  ///< Smoothes acceleration changes from one frame to another.
+const float        ACCELERATION_CAP                        = 0.0004f;///< Limits acceleration changes from one frame to another.
+
+// Defaults for Environment Variables:
+
+// Prediction Mode 1:
+const unsigned int DEFAULT_MAX_PREDICTION_AMOUNT           = 32;     ///< the upper bound of the range to clamp the prediction interpolation.
+const unsigned int DEFAULT_MIN_PREDICTION_AMOUNT           = 0;      ///< the lower bound of the range to clamp the prediction interpolation.
+const unsigned int DEFAULT_PREDICTION_AMOUNT_ADJUSTMENT    = 2;      ///< the amount of prediction interpolation to adjust (in milliseconds) each time when pan velocity changes.
+
+// Prediction Mode 2:
+const bool         DEFAULT_USE_ACTUAL_TIMES                = false;  ///< Disable to optionally override actual times if they make results worse.
+const int          DEFAULT_INTERPOLATION_TIME_RANGE        = 255;    ///< Time into past history (ms) to use points to interpolate the first point.
+const bool         DEFAULT_SCALAR_ONLY_PREDICTION_ENABLED  = false;  ///< If enabled, prediction is done using velocity alone (no integration or acceleration).
+const bool         DEFAULT_TWO_POINT_PREDICTION_ENABLED    = true;   ///< If enabled, a second interpolated point is predicted and combined with the first to get more stable values.
+const int          DEFAULT_TWO_POINT_PAST_INTERPOLATE_TIME = 42;     ///< The target time in the past to generate the second interpolated point.
+const float        DEFAULT_TWO_POINT_VELOCITY_BIAS         = 0.35f;  ///< The ratio of first and second interpolated points to use for velocity. 0.0f = 100% of first point. 1.0f = 100% of second point.
+const float        DEFAULT_TWO_POINT_ACCELERATION_BIAS     = 0.10f;  ///< The ratio of first and second interpolated points to use for acceleration. 0.0f = 100% of first point. 1.0f = 100% of second point.
+const int          DEFAULT_MULTITAP_SMOOTHING_RANGE        = 34;     ///< The range in time (ms) of points in the history to smooth the final output against.
+
+// Prediction Modes 1 & 2.
+const unsigned int DEFAULT_PREDICTION_AMOUNT[2]            = {     5,    57 }; ///< how much to interpolate pan position and displacement from last vsync time (in milliseconds)
+const float        DEFAULT_SMOOTHING_AMOUNT[2]             = { 0.25f, 0.23f }; ///< how much to smooth final result from last vsync time
+
+} // unnamed namespace
+
+const PanGesture::PredictionMode PanGesture::DEFAULT_PREDICTION_MODE = PanGesture::PREDICTION_NONE;
+const int PanGesture::NUM_PREDICTION_MODES = PanGesture::PREDICTION_2 + 1;
+
+const PanGesture::SmoothingMode PanGesture::DEFAULT_SMOOTHING_MODE = PanGesture::SMOOTHING_LAST_VALUE;
+const int PanGesture::NUM_SMOOTHING_MODES = PanGesture::SMOOTHING_MULTI_TAP + 1;
+
+PanGesture* PanGesture::New()
+{
+  return new PanGesture();
+}
+
+PanGesture::~PanGesture()
+{
+  delete mProfiling;
+}
+
+void PanGesture::AddGesture( const Dali::PanGesture& gesture )
+{
+  Dali::Mutex::ScopedLock lock( mMutex );
+  mGestures[ mWritePosition ] = gesture;
+
+  // Update our write position.
+  ++mWritePosition;
+  mWritePosition %= PAN_GESTURE_HISTORY;
+}
+
+void PanGesture::RemoveOldHistory(PanInfoHistory& panHistory, unsigned int currentTime, unsigned int maxAge, unsigned int minEvents)
+{
+  PanInfoHistoryConstIter endIter = panHistory.end();
+  PanInfoHistoryIter iter = panHistory.begin();
+  while( iter != endIter && panHistory.size() > minEvents)
+  {
+    PanInfo currentGesture = *iter;
+    if( currentTime < currentGesture.time + maxAge )
+    {
+      break;
+    }
+    iter = panHistory.erase(iter);
+    endIter = panHistory.end();
+  }
+
+  // dont want more than 5 previous predictions for smoothing
+  iter = mPredictionHistory.begin();
+  while( mPredictionHistory.size() > 1 && iter != mPredictionHistory.end() )
+  {
+    iter = mPredictionHistory.erase(iter);
+  }
+}
+
+void PanGesture::PredictionMode1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime)
+{
+  RemoveOldHistory(panHistory, lastVSyncTime, MAX_GESTURE_AGE, 0);
+  size_t panHistorySize = panHistory.size();
+  if( panHistorySize == 0 )
+  {
+    // cant do any prediction without a history
+    return;
+  }
+
+  PanInfoHistoryConstIter endIter = panHistory.end();
+  PanInfoHistoryIter iter = panHistory.begin();
+  Vector2 screenVelocity = gestureOut.screen.velocity;
+  Vector2 localVelocity = gestureOut.local.velocity;
+  Vector2 screenDisplacement = gestureOut.screen.displacement;
+  Vector2 localDisplacement = gestureOut.local.displacement;
+
+  bool havePreviousAcceleration = false;
+  bool previousVelocity = false;
+  float previousAccel = 0.0f;
+  unsigned int lastTime(0);
+
+  unsigned int interpolationTime = lastVSyncTime + mCurrentPredictionAmount;
+
+  if( interpolationTime > gestureOut.time ) // Guard against the rare case when gestureOut.time > (lastVSyncTime + mCurrentPredictionAmount)
+  {
+    interpolationTime -= gestureOut.time;
+  }
+  else
+  {
+    interpolationTime = 0u;
+  }
+
+  while( iter != endIter )
+  {
+    PanInfo currentGesture = *iter;
+    if( !previousVelocity )
+    {
+      // not yet set a previous velocity
+      screenVelocity = currentGesture.screen.velocity;
+      previousVelocity = true;
+      lastTime = currentGesture.time;
+      ++iter;
+      continue;
+    }
+    float previousValueWeight = (float)(MAX_GESTURE_AGE - (lastVSyncTime - lastTime)) / (float)MAX_GESTURE_AGE;
+    float velMag = currentGesture.screen.velocity.Length();
+    float velDiff = velMag - screenVelocity.Length();
+    float acceleration = 0.0f;
+
+    float time(0.f);
+    if (currentGesture.time > lastTime) // Guard against invalid timestamps
+    {
+      time = static_cast<float>( currentGesture.time - lastTime );
+    }
+    if( time > Math::MACHINE_EPSILON_1 )
+    {
+      acceleration = velDiff / time;
+    }
+
+    float newVelMag = 0.0f;
+    int currentInterpolation = interpolationTime;
+    if( !havePreviousAcceleration )
+    {
+      newVelMag =  velMag;
+      havePreviousAcceleration = true;
+    }
+    else
+    {
+      newVelMag = velMag + (((acceleration * (1.0f - previousValueWeight)) + (previousAccel * previousValueWeight)) * currentInterpolation);
+    }
+    float velMod = 1.0f;
+    if( velMag > Math::MACHINE_EPSILON_1 )
+    {
+      velMod = newVelMag / velMag;
+    }
+    gestureOut.screen.velocity = currentGesture.screen.velocity * velMod;
+    gestureOut.local.velocity = currentGesture.local.velocity * velMod;
+    screenDisplacement = gestureOut.screen.displacement + (gestureOut.screen.velocity * interpolationTime);
+    localDisplacement = gestureOut.local.displacement + (gestureOut.local.velocity * interpolationTime);
+    screenVelocity = currentGesture.screen.velocity;
+    localVelocity = currentGesture.local.velocity;
+    previousAccel = acceleration;
+    ++iter;
+  }
+  // gestureOut's position is currently equal to the last event's position and its displacement is equal to last frame's total displacement
+  // add interpolated distance and position to current
+  // work out interpolated velocity
+  gestureOut.screen.position = (gestureOut.screen.position - gestureOut.screen.displacement) + screenDisplacement;
+  gestureOut.local.position = (gestureOut.local.position - gestureOut.local.displacement) + localDisplacement;
+  gestureOut.screen.displacement = screenDisplacement;
+  gestureOut.local.displacement = localDisplacement;
+  gestureOut.time += interpolationTime;
+}
+
+void PanGesture::BlendPoints( PanInfo& gesture, PanInfo& lastGesture, float blendValue )
+{
+  gesture.screen.position -= ( gesture.screen.position - lastGesture.screen.position ) * 0.5f * ( 1.0f - blendValue );
+  gesture.local.position -= ( gesture.local.position - lastGesture.local.position ) * 0.5f * ( 1.0f - blendValue );
+  // Make current displacement relative to previous update-frame now.
+  gesture.screen.displacement = gesture.screen.position - lastGesture.screen.position;
+  gesture.local.displacement = gesture.local.position - lastGesture.local.position;
+  // Calculate velocity relative to previous update-frame
+  float timeDifference( gesture.time - lastGesture.time );
+  gesture.screen.velocity = gesture.screen.displacement / timeDifference;
+  gesture.local.velocity = gesture.local.displacement / timeDifference;
+}
+
+bool PanGesture::ReadGestures( FrameGestureInfo& info, unsigned int currentTimestamp )
+{
+  unsigned int previousReadPosition = 0;
+  bool eventFound = false;
+  info.frameGesture = mLastUnmodifiedGesture;
+
+  while( mReadPosition != mWritePosition )
+  {
+    // Copy the gesture first
+    PanInfo currentGesture( mGestures[mReadPosition] );
+
+    if( mProfiling )
+    {
+      mProfiling->mRawData.push_back( PanGestureProfiling::Position( currentGesture.time, currentGesture.screen.position, currentGesture.screen.displacement, currentGesture.screen.velocity, currentGesture.state ) );
+    }
+    info.frameGesture.local.position = currentGesture.local.position;
+    info.frameGesture.local.velocity = currentGesture.local.velocity;
+    info.frameGesture.screen.position = currentGesture.screen.position;
+    info.frameGesture.screen.velocity = currentGesture.screen.velocity;
+
+    if( info.eventsThisFrame > 0 )
+    {
+      info.acceleration = currentGesture.screen.velocity.Length() - mGestures[previousReadPosition].screen.velocity.Length();
+    }
+
+    if( !eventFound )
+    {
+      info.frameGesture.local.displacement = currentGesture.local.displacement;
+      info.frameGesture.screen.displacement = currentGesture.screen.displacement;
+      eventFound = true;
+    }
+    else
+    {
+      info.frameGesture.local.displacement += currentGesture.local.displacement;
+      info.frameGesture.screen.displacement += currentGesture.screen.displacement;
+    }
+    info.frameGesture.time = currentGesture.time;
+
+    // add event to history
+    mPanHistory.push_back( currentGesture );
+    if( currentGesture.state == Gesture::Started )
+    {
+      info.justStarted = true;
+      // clear just finished as we have started new pan
+      info.justFinished = false;
+    }
+    info.justFinished |= ( currentGesture.state == Gesture::Finished || currentGesture.state == Gesture::Cancelled );
+
+    // Update our read position.
+    previousReadPosition = mReadPosition;
+    ++info.eventsThisFrame;
+    ++mReadPosition;
+    mReadPosition %= PAN_GESTURE_HISTORY;
+  }
+  // This code does not determine if the data will be used.
+  return false;
+}
+
+bool PanGesture::ReadAndResampleGestures( FrameGestureInfo& info, unsigned int currentTimestamp )
+{
+  PanInfo lastReadGesture;
+  Dali::Mutex::ScopedLock lock( mMutex );
+  while( mReadPosition != mWritePosition )
+  {
+    // Copy the gesture first
+    lastReadGesture = mGestures[mReadPosition];
+    if( mProfiling )
+    {
+      mProfiling->mRawData.push_back( PanGestureProfiling::Position( lastReadGesture.time, lastReadGesture.screen.position,
+          lastReadGesture.screen.displacement, lastReadGesture.screen.velocity, lastReadGesture.state ) );
+    }
+
+    info.frameGesture.screen.position += lastReadGesture.screen.position;
+    info.frameGesture.local.position += lastReadGesture.local.position;
+    info.frameGesture.screen.velocity += lastReadGesture.screen.velocity;
+    info.frameGesture.local.velocity += lastReadGesture.local.velocity;
+
+    if( lastReadGesture.state == Gesture::Started )
+    {
+      // Clear just finished as we have started new pan.
+      info.justFinished = false;
+      info.justStarted = true;
+    }
+    else
+    {
+      info.justFinished |= ( lastReadGesture.state == Gesture::Finished || lastReadGesture.state == Gesture::Cancelled );
+    }
+
+    // Add event to history
+    mPanHistory.push_back( lastReadGesture );
+
+    // Update our read position.
+    ++info.eventsThisFrame;
+    ++mReadPosition;
+    mReadPosition %= PAN_GESTURE_HISTORY;
+  }
+
+  bool updateProperties = false;
+  if( info.eventsThisFrame > 0 )
+  {
+    // Some events were read this frame.
+    mTargetGesture = lastReadGesture;
+
+    if( info.eventsThisFrame > 1 )
+    {
+      info.frameGesture.screen.position /= info.eventsThisFrame;
+      info.frameGesture.local.position /= info.eventsThisFrame;
+      info.frameGesture.screen.velocity /= info.eventsThisFrame;
+      info.frameGesture.local.velocity /= info.eventsThisFrame;
+
+      info.frameGesture.screen.displacement = info.frameGesture.screen.position - mLastGesture.screen.position;
+      info.frameGesture.local.displacement = info.frameGesture.local.position - mLastGesture.local.position;
+
+      mNotAtTarget = true;
+    }
+    else
+    {
+      info.frameGesture.screen.displacement = lastReadGesture.screen.displacement;
+      info.frameGesture.local.displacement = lastReadGesture.local.displacement;
+    }
+
+    info.frameGesture.time = currentTimestamp;
+
+    updateProperties = true;
+  }
+  else
+  {
+    // 0 Events this frame.
+    if( mNotAtTarget )
+    {
+      mNotAtTarget = false;
+      info.frameGesture = mTargetGesture;
+      updateProperties = true;
+    }
+    else
+    {
+      info.frameGesture = mLastGesture;
+    }
+  }
+
+  return updateProperties;
+}
+
+bool PanGesture::UpdateProperties( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
+{
+  if( mPredictionMode == PREDICTION_2 )
+  {
+    // TODO: Have the two prediction modes share more behavior so some parts of mode 2 can
+    // be used with mode 1 etc. Needs code moving and more importantly testing.
+    return NewAlgorithm( lastVSyncTime, nextVSyncTime );
+  }
+
+  if( !mInGesture )
+  {
+    // clear current pan history
+    mPanHistory.clear();
+    mPredictionHistory.clear();
+  }
+
+  FrameGestureInfo frameInfo;
+  bool updateProperties = false;
+
+  // Read input data.
+  // If we are using a form of prediction, read all the input as-is.
+  if( mPredictionMode != PREDICTION_NONE )
+  {
+    // Read input required for prediction algorithms.
+    updateProperties = ReadGestures( frameInfo, lastVSyncTime );
+  }
+  else
+  {
+    // Read and resample input.
+    updateProperties = ReadAndResampleGestures( frameInfo, lastVSyncTime );
+  }
+
+  PanInfo frameGesture = frameInfo.frameGesture;
+  PanInfo unmodifiedGesture = frameGesture;
+
+  // Process input data.
+  mInGesture |= frameInfo.justStarted;
+  if( mInGesture )
+  {
+    // Profiling.
+    if( mProfiling )
+    {
+      mProfiling->mLatestData.push_back( PanGestureProfiling::Position( lastVSyncTime, frameGesture.screen.position,
+          frameGesture.screen.displacement, frameGesture.screen.velocity, frameGesture.state ) );
+    }
+
+    // Perform prediction.
+    if( mPredictionMode == PREDICTION_1 )
+    {
+      // Dynamically change the prediction amount according to the pan velocity acceleration.
+      if( !frameInfo.justStarted )
+      {
+        if( frameInfo.eventsThisFrame <= 1 )
+        {
+          frameInfo.acceleration = frameGesture.screen.velocity.Length() - mLastUnmodifiedGesture.screen.velocity.Length();
+        }
+
+        // Ignore tiny velocity fluctuation to avoid unnecessary prediction amount change
+        if( fabsf( frameInfo.acceleration ) > ACCELERATION_THRESHOLD )
+        {
+          mCurrentPredictionAmount += mPredictionAmountAdjustment * ( frameInfo.acceleration > Math::MACHINE_EPSILON_0 ? 1.0f : -1.0f );
+          if( mCurrentPredictionAmount > mMaxPredictionAmount + mPredictionAmountAdjustment ) // Guard against unsigned int overflow
+          {
+            mCurrentPredictionAmount = 0;
+          }
+        }
+      }
+      else
+      {
+        if( !mPredictionAmountOverridden )
+        {
+          // If the prediction amount has not been modified, default to the correct amount for this algorithm.
+          mPredictionAmount = DEFAULT_PREDICTION_AMOUNT[0];
+        }
+        mCurrentPredictionAmount = mPredictionAmount; // Reset the prediction amount for each new gesture
+      }
+
+      mCurrentPredictionAmount = std::max( mMinPredictionAmount, std::min( mCurrentPredictionAmount, mMaxPredictionAmount ) );
+
+      // Calculate the delta of positions before the prediction
+      Vector2 deltaPosition = frameGesture.screen.position - mLastUnmodifiedGesture.screen.position;
+
+      // Make latest gesture equal to current gesture before interpolation
+      PredictionMode1( frameInfo.eventsThisFrame, frameGesture, mPanHistory, lastVSyncTime, nextVSyncTime );
+
+      // Calculate the delta of positions after the prediction.
+      Vector2 deltaPredictedPosition = frameGesture.screen.position - mLastGesture.screen.position;
+
+      // If the change in the prediction has a different sign than the change in the actual position,
+      // there is overshot (i.e. the current prediction is too large). Return the previous prediction
+      // to give the user's finger a chance to catch up with where we have panned to.
+      bool overshotXAxis = false;
+      bool overshotYAxis = false;
+      if( (deltaPosition.x > Math::MACHINE_EPSILON_0 && deltaPredictedPosition.x < Math::MACHINE_EPSILON_0 )
+       || (deltaPosition.x < Math::MACHINE_EPSILON_0 && deltaPredictedPosition.x > Math::MACHINE_EPSILON_0 ) )
+      {
+        overshotXAxis = true;
+        frameGesture.screen.position.x = mLastGesture.screen.position.x;
+      }
+
+      if( (deltaPosition.y > Math::MACHINE_EPSILON_0 && deltaPredictedPosition.y < Math::MACHINE_EPSILON_0 )
+       || (deltaPosition.y < Math::MACHINE_EPSILON_0 && deltaPredictedPosition.y > Math::MACHINE_EPSILON_0 ) )
+      {
+        overshotYAxis = true;
+        frameGesture.screen.position.y = mLastGesture.screen.position.y;
+      }
+
+      // If there is overshot in one axis, reduce the possible overshot in the other axis,
+      // and reduce the prediction amount so that it doesn't overshoot as easily next time.
+      if(overshotXAxis || overshotYAxis)
+      {
+        mCurrentPredictionAmount -= mPredictionAmountAdjustment;
+        if( mCurrentPredictionAmount > mMaxPredictionAmount + mPredictionAmountAdjustment ) // Guard against unsigned int overflow
+        {
+          mCurrentPredictionAmount = 0;
+        }
+        mCurrentPredictionAmount = std::max( mMinPredictionAmount, std::min( mCurrentPredictionAmount, mMaxPredictionAmount ) );
+
+        if( overshotXAxis && !overshotYAxis )
+        {
+          frameGesture.screen.position.y = ( mLastGesture.screen.position.y + frameGesture.screen.position.y ) * 0.5f;
+        }
+
+        if( overshotYAxis && !overshotXAxis )
+        {
+          frameGesture.screen.position.x = ( mLastGesture.screen.position.x + frameGesture.screen.position.x ) * 0.5f;
+        }
+      }
+
+      updateProperties = true;
+    }
+
+    // Perform smoothing.
+    switch( mSmoothingMode )
+    {
+      case SMOOTHING_NONE:
+      case SMOOTHING_MULTI_TAP:
+      {
+        // No smoothing
+        // TODO: Old algorithm to be able to use multitap smoothing.
+        break;
+      }
+      case SMOOTHING_LAST_VALUE:
+      {
+        if( !frameInfo.justStarted )
+        {
+          if( !mSmoothingAmountOverridden )
+          {
+            // If the smoothing amount has not been modified, default to the correct amount for this algorithm.
+            mSmoothingAmount = DEFAULT_SMOOTHING_AMOUNT[0];
+          }
+          BlendPoints( frameGesture, mLastGesture, mSmoothingAmount );
+        }
+        break;
+      }
+    }
+
+    if( updateProperties )
+    {
+      // only update properties if event received
+      // set latest gesture to raw pan info with unchanged time
+      mPanning.Set( mInGesture & !frameInfo.justFinished );
+      mScreenPosition.Set( frameGesture.screen.position );
+      mScreenDisplacement.Set( frameGesture.screen.displacement );
+      mScreenVelocity.Set( frameGesture.screen.velocity );
+      mLocalPosition.Set( frameGesture.local.position );
+      mLocalDisplacement.Set( frameGesture.local.displacement );
+      mLocalVelocity.Set( frameGesture.local.velocity );
+    }
+
+    if( mProfiling )
+    {
+      mProfiling->mAveragedData.push_back( PanGestureProfiling::Position( frameGesture.time, frameGesture.screen.position,
+          frameGesture.screen.displacement, frameGesture.screen.velocity, frameGesture.state ) );
+    }
+  }
+
+  mLastGesture = frameGesture;
+  mLastUnmodifiedGesture = unmodifiedGesture;
+
+  mInGesture &= ~frameInfo.justFinished;
+  if( mProfiling && frameInfo.justFinished )
+  {
+    mProfiling->PrintData();
+    mProfiling->ClearData();
+  }
+
+  return updateProperties;
+}
+
+const GesturePropertyBool& PanGesture::GetPanningProperty() const
+{
+  return mPanning;
+}
+
+const GesturePropertyVector2& PanGesture::GetScreenPositionProperty() const
+{
+  return mScreenPosition;
+}
+
+const GesturePropertyVector2& PanGesture::GetScreenVelocityProperty() const
+{
+  return mScreenVelocity;
+}
+
+const GesturePropertyVector2& PanGesture::GetScreenDisplacementProperty() const
+{
+  return mScreenDisplacement;
+}
+
+const GesturePropertyVector2& PanGesture::GetLocalPositionProperty() const
+{
+  return mLocalPosition;
+}
+
+const GesturePropertyVector2& PanGesture::GetLocalDisplacementProperty() const
+{
+  return mLocalDisplacement;
+}
+
+const GesturePropertyVector2& PanGesture::GetLocalVelocityProperty() const
+{
+  return mLocalVelocity;
+}
+
+void PanGesture::SetPredictionMode(PredictionMode mode)
+{
+  mPredictionMode = mode;
+}
+
+void PanGesture::SetPredictionAmount(unsigned int amount)
+{
+  mPredictionAmount = amount;
+  mPredictionAmountOverridden = true;
+}
+
+void PanGesture::SetMaximumPredictionAmount(unsigned int amount)
+{
+  mMaxPredictionAmount = amount;
+}
+
+void PanGesture::SetMinimumPredictionAmount(unsigned int amount)
+{
+  mMinPredictionAmount = amount;
+}
+
+void PanGesture::SetPredictionAmountAdjustment(unsigned int amount)
+{
+  mPredictionAmountAdjustment = amount;
+}
+
+void PanGesture::SetSmoothingMode(SmoothingMode mode)
+{
+  mSmoothingMode = mode;
+}
+
+void PanGesture::SetSmoothingAmount(float amount)
+{
+  mSmoothingAmount = amount;
+  mSmoothingAmountOverridden = true;
+}
+
+void PanGesture::SetUseActualTimes( bool value )
+{
+  mUseActualTimes = value;
+}
+
+void PanGesture::SetInterpolationTimeRange( int value )
+{
+  mInterpolationTimeRange = value;
+}
+
+void PanGesture::SetScalarOnlyPredictionEnabled( bool value )
+{
+  mScalarOnlyPredictionEnabled = value;
+}
+
+void PanGesture::SetTwoPointPredictionEnabled( bool value )
+{
+  mTwoPointPredictionEnabled = value;
+}
+
+void PanGesture::SetTwoPointInterpolatePastTime( int value )
+{
+  mTwoPointPastInterpolateTime = value;
+}
+
+void PanGesture::SetTwoPointVelocityBias( float value )
+{
+  mTwoPointVelocityBias = value;
+}
+
+void PanGesture::SetTwoPointAccelerationBias( float value )
+{
+  mTwoPointAccelerationBias = value;
+}
+
+void PanGesture::SetMultitapSmoothingRange( int value )
+{
+  mMultiTapSmoothingRange = value;
+}
+
+void PanGesture::EnableProfiling()
+{
+  if( !mProfiling )
+  {
+    mProfiling = new PanGestureProfiling();
+  }
+}
+
+void PanGesture::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  mScreenPosition.Reset();
+  mScreenDisplacement.Reset();
+  mLocalPosition.Reset();
+  mLocalDisplacement.Reset();
+  mPanning.Reset();
+}
+
+PanGesture::PanGesture()
+: mGestures(),
+  mWritePosition( 0 ),
+  mReadPosition( 0 ),
+  mNotAtTarget( false ),
+  mInGesture( false ),
+  mPredictionAmountOverridden( false ),
+  mSmoothingAmountOverridden( false ),
+  mProfiling( NULL ),
+
+  // Set environment variable defaults:
+  mPredictionMode( DEFAULT_PREDICTION_MODE ),
+  mPredictionAmount( DEFAULT_PREDICTION_AMOUNT[0] ),
+  mCurrentPredictionAmount( DEFAULT_PREDICTION_AMOUNT[0] ),
+  mMaxPredictionAmount( DEFAULT_MAX_PREDICTION_AMOUNT ),
+  mMinPredictionAmount( DEFAULT_MIN_PREDICTION_AMOUNT ),
+  mPredictionAmountAdjustment( DEFAULT_PREDICTION_AMOUNT_ADJUSTMENT ),
+  mSmoothingMode( DEFAULT_SMOOTHING_MODE ),
+  mSmoothingAmount( DEFAULT_SMOOTHING_AMOUNT[0] ),
+  mUseActualTimes( DEFAULT_USE_ACTUAL_TIMES ),
+  mInterpolationTimeRange( DEFAULT_INTERPOLATION_TIME_RANGE ),
+  mScalarOnlyPredictionEnabled( DEFAULT_SCALAR_ONLY_PREDICTION_ENABLED ),
+  mTwoPointPredictionEnabled( DEFAULT_TWO_POINT_PREDICTION_ENABLED ),
+  mTwoPointPastInterpolateTime( DEFAULT_TWO_POINT_PAST_INTERPOLATE_TIME ),
+  mTwoPointVelocityBias( DEFAULT_TWO_POINT_VELOCITY_BIAS ),
+  mTwoPointAccelerationBias( DEFAULT_TWO_POINT_ACCELERATION_BIAS ),
+  mMultiTapSmoothingRange( DEFAULT_MULTITAP_SMOOTHING_RANGE )
+{
+
+}
+
+// Prediction mode 2 related code and functions follow:
+
+unsigned int PanGesture::ReadFrameEvents()
+{
+  unsigned int eventsThisFrame;
+  // Copy the events into a linear buffer while holding the mutex.
+  // This is so the lock is not held while any processing is done.
+  Dali::Mutex::ScopedLock lock( mMutex );
+  for( eventsThisFrame = 0; mReadPosition != mWritePosition; ++eventsThisFrame )
+  {
+    mReadGestures[ eventsThisFrame ] = mGestures[ mReadPosition ];
+    ++mReadPosition;
+    mReadPosition %= PAN_GESTURE_HISTORY;
+  }
+  return eventsThisFrame;
+}
+
+// TODO: eventsThisFrame parameter can be removed if we use a smarter container.
+bool PanGesture::InputRateConversion( PanInfo& rateConvertedGesture, unsigned int eventsThisFrame,
+    unsigned int currentFrameTime, unsigned int lastFrameTime, bool& justStarted, bool& justFinished )
+{
+  // TODO: Lots of variables on the stack. Needs optimizing.
+  PanInfo readGesture;
+  PanInfo firstReadGesture;
+  unsigned int eventsKeptThisFrame = 0;
+
+  for( unsigned int readPosition = 0; readPosition < eventsThisFrame; ++readPosition )
+  {
+    // Copy the gesture first
+    readGesture = mReadGestures[ readPosition ];
+
+    if( mProfiling )
+    {
+      mProfiling->mRawData.push_back( PanGestureProfiling::Position( readGesture.time, readGesture.screen.position,
+          readGesture.screen.displacement, readGesture.screen.velocity, readGesture.state ) );
+    }
+
+    if( readGesture.state == Gesture::Started )
+    {
+      // Clear pan data.
+      mPanHistory.clear();
+      mPredictionHistory.clear();
+      mLastAcceleration.local = Vector2::ZERO;
+      mLastAcceleration.screen = Vector2::ZERO;
+      mLastInterpolatedAcceleration.local = Vector2::ZERO;
+      mLastInterpolatedAcceleration.screen = Vector2::ZERO;
+      mLastInitialAcceleration.local = Vector2::ZERO;
+      mLastInitialAcceleration.screen = Vector2::ZERO;
+      PanInfo startInfo;
+      mLastGesture = startInfo;
+      mLastSecondInterpolatedPoint = startInfo;
+      mLastPredictedPoint = startInfo;
+      mLastFrameReadGesture = startInfo;
+      rateConvertedGesture = startInfo;
+      firstReadGesture = readGesture;
+      eventsKeptThisFrame = 0;
+      mNotAtTarget = false;
+      justFinished = false;
+      justStarted = true;
+      mInGesture = true;
+
+      if( !mPredictionAmountOverridden )
+      {
+        // If the prediction amount has not been modified, default to the correct amount for this algorithm.
+        mPredictionAmount = DEFAULT_PREDICTION_AMOUNT[1];
+      }
+      mCurrentPredictionAmount = mPredictionAmount;
+    }
+    else
+    {
+      justFinished |= ( readGesture.state == Gesture::Finished || readGesture.state == Gesture::Cancelled );
+    }
+
+    rateConvertedGesture.screen.position += readGesture.screen.position;
+    rateConvertedGesture.local.position += readGesture.local.position;
+    rateConvertedGesture.screen.velocity += readGesture.screen.velocity;
+    rateConvertedGesture.local.velocity += readGesture.local.velocity;
+    rateConvertedGesture.screen.displacement += readGesture.screen.displacement;
+    rateConvertedGesture.local.displacement += readGesture.local.displacement;
+
+    ++eventsKeptThisFrame;
+  }
+
+  bool storeGesture = false;
+  if( eventsKeptThisFrame > 0 )
+  {
+    // Some events were read this frame.
+    if( eventsKeptThisFrame > 1 )
+    {
+      float eventDivisor( eventsKeptThisFrame );
+      rateConvertedGesture.screen.position /= eventDivisor;
+      rateConvertedGesture.local.position /= eventDivisor;
+      rateConvertedGesture.screen.velocity /= eventDivisor;
+      rateConvertedGesture.local.velocity /= eventDivisor;
+      rateConvertedGesture.screen.displacement /= eventDivisor;
+      rateConvertedGesture.local.displacement /= eventDivisor;
+
+      mTargetGesture = readGesture;
+      mNotAtTarget = true;
+    }
+    else
+    {
+      mNotAtTarget = false;
+    }
+
+    rateConvertedGesture.time = currentFrameTime;
+    storeGesture = true;
+  }
+  else
+  {
+    // We did not get any event this frame.
+    // If we just started (or aren't in a gesture), exit.
+    if( !mInGesture || justStarted )
+    {
+      // We cannot guess what the event could be as we have no other events to base the guess from.
+      return false;
+    }
+
+    // As we are currently in a gesture, we can estimate an event.
+    readGesture = mLastFrameReadGesture;
+    readGesture.time = currentFrameTime;
+
+    // Take the last event, halve the acceleration, and use that.
+    const float accelerationDegrade = 2.0f;
+    Vector2 degradedAccelerationLocal( mLastAcceleration.local /= accelerationDegrade );
+    Vector2 degradedAccelerationScreen( mLastAcceleration.screen /= accelerationDegrade );
+
+    float outputTimeGranularity( GetDivisibleTimeDifference( currentFrameTime, lastFrameTime, 1.0f, OUTPUT_TIME_DIFFERENCE ) );
+
+    readGesture.local.velocity = degradedAccelerationLocal * outputTimeGranularity;
+    readGesture.local.displacement = readGesture.local.velocity * outputTimeGranularity;
+    readGesture.local.position = mLastFrameReadGesture.local.position + readGesture.local.displacement;
+    readGesture.screen.velocity = degradedAccelerationScreen * outputTimeGranularity;
+    readGesture.screen.displacement = readGesture.screen.velocity * outputTimeGranularity;
+    readGesture.screen.position = mLastFrameReadGesture.screen.position + readGesture.screen.displacement;
+
+    rateConvertedGesture = readGesture;
+    eventsKeptThisFrame = 1;
+    storeGesture = true;
+  }
+
+  if( eventsKeptThisFrame > 0 )
+  {
+    // Store last read gesture.
+    readGesture.time = currentFrameTime;
+    mLastFrameReadGesture = readGesture;
+
+    if( eventsKeptThisFrame > 2 )
+    {
+      DALI_LOG_WARNING( "Got events this frame:%d (more than 2 will compromise result)\n", eventsKeptThisFrame );
+    }
+  }
+
+  if( storeGesture )
+  {
+    // Store final converted result.
+    mPanHistory.push_back( rateConvertedGesture );
+  }
+  return true;
+}
+
+bool PanGesture::InterpolatePoint( PanInfoHistory& history, unsigned int currentTime, unsigned int targetTime, unsigned int range,
+      PanInfo& outPoint, RelativeVectors& acceleration, int outputTimeGranularity, bool eraseUnused )
+{
+  unsigned int discardInputBufferTime = targetTime + range;
+  unsigned int maxHistoryTime = targetTime - range;
+  unsigned int tapsUsed = 0;
+  outPoint.time = targetTime;
+  float divisor = 0.0f;
+  float accelerationDivisor = 0.0f;
+  PanInfoHistoryIter historyBegin = history.begin();
+  PanInfoHistoryIter lastIt = history.end();
+  bool pointGenerated = false;
+  RelativeVectors newAcceleration;
+
+  // Iterate through point history to perform interpolation.
+  for( PanInfoHistoryIter it = historyBegin; it != history.end(); )
+  {
+    unsigned int gestureTime = it->time;
+
+    if( gestureTime < maxHistoryTime )
+    {
+      // Too far in the past, discard.
+      // Clean history as we go (if requested).
+      if( eraseUnused )
+      {
+        it = history.erase( it );
+      }
+      else
+      {
+        ++it;
+        continue;
+      }
+    }
+    else
+    {
+      if( gestureTime > discardInputBufferTime )
+      {
+        // Too far in the future, discard (and finish).
+        break;
+      }
+
+      float timeDelta( static_cast<float>( abs( int( targetTime - gestureTime ) ) ) );
+      // Handle low time deltas.
+      if( timeDelta < 1.0f )
+      {
+        timeDelta = 1.0f;
+      }
+
+      outPoint.local.position += it->local.position / timeDelta;
+      outPoint.screen.position += it->screen.position / timeDelta;
+      outPoint.local.velocity += it->local.velocity / timeDelta;
+      outPoint.screen.velocity += it->screen.velocity / timeDelta;
+      outPoint.local.displacement += it->local.displacement / timeDelta;
+      outPoint.screen.displacement += it->screen.displacement / timeDelta;
+
+      divisor += 1.0f / timeDelta;
+
+      // Acceleration requires a previous point.
+      if( lastIt != history.end() )
+      {
+        // Time delta of input.
+        float timeDifference( GetDivisibleTimeDifference( it->time, lastIt->time, 1.0f, OUTPUT_TIME_DIFFERENCE ) );
+
+        newAcceleration.local += ( ( it->local.velocity - lastIt->local.velocity ) / timeDifference ) / timeDelta;
+        newAcceleration.screen += ( ( it->screen.velocity - lastIt->screen.velocity ) / timeDifference ) / timeDelta;
+
+        accelerationDivisor += 1.0f / timeDelta;
+      }
+
+      tapsUsed++;
+      lastIt = it;
+      ++it;
+    }
+  }
+
+  // Divide results by their respective divisors.
+  if( tapsUsed > 0 )
+  {
+    if( divisor > 0.0f )
+    {
+      outPoint.local.position /= divisor;
+      outPoint.screen.position /= divisor;
+      outPoint.local.velocity /= divisor;
+      outPoint.screen.velocity /= divisor;
+      outPoint.local.displacement /= divisor;
+      outPoint.screen.displacement /= divisor;
+    }
+
+    if( tapsUsed > 1 )
+    {
+      if( accelerationDivisor > 0.0f )
+      {
+        newAcceleration.local /= accelerationDivisor;
+        newAcceleration.screen /= accelerationDivisor;
+      }
+
+      float accelerationSmoothing( ACCELERATION_SMOOTHING );
+      newAcceleration.local = ( acceleration.local * accelerationSmoothing ) + ( newAcceleration.local * ( 1.0f - accelerationSmoothing ) );
+      newAcceleration.screen = ( acceleration.screen * accelerationSmoothing ) + ( newAcceleration.screen * ( 1.0f - accelerationSmoothing ) );
+    }
+    else
+    {
+      // If we just started, last velocity was 0. So difference of zero to current velocity over time gives acceleration of the first point.
+      newAcceleration.local = outPoint.local.velocity / outputTimeGranularity;
+      newAcceleration.screen = outPoint.screen.velocity / outputTimeGranularity;
+    }
+    pointGenerated = true;
+  }
+
+  acceleration.local = newAcceleration.local;
+  acceleration.screen = newAcceleration.screen;
+  return pointGenerated;
+}
+
+float PanGesture::GetDivisibleTimeDifference( int timeA, int timeB, float minimumDelta, float overrideDifference )
+{
+  float timeDifference( overrideDifference );
+  if( mUseActualTimes )
+  {
+    timeDifference = static_cast<float>( abs( timeA - timeB ) );
+    if( timeDifference < minimumDelta )
+    {
+      timeDifference = minimumDelta;
+    }
+  }
+  return timeDifference;
+}
+
+void PanGesture::LimitAccelerationChange( RelativeVectors& currentAcceleration, RelativeVectors& lastAcceleration, float changeLimit )
+{
+  // We don't use the float parameter version of clamp here, as that will create the capping vectors twice in total.
+  Vector2 capMinimum( -changeLimit, -changeLimit );
+  Vector2 capMaximum( changeLimit, changeLimit );
+  Vector2 accelerationDeltaLocal( currentAcceleration.local - lastAcceleration.local );
+  Vector2 accelerationDeltaScreen( currentAcceleration.screen - lastAcceleration.screen );
+  accelerationDeltaLocal.Clamp( capMinimum, capMaximum );
+  accelerationDeltaScreen.Clamp( capMinimum, capMaximum );
+  currentAcceleration.local = lastAcceleration.local + accelerationDeltaLocal;
+  currentAcceleration.screen = lastAcceleration.screen + accelerationDeltaScreen;
+}
+
+void PanGesture::PredictionMode2( PanInfo& startPoint, RelativeVectors& accelerationToUse,
+    PanInfo& predictedPoint, unsigned int currentFrameTime, unsigned int previousFrameTime, bool noPreviousData )
+{
+  // Do the prediction (based on mode).
+  if( mScalarOnlyPredictionEnabled )
+  {
+    // We are doing scalar based prediction.
+    // This divisor is to help tuning by giving the scalar only result
+    // a similar prediction amount to the integrated result.
+    float scalarVelocityMultiplier = static_cast<float>( mCurrentPredictionAmount ) / 1.364f;
+    predictedPoint.local.position = startPoint.local.position + ( startPoint.local.velocity * scalarVelocityMultiplier );
+    predictedPoint.screen.position = startPoint.screen.position + ( startPoint.screen.velocity * scalarVelocityMultiplier );
+  }
+  else
+  {
+    // We are doing integration based prediction.
+    float predictionDelta( mCurrentPredictionAmount );
+
+    predictedPoint.local.position = startPoint.local.position + ( startPoint.local.velocity * predictionDelta ) +
+        ( accelerationToUse.local * ( predictionDelta * predictionDelta * 0.5f ) );
+    predictedPoint.screen.position = startPoint.screen.position + ( startPoint.screen.velocity * predictionDelta ) +
+        ( accelerationToUse.screen * ( predictionDelta * predictionDelta * 0.5f ) );
+  }
+
+  // Calculate remaining gesture data from the result.
+  float timeDifference( GetDivisibleTimeDifference( currentFrameTime, previousFrameTime, 1.0f, OUTPUT_TIME_DIFFERENCE ) );
+  if( noPreviousData )
+  {
+    predictedPoint.local.displacement = predictedPoint.local.position - startPoint.local.position;
+    predictedPoint.screen.displacement = predictedPoint.screen.position - startPoint.screen.position;
+  }
+  else
+  {
+    predictedPoint.local.displacement = predictedPoint.local.position - mLastPredictedPoint.local.position;
+    predictedPoint.screen.displacement = predictedPoint.screen.position - mLastPredictedPoint.screen.position;
+  }
+  predictedPoint.local.velocity = predictedPoint.local.displacement / timeDifference;
+  predictedPoint.screen.velocity = predictedPoint.screen.displacement / timeDifference;
+
+  // TODO: Experimental - not used at run time. Left in code for reference only.
+  if( TEST_TUNE_ENABLE_OVERSHOOT_PROTECTION )
+  {
+    // Overshoot protection
+    if( !noPreviousData )
+    {
+      if( ( mLastPredictedPoint.local.velocity.x > Math::MACHINE_EPSILON_0 && predictedPoint.local.velocity.x < Math::MACHINE_EPSILON_0 )
+        || ( mLastPredictedPoint.local.velocity.x < Math::MACHINE_EPSILON_0 && predictedPoint.local.velocity.x > Math::MACHINE_EPSILON_0 ) )
+      {
+        predictedPoint.local.position.x = mLastPredictedPoint.local.position.x;
+        predictedPoint.screen.position.x = mLastPredictedPoint.screen.position.x;
+        mPredictionHistory.clear();
+      }
+      if( ( mLastPredictedPoint.local.velocity.y > Math::MACHINE_EPSILON_0 && predictedPoint.local.velocity.y < Math::MACHINE_EPSILON_0 )
+        || ( mLastPredictedPoint.local.velocity.y < Math::MACHINE_EPSILON_0 && predictedPoint.local.velocity.y > Math::MACHINE_EPSILON_0 ) )
+      {
+        predictedPoint.local.position.y = mLastPredictedPoint.local.position.y;
+        predictedPoint.screen.position.y = mLastPredictedPoint.screen.position.y;
+        mPredictionHistory.clear();
+      }
+    }
+  }
+
+  predictedPoint.time = currentFrameTime;
+  mLastPredictedPoint = predictedPoint;
+}
+
+// TODO: This needs a better name! It is called this instead of prediction mode 2 because:
+// 1) It is the entire workflow, not just prediction.
+// 2) To make it less confusing as there is a function that does prediction alone called PerformPredictionMode2.
+// Ultimately we need to combine the old and new code modularly so there is one code path that can optionally run different functions based on configuration.
+// At the moment, the differences between the inputs & outputs of these different functions prevent that, but this can be resolved.
+bool PanGesture::NewAlgorithm( unsigned int lastVSyncTime, unsigned int nextVSyncTime )
+{
+  if( !mInGesture )
+  {
+    // clear current pan history
+    mPanHistory.clear();
+    mPredictionHistory.clear();
+  }
+
+  /*#########################################################################################
+    #### Read in all gestures received this frame first (holding a lock for a short time)
+    #########################################################################################*/
+
+  unsigned int eventsThisFrame = ReadFrameEvents();
+
+  /*#########################################################################################
+    #### Perform input rate-conversion on all gestures received this frame.
+    #### This also populates the pan history.
+    #########################################################################################*/
+
+  bool justStarted = false;
+  bool justFinished = false;
+  PanInfo rateConvertedGesture;
+  if( !InputRateConversion( rateConvertedGesture, eventsThisFrame, nextVSyncTime, lastVSyncTime, justStarted, justFinished ) )
+  {
+    // There's nothing we can do with the input, exit.
+    return false;
+  }
+
+  /*#########################################################################################
+    #### If we are in gesture, Get first interpolated point with: target time = current time
+    #########################################################################################*/
+
+  bool performUpdate = false;
+  RelativeVectors currentAcceleration;
+  currentAcceleration.local = mLastInitialAcceleration.local;
+  currentAcceleration.screen = mLastInitialAcceleration.screen;
+
+  if( mInGesture || justStarted )
+  {
+    // Get first interpolated point.
+    // TODO: Erase time should be maximum of both interpolated point ranges in past.
+    PanInfo targetPoint;
+    float outputTimeGranularity( GetDivisibleTimeDifference( nextVSyncTime, lastVSyncTime, 1.0f, OUTPUT_TIME_DIFFERENCE ) );
+    bool pointGenerated = InterpolatePoint( mPanHistory, nextVSyncTime, nextVSyncTime, mInterpolationTimeRange,
+        targetPoint, currentAcceleration, outputTimeGranularity, true );
+    if( pointGenerated )
+    {
+      mLastInitialAcceleration.local = currentAcceleration.local;
+      mLastInitialAcceleration.screen = currentAcceleration.screen;
+      performUpdate = true;
+    }
+    else
+    {
+      targetPoint = rateConvertedGesture;
+      currentAcceleration.local = mLastInitialAcceleration.local;
+      currentAcceleration.screen = mLastInitialAcceleration.screen;
+      // TODO: Potentially do something to substitute lack of generated point (and perform update).
+      if( eventsThisFrame > 0 )
+      {
+        performUpdate = true;
+      }
+    }
+
+    /*#########################################################################################
+      #### Limit the change of acceleration of the first interpolated point since last time
+      #########################################################################################*/
+
+    if( !justStarted )
+    {
+      LimitAccelerationChange( currentAcceleration, mLastAcceleration, ACCELERATION_CAP );
+    }
+    mLastAcceleration.local = currentAcceleration.local;
+    mLastAcceleration.screen = currentAcceleration.screen;
+
+    /*#########################################################################################
+      #### Get second interpolated point, and blend the resultant velocity and acceleration (optional)
+      #########################################################################################*/
+
+    PanInfo outPoint;
+    RelativeVectors interpolatedAcceleration;
+    if( mTwoPointPredictionEnabled )
+    {
+      // Get second interpolated point with target time = current time - past interpolate time.
+      unsigned int pastInterpolateTime = nextVSyncTime - mTwoPointPastInterpolateTime;
+      PanInfo outPoint;
+      RelativeVectors interpolatedAcceleration;
+      interpolatedAcceleration.local = mLastInterpolatedAcceleration.local;
+      interpolatedAcceleration.screen = mLastInterpolatedAcceleration.screen;
+      if( !InterpolatePoint( mPanHistory, nextVSyncTime, pastInterpolateTime, mTwoPointPastInterpolateTime,
+          outPoint, interpolatedAcceleration, outputTimeGranularity, false ) )
+      {
+        if( justStarted )
+        {
+          outPoint = targetPoint;
+        }
+        else
+        {
+          outPoint = mLastSecondInterpolatedPoint;
+        }
+      }
+      mLastInterpolatedAcceleration.local = interpolatedAcceleration.local;
+      mLastInterpolatedAcceleration.screen = interpolatedAcceleration.screen;
+      mLastSecondInterpolatedPoint = outPoint;
+
+      // Combine the first interpolated point and the second interpolated point.
+      // by mixing them with the configured amount. This is done for acceleration and velocity.
+      // It could be optionally done for position too, but this typically is worse as it means we have to predict further ahead.
+      float currentVelocityMultiplier( 1.0f - mTwoPointVelocityBias );
+      float lastVelocityMultiplier( mTwoPointVelocityBias );
+      targetPoint.local.velocity = ( outPoint.local.velocity * lastVelocityMultiplier ) + ( targetPoint.local.velocity * currentVelocityMultiplier );
+      targetPoint.screen.velocity = ( outPoint.screen.velocity * lastVelocityMultiplier ) + ( targetPoint.screen.velocity * currentVelocityMultiplier );
+      float currentAccelerationMultiplier( 1.0f - mTwoPointAccelerationBias );
+      float lastAccelerationMultiplier( mTwoPointAccelerationBias );
+      currentAcceleration.local = ( interpolatedAcceleration.local * lastAccelerationMultiplier ) + ( currentAcceleration.local * currentAccelerationMultiplier );
+      currentAcceleration.screen = ( interpolatedAcceleration.screen * lastAccelerationMultiplier ) + ( currentAcceleration.screen * currentAccelerationMultiplier );
+    }
+
+    /*#########################################################################################
+      #### Perform prediction
+      #########################################################################################*/
+
+    PanInfo predictedPoint;
+    PredictionMode2( targetPoint, currentAcceleration, predictedPoint, nextVSyncTime, lastVSyncTime, justStarted );
+    targetPoint = predictedPoint;
+
+    /*#########################################################################################
+      #### Smoothing
+      #########################################################################################*/
+
+    // If we are using multi-tap smoothing, keep a history of predicted results.
+    if( mSmoothingMode == SMOOTHING_MULTI_TAP )
+    {
+      mPredictionHistory.push_back( targetPoint );
+    }
+
+    if( !justStarted )
+    {
+      float outputTimeGranularity( GetDivisibleTimeDifference( nextVSyncTime, lastVSyncTime, 1.0f, OUTPUT_TIME_DIFFERENCE ) );
+      if( mSmoothingMode == SMOOTHING_MULTI_TAP )
+      {
+        // Perform Multi-tap Smoothing.
+        RelativeVectors blank;
+        InterpolatePoint( mPredictionHistory, nextVSyncTime, nextVSyncTime, mMultiTapSmoothingRange,
+            targetPoint, blank, outputTimeGranularity, true );
+      }
+      else
+      {
+        // Perform Single-tap Smoothing.
+        if( !mSmoothingAmountOverridden )
+        {
+          // If the smoothing amount has not been modified, default to the correct amount for this algorithm.
+          mSmoothingAmount = DEFAULT_SMOOTHING_AMOUNT[1];
+        }
+        BlendPoints( targetPoint, mLastGesture, mSmoothingAmount );
+      }
+
+      /*#########################################################################################
+        #### Finalize other point data (from position)
+        #########################################################################################*/
+
+      targetPoint.local.displacement = targetPoint.local.position - mLastGesture.local.position;
+      targetPoint.local.velocity = targetPoint.local.displacement / outputTimeGranularity;
+      targetPoint.screen.displacement = targetPoint.screen.position - mLastGesture.screen.position;
+      targetPoint.screen.velocity = targetPoint.screen.displacement / outputTimeGranularity;
+    }
+
+    /*#########################################################################################
+      #### Send out the new point, by setting the properties
+      #### (Constraints will automatically react to this)
+      #########################################################################################*/
+
+    if( performUpdate )
+    {
+      mPanning.Set( mInGesture & !justFinished );
+      mScreenPosition.Set( targetPoint.screen.position );
+      mScreenDisplacement.Set( targetPoint.screen.displacement );
+      mScreenVelocity.Set( targetPoint.screen.velocity );
+      mLocalPosition.Set( targetPoint.local.position );
+      mLocalDisplacement.Set( targetPoint.local.displacement );
+      mLocalVelocity.Set( targetPoint.local.velocity );
+
+      mLastGesture = targetPoint;
+
+      if( mProfiling )
+      {
+        mProfiling->mAveragedData.push_back( PanGestureProfiling::Position( targetPoint.time, targetPoint.screen.position,
+            targetPoint.screen.displacement, targetPoint.screen.velocity, targetPoint.state ) );
+      }
+    }
+  }
+
+  mInGesture &= ~justFinished;
+
+  return performUpdate;
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/gestures/scene-graph-pan-gesture.h b/dali/internal/update/gestures/scene-graph-pan-gesture.h
new file mode 100644 (file)
index 0000000..6c172c4
--- /dev/null
@@ -0,0 +1,588 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/mutex.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/events/pan-gesture.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/gestures/gesture-properties.h>
+
+namespace Dali
+{
+
+struct PanGesture;
+
+namespace Internal
+{
+
+struct PanGestureProfiling;
+
+namespace SceneGraph
+{
+
+/**
+ * The latest pan gesture information is stored in this scene object.
+ */
+class PanGesture : public PropertyOwner
+{
+public:
+
+  enum PredictionMode
+  {
+    PREDICTION_NONE = 0,
+    PREDICTION_1,
+    PREDICTION_2,
+  };
+
+  enum SmoothingMode
+  {
+    SMOOTHING_NONE,           // No smoothing.
+    SMOOTHING_LAST_VALUE,     // Smooth between last value and latest value.
+    SMOOTHING_MULTI_TAP,      // Uses multitap smoothing, only available with Prediction mode 2.
+  };
+
+  static const PredictionMode DEFAULT_PREDICTION_MODE;
+  static const int NUM_PREDICTION_MODES;
+
+  static const SmoothingMode DEFAULT_SMOOTHING_MODE;
+  static const int NUM_SMOOTHING_MODES;
+
+  // Latest Pan Information
+
+  /**
+   * Only stores the information we actually require from Dali::PanGesture
+   */
+  struct PanInfo
+  {
+    /**
+     * Stores the velocity, displacement and position.
+     */
+    struct Info
+    {
+      Info()
+      {
+      }
+
+      /**
+       * Copy constructor
+       */
+      Info( const Info& rhs )
+      : velocity( rhs.velocity ),
+        displacement( rhs.displacement ),
+        position( rhs.position )
+      {
+      }
+
+      /**
+       * Assignment operator
+       */
+      Info& operator=( const Info& rhs )
+      {
+        velocity = rhs.velocity;
+        displacement = rhs.displacement;
+        position = rhs.position;
+
+        return *this;
+      }
+
+      // Data
+
+      Vector2 velocity;
+      Vector2 displacement;
+      Vector2 position;
+    };
+
+    /**
+     * Constructor
+     */
+    PanInfo()
+    : time( 0u ),
+      state( Gesture::Clear ),
+      read( true )
+    {
+    }
+
+    /**
+     * Copy constructor
+     */
+    PanInfo( const PanInfo& rhs )
+    : time( rhs.time ),
+      state( rhs.state ),
+      local( rhs.local ),
+      screen( rhs.screen ),
+      read( true )
+    {
+    }
+
+    /**
+     * Assignment operator
+     */
+    PanInfo& operator=( const PanInfo& rhs )
+    {
+      time = rhs.time;
+      state = rhs.state;
+      local = rhs.local;
+      screen = rhs.screen;
+
+      return *this;
+    }
+
+    /**
+     * Assignment operator
+     * @param[in] gesture A Dali::Gesture
+     */
+    PanInfo& operator=( const Dali::PanGesture& rhs )
+    {
+      time = rhs.time;
+      state = rhs.state;
+
+      local.velocity = rhs.velocity;
+      local.displacement = rhs.displacement;
+      local.position = rhs.position;
+
+      screen.velocity = rhs.screenVelocity;
+      screen.displacement = rhs.screenDisplacement;
+      screen.position = rhs.screenPosition;
+
+      return *this;
+    }
+
+    // Data
+    unsigned int time;
+    Gesture::State state;
+    Info local;
+    Info screen;
+    volatile bool read;
+  };
+
+  typedef std::vector<PanInfo> PanInfoHistory;
+  typedef PanInfoHistory::iterator PanInfoHistoryIter;
+  typedef PanInfoHistory::const_iterator PanInfoHistoryConstIter;
+
+private:
+  static const unsigned int PAN_GESTURE_HISTORY = 30u;
+
+public:
+
+  /**
+   * Create a new PanGesture
+   */
+  static PanGesture* New();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~PanGesture();
+
+  /**
+   * Adds a PanGesture to the internal circular-buffer waiting to be handled by UpdateProperties.
+   * @param[in]  gesture  The latest pan gesture.
+   */
+  void AddGesture( const Dali::PanGesture& gesture );
+
+  /**
+   * @brief Removes pan events from the history that are older than maxAge, leaving at least minEvents
+   *
+   * @param[in] panHistory The pan event history container
+   * @param[in] currentTime The current frame time
+   * @param[in] maxAge Maximum age of an event before removing (in millis)
+   * @param[in] minEvents The minimum number of events to leave in history, oldest events are removed before newest
+   */
+  void RemoveOldHistory(PanInfoHistory& panHistory, unsigned int currentTime, unsigned int maxAge, unsigned int minEvents);
+
+  /**
+   * Uses elapsed time and time stamps
+   */
+  void PredictionMode1(int eventsThisFrame, PanInfo& gestureOut, PanInfoHistory& panHistory, unsigned int lastVSyncTime, unsigned int nextVSyncTime);
+
+  /**
+   * Blends two points together.
+   * The blend value ranges are:
+   * 0.0f = use 100% of current value.
+   * 1.0f = use half-way average of current and last value.
+   *
+   * @param[in,out] gesture     Pass in current gesture, outputs result of blend.
+   * @param[in]     lastGesture Pass in gesture to blend between.
+   */
+  void BlendPoints( PanInfo& gesture, PanInfo& lastGesture, float blendValue );
+
+  /**
+   * Called by the update manager so that we can update the value of our properties.
+   * @param[in]  nextRenderTime  The estimated time of the next render (in milliseconds).
+   * @return true, if properties were updated.
+   */
+  virtual bool UpdateProperties( unsigned int lastRenderTime, unsigned int nextRenderTime );
+
+  /**
+   * Retrieves a reference to the panning flag property.
+   * @return The panning flag property.
+   */
+  const GesturePropertyBool& GetPanningProperty() const;
+
+  /**
+   * Retrieves a reference to the screen position property.
+   * @return The screen position property.
+   */
+  const GesturePropertyVector2& GetScreenPositionProperty() const;
+
+  /**
+   * Retrieves a reference to the screen velocity property.
+   * @return The screen velocity property.
+   */
+  const GesturePropertyVector2& GetScreenVelocityProperty() const;
+
+  /**
+   * Retrieves a reference to the screen displacement property.
+   * @return The screen displacement property.
+   */
+  const GesturePropertyVector2& GetScreenDisplacementProperty() const;
+
+  /**
+   * Retrieves a reference to the local position property.
+   * @return The local position property.
+   */
+  const GesturePropertyVector2& GetLocalPositionProperty() const;
+
+  /**
+   * Retrieves a reference to the local displacement property.
+   * @return The local displacement property.
+   */
+  const GesturePropertyVector2& GetLocalDisplacementProperty() const;
+
+  /**
+   * Retrieves a reference to the local velocity property.
+   * @return The local velocity property.
+   */
+  const GesturePropertyVector2& GetLocalVelocityProperty() const;
+
+  /**
+   * @brief Sets the prediction mode of the pan gesture
+   *
+   * @param[in] mode The prediction mode
+   */
+  void SetPredictionMode(PredictionMode mode);
+
+  /**
+   * @brief Sets the prediction amount of the pan gesture
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the upper bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetMaximumPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the lower bound of the prediction amount for clamping
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetMinimumPredictionAmount(unsigned int amount);
+
+  /**
+   * @brief Sets the amount of prediction interpolation to adjust when the pan velocity is changed
+   *
+   * @param[in] amount The prediction amount in milliseconds
+   */
+  void SetPredictionAmountAdjustment(unsigned int amount);
+
+  /**
+   * @brief Sets the prediction mode of the pan gesture
+   *
+   * @param[in] mode The prediction mode
+   */
+  void SetSmoothingMode(SmoothingMode mode);
+
+  /**
+   * @brief Sets the amount of smoothing to apply for the current smoothing mode
+   *
+   * @param[in] amount The amount of smoothing [0.0f,1.0f]
+   */
+  void SetSmoothingAmount(float amount);
+
+  /*
+   * @brief Sets whether to use actual times of the real gesture and frames or not.
+   *
+   * @param[in] value True = use actual times, False = use perfect values
+   */
+  void SetUseActualTimes( bool value );
+
+  /**
+   * @brief Sets the interpolation time range (ms) of past points to use (with weights) when interpolating.
+   *
+   * @param[in] value Time range in ms
+   */
+  void SetInterpolationTimeRange( int value );
+
+  /**
+   * @brief Sets whether to use scalar only prediction, which when enabled, ignores acceleration.
+   *
+   * @param[in] value True = use scalar prediction only
+   */
+  void SetScalarOnlyPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets whether to use two point prediction. This combines two interpolated points to get more steady acceleration and velocity values.
+   *
+   * @param[in] value True = use two point prediction
+   */
+  void SetTwoPointPredictionEnabled( bool value );
+
+  /**
+   * @brief Sets the time in the past to interpolate the second point when using two point interpolation.
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetTwoPointInterpolatePastTime( int value );
+
+  /**
+   * @brief Sets the two point velocity bias. This is the ratio of first and second points to use for velocity.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetTwoPointVelocityBias( float value );
+
+  /**
+   * @brief Sets the two point acceleration bias. This is the ratio of first and second points to use for acceleration.
+   *
+   * @param[in] value 0.0f = 100% first point. 1.0f = 100% of second point.
+   */
+  void SetTwoPointAccelerationBias( float value );
+
+  /**
+   * @brief Sets the range of time (ms) of points in the history to perform multitap smoothing with (if enabled).
+   *
+   * @param[in] value Time in past in ms
+   */
+  void SetMultitapSmoothingRange( int value );
+
+  /**
+   * Called to provide pan-gesture profiling information.
+   */
+  void EnableProfiling();
+
+private:
+
+  /**
+   * Protected constructor.
+   */
+  PanGesture();
+
+  // Undefined
+  PanGesture(const PanGesture&);
+
+private:
+
+  // Struct to keep pairs of local and screen data together.
+  // TODO: This can encapsulate some functionality also.
+  typedef struct
+  {
+    Vector2 local;
+    Vector2 screen;
+  } RelativeVectors;
+
+  /**
+   * Houses new code to process input events and generate an output point.
+   *
+   * @param[in]  lastVSyncTime The time of the last render (in milliseconds)
+   * @param[in]  nextVSyncTime The estimated time of the next render (in milliseconds)
+   */
+  bool NewAlgorithm( unsigned int lastVSyncTime, unsigned int nextVSyncTime );
+
+  /**
+   * Gets the (absolute) time difference between two times.
+   * This is limited by minimumDelta, so it can be safe to use as a divisor.
+   * This function is wrapped so that the behviour can be overridden to return a "perfect" time difference (overrideDifference).
+   *
+   * @param[in]  timeA The first time to calculate from
+   * @param[in]  timeB The second time to calculate from
+   * @param[in]  minimumDelta The smallest amount the difference can become
+   * @param[in]  overrideDifference The time difference to return if using perfect times
+   */
+  inline float GetDivisibleTimeDifference( int timeA, int timeB, float minimumDelta, float overrideDifference );
+
+  /**
+   * This limits the change currentAcceleration can have over lastAcceleration by the specified changeLimit value.
+   *
+   * @param[in]  currentAcceleration The acceleration to modify
+   * @param[in]  lastAcceleration The acceleration to limit against
+   * @param[in]  changeLimit The maximum change (in either direction)
+   */
+  void LimitAccelerationChange( RelativeVectors& currentAcceleration, RelativeVectors& lastAcceleration, float changeLimit );
+
+  /**
+   * Reads all events received this frame into a linear buffer.
+   * A lock is held while this is done.
+   */
+  unsigned int ReadFrameEvents();
+
+  /**
+   * Converts between input rate and internal rate (typically 60Hz internally).
+   * Also writes to the pan history container.
+   * TODO: Does not need to return the gesture if it is in the history also, but currently it's used.
+   * (if rate conversion does not generate a point there are points still in history, but this can been done with a bool property).
+   *
+   * @param[out] rateConvertedGesture Result gesture for this frame is writen here.
+   * @param[in]  eventsThisFrame Number of events to convert
+   * @param[in]  currentFrameTime Time of the frame we will render to
+   * @param[in]  lastFrameTime Time of the last rendered frame
+   * @param[out] justStarted Set to true if we are now starting a new gesture
+   * @param[out] justFinished Set to true if we are now finishing a gesture
+   */
+  bool InputRateConversion( PanInfo& rateConvertedGesture, unsigned int eventsThisFrame,
+      unsigned int currentFrameTime, unsigned int lastFrameTime, bool& justStarted, bool& justFinished );
+
+  /**
+   * Generates an interpolated point at the specified point in time.
+   *
+   * @param[in]  history of points to use
+   * @param[in]  currentTime Time of the frame we will render to
+   * @param[in]  targetTime Time of the point to generate
+   * @param[in]  range Range of time (each side of target time) to use points from
+   * @param[out] outPoint Generated point
+   * @param[out] acceleration Generated acceleration
+   * @param[in]  outputTimeGranularity Time difference between output point (typically 60Hz)
+   * @param[in]  eraseUnused Set to true to clean up any history not used by the function
+   */
+  bool InterpolatePoint( PanInfoHistory& history, unsigned int currentTime, unsigned int targetTime, unsigned int range,
+      PanInfo& outPoint, RelativeVectors& acceleration, int outputTimeGranularity, bool eraseUnused );
+
+  /**
+   * Predicts a point in the future, based on the supplied point and acceleration.
+   * Other user configuration settings are considered.
+   *
+   * @param[in] startPoint Starting point to use. Position and velocity are taken from here.
+   * @param[in] accelerationToUse The acceleration to use.
+   * @param[out] predictedPoint Generated predicted point
+   * @param[in]  currentFrameTime Time of the frame we will render to
+   * @param[in]  previousFrameTime Time of the last rendered frame
+   * @param[in]  noPreviousData Set to true if we are just starting a gesture
+   */
+  void PredictionMode2( PanInfo& startPoint, RelativeVectors& accelerationToUse,
+      PanInfo& predictedPoint, unsigned int currentFrameTime, unsigned int previousFrameTime, bool noPreviousData );
+
+private:
+
+  // Undefined
+  PanGesture& operator=(const PanGesture&);
+
+  // PropertyOwner
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+  // Defines information to be gathered by the gesture reading code.
+  struct FrameGestureInfo
+  {
+    PanGesture::PanInfo frameGesture;
+    float acceleration;
+    unsigned int eventsThisFrame;
+    bool justStarted;
+    bool justFinished;
+
+    FrameGestureInfo()
+    : acceleration( 0.0f ),
+      eventsThisFrame( 0 ),
+      justStarted( false ),
+      justFinished( false )
+    {
+    }
+  };
+
+  /**
+   * Reads gestures from input, builds history.
+   * @param[out] info Written to with information about gestures read this frame.
+   * @param[in] currentTimestamp The time of this frame.
+   */
+  bool ReadGestures( FrameGestureInfo& info, unsigned int currentTimestamp );
+
+  /**
+   * Reads gestures from input and resamples data, builds history.
+   * @param[out] info Written to with information about gestures read this frame.
+   * @param[in] currentTimestamp The time of this frame.
+   */
+  bool ReadAndResampleGestures( FrameGestureInfo& info, unsigned int currentTimestamp );
+
+private:
+
+  // Properties
+  GesturePropertyBool    mPanning;            ///< panning flag
+  GesturePropertyVector2 mScreenPosition;     ///< screen-position
+  GesturePropertyVector2 mScreenDisplacement; ///< screen-displacement
+  GesturePropertyVector2 mScreenVelocity;     ///< screen-velocity
+  GesturePropertyVector2 mLocalPosition;      ///< local-position
+  GesturePropertyVector2 mLocalDisplacement;  ///< local-displacement
+  GesturePropertyVector2 mLocalVelocity;      ///< local-velocity
+
+  PanInfoHistory mPanHistory;
+  PanInfoHistory mPredictionHistory;
+  PanInfo mGestures[PAN_GESTURE_HISTORY];     ///< Circular buffer storing the 4 most recent gestures.
+  PanInfo mReadGestures[PAN_GESTURE_HISTORY]; ///< Linear buffer storing the most recent gestures (to reduce read lock time).
+  PanInfo mLastGesture;                       ///< The last gesture. (last update frame).
+  PanInfo mTargetGesture;                     ///< The most recent input gesture, if the current used gesture does not match.
+  PanInfo mLastUnmodifiedGesture;             ///< The last gesture before any processing was done on it.
+  PanInfo mLastSecondInterpolatedPoint;       ///< Stores the last second interpolated point we generated.
+  PanInfo mLastFrameReadGesture;              ///< Stores the last gesture read.
+  PanInfo mLastPredictedPoint;                ///< Stores the last predicted point we generated.
+  RelativeVectors mLastAcceleration;          ///< Stores the acceleration value from the acceleration limiting last frame.
+  RelativeVectors mLastInterpolatedAcceleration;  ///< Stores the second interpolated point acceleration value from the last frame.
+  RelativeVectors mLastInitialAcceleration;   ///< Stores the initial acceleration value from the last frame.
+
+  volatile unsigned int mWritePosition;       ///< The next PanInfo buffer to write to. (starts at 0).
+  unsigned int mReadPosition;                 ///< The next PanInfo buffer to read. (starts at 0).
+  bool mNotAtTarget;                          ///< Keeps track of if the last gesture used was the most recent received.
+  bool mInGesture;                            ///< True if the gesture is currently being handled i.e. between Started <-> Finished/Cancelled.
+  bool mPredictionAmountOverridden;
+  bool mSmoothingAmountOverridden;
+
+  PanGestureProfiling* mProfiling;            ///< NULL unless pan-gesture profiling information is required.
+  Dali::Mutex mMutex;                         ///< Mutex to lock access.
+
+  // Environment variables:
+
+  PredictionMode mPredictionMode;             ///< The pan gesture prediction mode
+  unsigned int mPredictionAmount;             ///< how far into future to predict in milliseconds
+  unsigned int mCurrentPredictionAmount;      ///< the current prediction amount used by the prediction algorithm
+  unsigned int mMaxPredictionAmount;          ///< the maximum prediction amount used by the prediction algorithm
+  unsigned int mMinPredictionAmount;          ///< the minimum prediction amount used by the prediction algorithm
+  unsigned int mPredictionAmountAdjustment;   ///< the prediction amount to adjust in milliseconds when pan velocity changes
+  SmoothingMode mSmoothingMode;               ///< The pan gesture prediction mode
+  float         mSmoothingAmount;             ///< How much smoothing to apply [0.0f,1.0f]
+  bool mUseActualTimes;                       ///< Disable to optionally override actual times if they make results worse.
+  int mInterpolationTimeRange;                ///< Time into past history (ms) to use points to interpolate the first point.
+  bool mScalarOnlyPredictionEnabled;          ///< If enabled, prediction is done using velocity alone (no integration or acceleration).
+  bool mTwoPointPredictionEnabled;            ///< If enabled, a second interpolated point is predicted and combined with the first to get more stable values.
+  int mTwoPointPastInterpolateTime;           ///< The target time in the past to generate the second interpolated point.
+  float mTwoPointVelocityBias;                ///< The ratio of first and second interpolated points to use for velocity. 0.0f = 100% of first point. 1.0f = 100% of second point.
+  float mTwoPointAccelerationBias;            ///< The ratio of first and second interpolated points to use for acceleration. 0.0f = 100% of first point. 1.0f = 100% of second point.
+  int mMultiTapSmoothingRange;                ///< The range in time (ms) of points in the history to smooth the final output against.
+
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PAN_GESTURE_H__
diff --git a/dali/internal/update/manager/object-owner-container.h b/dali/internal/update/manager/object-owner-container.h
new file mode 100644 (file)
index 0000000..7c0aa5c
--- /dev/null
@@ -0,0 +1,146 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
+#define DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/update/common/discard-queue.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class UpdateManager;
+
+/**
+ * ObjectOwnerContainer is an object which owns SceneGraph Objects.
+ * It is responsible for ensuring they are placed on a discard queue
+ * when removed from the container.
+ */
+template< class Type >
+class ObjectOwnerContainer
+{
+public:
+  typedef typename Internal::OwnerContainer< Type* > ObjectContainer;
+  typedef typename Internal::OwnerContainer< Type* >::Iterator Iterator;
+
+  /**
+   * @brief Constructor - createw a new object container
+   *
+   * Object container own update side objects
+   *
+   * @param[in] sceneGraphBuffers Helper to get the correct buffer index
+   * @param[in] discardQueue Queue to discard objects that might still be in use in the render thread.
+   **/
+  ObjectOwnerContainer( SceneGraphBuffers& sceneGraphBuffers, DiscardQueue& discardQueue )
+  : mSceneController( NULL ),
+    mSceneGraphBuffers( sceneGraphBuffers ),
+    mDiscardQueue( discardQueue )
+  {
+  }
+
+  /**
+   * @brief Set the SceneController on this owner
+   *
+   * @param[in] sceneController The SceneController
+   **/
+  void SetSceneController( SceneController& sceneController )
+  {
+    mSceneController = &sceneController;
+  }
+
+  /**
+   * @brief Add an object to the owner
+   *
+   * @param[in] object Pointer to the object that will be owned
+   **/
+  void Add( Type* pointer )
+  {
+    DALI_ASSERT_DEBUG( pointer && "Pointer should not be null" );
+
+    mObjectContainer.PushBack( pointer );
+
+    pointer->ConnectToSceneGraph(*mSceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+  }
+
+  /**
+   * @brief Remove an object from the owner.
+   *
+   * The object is put on the discard queue.
+   *
+   * @param[in] object Pointer to the object to be removed
+   **/
+  void Remove( Type* pointer )
+  {
+    DALI_ASSERT_DEBUG( pointer && "Pointer should not be null" );
+
+    // Find the object
+    Iterator match = std::find( mObjectContainer.Begin(), mObjectContainer.End(), pointer );
+    DALI_ASSERT_DEBUG( match != mObjectContainer.End() && "Should always find a match" );
+
+    mDiscardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), mObjectContainer.Release( match ) );
+    pointer->DisconnectFromSceneGraph(*mSceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+  }
+
+  /**
+   * @brief Method to call ResetToBaseValues on all the objects owned.
+   *
+   * @param[in] bufferIndex Buffer index for double buffered values.
+   **/
+  void ResetToBaseValues( BufferIndex bufferIndex )
+  {
+    for ( Iterator iter = mObjectContainer.Begin(); iter != mObjectContainer.End(); ++iter)
+    {
+      Type* object = (*iter);
+      object->ResetToBaseValues( bufferIndex );
+    }
+  }
+
+  /**
+   * @brief Method to call ConstrainObjects on all the objects owned.
+   *
+   * @param[in] bufferIndex Buffer index for double buffered values.
+   **/
+  void ConstrainObjects( BufferIndex bufferIndex )
+  {
+    for ( Iterator iter = mObjectContainer.Begin(); iter != mObjectContainer.End(); ++iter)
+    {
+      Type* object = (*iter);
+      ConstrainPropertyOwner( *object, bufferIndex );
+    }
+  }
+
+private:
+  SceneController* mSceneController;      ///< SceneControler used to send messages
+  ObjectContainer mObjectContainer;       ///< Container for the objects owned
+  SceneGraphBuffers& mSceneGraphBuffers;  ///< Reference to a SceneGraphBuffers to get the indexBuffer
+  DiscardQueue& mDiscardQueue;            ///< Discard queue used for removed objects
+};
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_OBJECT_OWNER_CONTAINER
diff --git a/dali/internal/update/manager/prepare-render-algorithms.cpp b/dali/internal/update/manager/prepare-render-algorithms.cpp
new file mode 100644 (file)
index 0000000..c213f95
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/prepare-render-algorithms.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/common/render-instruction.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/******************************************************************************
+ ************************** Clear lists from previous update ******************
+ ******************************************************************************/
+
+void ClearRenderables( SortedLayerPointers& sortedLayers )
+{
+  // Clear the lists of renderables from the previous update
+
+  const SortedLayersIter endIter = sortedLayers.end();
+
+  for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
+  {
+    (*iter)->stencilRenderables.clear();
+    (*iter)->colorRenderables.clear();
+    (*iter)->overlayRenderables.clear();
+  }
+}
+
+/******************************************************************************
+ ***************************** Prepare renderers ******************************
+ ******************************************************************************/
+
+void PrepareRenderables( BufferIndex updateBufferIndex, RenderableAttachmentContainer& renderableList )
+{
+  const RenderableAttachmentIter endIter = renderableList.end();
+  for ( RenderableAttachmentIter iter = renderableList.begin(); iter != endIter; ++iter )
+  {
+    RenderableAttachment& renderable = **iter;
+    renderable.PrepareRender( updateBufferIndex );
+  }
+}
+
+void PrepareRenderables( BufferIndex updateBufferIndex, SortedLayerPointers& sortedLayers )
+{
+  const SortedLayersIter endIter = sortedLayers.end();
+
+  for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
+  {
+    Layer& layer = **iter;
+
+    PrepareRenderables( updateBufferIndex, layer.stencilRenderables );
+    PrepareRenderables( updateBufferIndex, layer.colorRenderables );
+    PrepareRenderables( updateBufferIndex, layer.overlayRenderables );
+  }
+}
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/update/manager/prepare-render-algorithms.h b/dali/internal/update/manager/prepare-render-algorithms.h
new file mode 100644 (file)
index 0000000..2b06667
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_ALGORITHMS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_ALGORITHMS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/manager/sorted-layers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Clear the list of opaque/transparent renderables for each layer.
+ * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables.
+ */
+void ClearRenderables( SortedLayerPointers& sortedLayers );
+
+/**
+ * Prepares the list of opaque/transparent renderable attachments for each layer.
+ * Whilst iterating through each layer, update the attachments ModelView matrices
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables.
+ */
+void PrepareRenderables( BufferIndex updateBufferIndex, SortedLayerPointers& sortedLayers );
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_ALGORITHMS_H__
+
diff --git a/dali/internal/update/manager/prepare-render-instructions.cpp b/dali/internal/update/manager/prepare-render-instructions.cpp
new file mode 100644 (file)
index 0000000..d5df2b4
--- /dev/null
@@ -0,0 +1,558 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/prepare-render-instructions.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/actors/layer-impl.h> // for the default sorting function
+#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/common/render-item.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/render/common/render-instruction.h>
+#include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+
+namespace
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gRenderListLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RENDER_LISTS");
+#endif
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+/**
+ * Add a renderer to the list
+ * @param updateBufferIndex to read the model matrix from
+ * @param renderList to add the item to
+ * @param renderable attachment
+ * @param viewMatrix used to calculate modelview matrix for the item
+ */
+inline void AddRendererToRenderList( BufferIndex updateBufferIndex,
+                                     RenderList& renderList,
+                                     RenderableAttachment& renderable,
+                                     const Matrix& viewMatrix,
+                                     SceneGraph::CameraAttachment& cameraAttachment,
+                                     bool isLayer3d )
+{
+  // Check for cull against view frustum
+  bool inside = true;
+
+  const Node& parentNode = renderable.GetParent();
+  const Matrix& worldMatrix = parentNode.GetWorldMatrix( updateBufferIndex );
+
+  if ( RendererAttachment* rendererAttachment = dynamic_cast< RendererAttachment* >( &renderable ) )
+  {
+    if ( rendererAttachment->GetMaterial().GetShader()->GeometryHintEnabled( Dali::ShaderEffect::HINT_DOESNT_MODIFY_GEOMETRY ) )
+    {
+      // Get the geometry extents for frustum checking
+      const Vector3& position = worldMatrix.GetTranslation3();
+      const Geometry& geometry = rendererAttachment->GetGeometry();
+      const Vector3& scale = parentNode.GetScale( updateBufferIndex );
+
+      Vector3 center( geometry.mCenter[ updateBufferIndex ] );
+      center *= scale;
+      center += position;
+
+      // Do a fast sphere check
+      if ( cameraAttachment.CheckSphereInFrustum( updateBufferIndex, center, geometry.mRadius[ updateBufferIndex ] * scale.Length() ) )
+      {
+        // Check geometry AABB
+        if ( !cameraAttachment.CheckAABBInFrustum( updateBufferIndex, center, geometry.mHalfExtents[ updateBufferIndex ] * scale ) )
+        {
+          inside = false;
+        }
+      }
+      else
+      {
+        inside = false;
+      }
+    }
+  }
+  if ( inside )
+  {
+    // Get the next free RenderItem and initialization
+    RenderItem& item = renderList.GetNextFreeItem();
+    const Renderer& renderer = renderable.GetRenderer();
+    item.SetRenderer( const_cast< Renderer* >( &renderer ) );
+    item.SetIsOpaque( renderable.IsFullyOpaque(updateBufferIndex) );
+    if( isLayer3d )
+    {
+      item.SetDepthIndex( renderable.GetDepthIndex() );
+    }
+    else
+    {
+      item.SetDepthIndex( renderable.GetDepthIndex() + static_cast<int>( parentNode.GetDepth() ) * Dali::Layer::TREE_DEPTH_MULTIPLIER );
+    }
+
+    // save MV matrix onto the item
+    Matrix::Multiply( item.GetModelViewMatrix(), worldMatrix, viewMatrix );
+  }
+}
+
+/**
+ * Add all renderers to the list
+ * @param updateBufferIndex to read the model matrix from
+ * @param renderList to add the items to
+ * @param renderable attachments
+ * @param viewMatrix used to calculate modelview matrix for the items
+ */
+inline void AddRenderersToRenderList( BufferIndex updateBufferIndex,
+                                      RenderList& renderList,
+                                      RenderableAttachmentContainer& attachments,
+                                      const Matrix& viewMatrix,
+                                      SceneGraph::CameraAttachment& cameraAttachment,
+                                      bool isLayer3d )
+{
+  DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "AddRenderersToRenderList()\n");
+
+  // Add renderer for each attachment
+  int index=0;
+  const RenderableAttachmentIter endIter = attachments.end();
+  for ( RenderableAttachmentIter iter = attachments.begin(); iter != endIter; ++iter )
+  {
+    RenderableAttachment& attachment = **iter;
+    AddRendererToRenderList( updateBufferIndex, renderList, attachment, viewMatrix, cameraAttachment, isLayer3d );
+
+    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  List[%d].renderer = %p\n", index, &(attachment.GetRenderer()));
+    index++;
+  }
+}
+
+/**
+ * Try to reuse cached renderitems from the renderlist
+ * This avoids recalculating the model view matrices in case this part of the scene was static
+ * An example case is a toolbar layer that rarely changes or a popup on top of the rest of the stage
+ * @param layer that is being processed
+ * @param renderList that is cached from frame N-1
+ * @param attachmentList that is being used
+ */
+inline bool TryReuseCachedRenderers( Layer& layer,
+                                     RenderList& renderList,
+                                     RenderableAttachmentContainer& attachmentList )
+{
+  bool retValue = false;
+  size_t renderableCount = attachmentList.size();
+  // check that the cached list originates from this layer and that the counts match
+  if( ( renderList.GetSourceLayer() == &layer )&&
+      ( renderList.GetCachedItemCount() == renderableCount ) )
+  {
+    // check that all the same renderers are there. This gives us additional security in avoiding rendering the wrong attachments
+    // Attachments are not sorted, but render list is so at this stage renderers may be in different order
+    // therefore we check a combined sum of all renderer addresses
+    size_t checkSumNew = 0;
+    size_t checkSumOld = 0;
+    for( size_t index = 0; index < renderableCount; ++index )
+    {
+      RenderableAttachment* attachment = attachmentList[ index ];
+      const Renderer& renderer = attachment->GetRenderer();
+      checkSumNew += size_t( &renderer );
+      checkSumOld += size_t( renderList.GetRenderer( index ) );
+    }
+    if( checkSumNew == checkSumOld )
+    {
+      // tell list to reuse its existing items
+      renderList.ReuseCachedItems();
+      retValue = true;
+    }
+  }
+  return retValue;
+}
+
+
+/**
+ * Function which sorts render items by depth index then by instance
+ * ptrs of shader/geometry/material.
+ * @param lhs item
+ * @param rhs item
+ * @return true if left item is greater than right
+ */
+bool CompareItems( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
+{
+  // @todo MESH_REWORK Consider replacing all these sortAttributes with a single long int that
+  // encapsulates the same data (e.g. the middle-order bits of the ptrs)
+  if( lhs.renderItem->GetDepthIndex() == rhs.renderItem->GetDepthIndex() )
+  {
+    if( lhs.shader == rhs.shader )
+    {
+      if( lhs.material == rhs.material )
+      {
+        return lhs.geometry < rhs.geometry;
+      }
+      return lhs.material < rhs.material;
+    }
+    return lhs.shader < rhs.shader;;
+  }
+  return lhs.renderItem->GetDepthIndex() < rhs.renderItem->GetDepthIndex();
+}
+/**
+ * Function which sorts the render items by Z function, then
+ * by instance ptrs of shader/geometry/material.
+ * @param lhs item
+ * @param rhs item
+ * @return true if left item is greater than right
+ */
+bool CompareItems3D( const RendererWithSortAttributes& lhs, const RendererWithSortAttributes& rhs )
+{
+  bool lhsIsOpaque = lhs.renderItem->IsOpaque();
+  if( lhsIsOpaque ==  rhs.renderItem->IsOpaque())
+  {
+    if( lhsIsOpaque )
+    {
+      //If both RenderItems are opaque, sort using shader, then material then geometry
+      if( lhs.shader == rhs.shader )
+      {
+        if( lhs.material == rhs.material )
+        {
+          return lhs.geometry < rhs.geometry;
+        }
+        return lhs.material < rhs.material;
+      }
+      return lhs.shader < rhs.shader;
+    }
+    else
+    {
+      //If both RenderItems are transparent, sort using z,then shader, then material, then geometry
+      if( Equals(lhs.zValue, rhs.zValue) )
+      {
+        if( lhs.shader == rhs.shader )
+        {
+          if( lhs.material == rhs.material )
+          {
+            return lhs.geometry < rhs.geometry;
+          }
+          return lhs.material < rhs.material;
+        }
+        return lhs.shader < rhs.shader;
+      }
+      return lhs.zValue > rhs.zValue;
+    }
+  }
+  else
+  {
+    return lhsIsOpaque;
+  }
+}
+
+/**
+ * Sort color render items
+ * @param colorRenderList to sort
+ * @param layer where the renderers are from
+ * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ */
+inline void SortColorRenderItems( BufferIndex bufferIndex, RenderList& renderList, Layer& layer, RendererSortingHelper& sortingHelper )
+{
+  const size_t renderableCount = renderList.Count();
+  // reserve space if needed
+  const unsigned int oldcapacity = sortingHelper.size();
+  if( oldcapacity < renderableCount )
+  {
+    sortingHelper.reserve( renderableCount );
+    // add real objects (reserve does not construct objects)
+    sortingHelper.insert( sortingHelper.begin() + oldcapacity,
+                          (renderableCount - oldcapacity),
+                          RendererWithSortAttributes() );
+  }
+  else
+  {
+    // clear extra elements from helper, does not decrease capability
+    sortingHelper.resize( renderableCount );
+  }
+
+  // calculate the sorting value, once per item by calling the layers sort function
+  // Using an if and two for-loops rather than if inside for as its better for branch prediction
+  if( layer.UsesDefaultSortFunction() )
+  {
+    for( size_t index = 0; index < renderableCount; ++index )
+    {
+      RenderItem& item = renderList.GetItem( index );
+
+      //@todo MESH_REWORK After merge of RenderableAttachment and RendererAttachment, should instead store the renderable ptr and get the fields directly
+      layer.colorRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+
+      // the default sorting function should get inlined here
+      sortingHelper[ index ].zValue = Internal::Layer::ZValue( item.GetModelViewMatrix().GetTranslation3() ) - item.GetDepthIndex();
+
+      // keep the renderitem pointer in the helper so we can quickly reorder items after sort
+      sortingHelper[ index ].renderItem = &item;
+    }
+  }
+  else
+  {
+    const Dali::Layer::SortFunctionType sortFunction = layer.GetSortFunction();
+    for( size_t index = 0; index < renderableCount; ++index )
+    {
+      RenderItem& item = renderList.GetItem( index );
+
+      layer.colorRenderables[index]->SetSortAttributes( bufferIndex, sortingHelper[ index ] );
+      sortingHelper[ index ].zValue = (*sortFunction)( item.GetModelViewMatrix().GetTranslation3() ) - item.GetDepthIndex();
+
+      // keep the renderitem pointer in the helper so we can quickly reorder items after sort
+      sortingHelper[ index ].renderItem = &item;
+    }
+  }
+
+  if( layer.GetBehavior() ==  Dali::Layer::LAYER_3D)
+  {
+    // sort the renderers back to front, Z Axis point from near plane to far plane
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems3D );
+  }
+  else
+  {
+    // sort the renderers based on DepthIndex
+    std::stable_sort( sortingHelper.begin(), sortingHelper.end(), CompareItems );
+  }
+
+  // reorder/repopulate the renderitems in renderlist to correct order based on sortinghelper
+  DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "Sorted Transparent List:\n");
+  RenderItemContainer::Iterator renderListIter = renderList.GetContainer().Begin();
+  for( unsigned int index = 0; index < renderableCount; ++index, ++renderListIter )
+  {
+    *renderListIter = sortingHelper[ index ].renderItem;
+    DALI_LOG_INFO( gRenderListLogFilter, Debug::Verbose, "  sortedList[%d] = %p\n", index, sortingHelper[ index ].renderItem->GetRenderer() );
+  }
+}
+
+/**
+ * Add color renderers from the layer onto the next free render list
+ * @param updateBufferIndex to use
+ * @param layer to get the renderers from
+ * @param viewmatrix for the camera from rendertask
+ * @param cameraAttachment to use the view frustum
+ * @param stencilRenderablesExist is true if there are stencil renderers on this layer
+ * @param instruction to fill in
+ * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ */
+inline void AddColorRenderers( BufferIndex updateBufferIndex,
+                               Layer& layer,
+                               const Matrix& viewMatrix,
+                               SceneGraph::CameraAttachment& cameraAttachment,
+                               bool stencilRenderablesExist,
+                               RenderInstruction& instruction,
+                               RendererSortingHelper& sortingHelper,
+                               bool tryReuseRenderList )
+{
+  RenderList& renderList = instruction.GetNextFreeRenderList( layer.colorRenderables.size() );
+  renderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+  renderList.SetHasColorRenderItems( true );
+
+  // try to reuse cached renderitems from last time around
+  if( tryReuseRenderList )
+  {
+    if( TryReuseCachedRenderers( layer, renderList, layer.colorRenderables ) )
+    {
+      return;
+    }
+  }
+
+  AddRenderersToRenderList( updateBufferIndex, renderList, layer.colorRenderables, viewMatrix, cameraAttachment, layer.GetBehavior() == Dali::Layer::LAYER_3D );
+  SortColorRenderItems( updateBufferIndex, renderList, layer, sortingHelper );
+
+  //Set render flags
+  unsigned int flags = 0u;
+  if( stencilRenderablesExist )
+  {
+    flags = RenderList::STENCIL_BUFFER_ENABLED;
+  }
+
+  // Special optimization if depth test is disabled or if only one opaque rendered in the layer (for example background image)
+  // and this renderer does not need depth test against itself (e.g. mesh)
+  // and if this layer has got exactly one opaque renderer
+  // and this renderer is not interested in depth testing
+  // (i.e. is an image and not a mesh)
+  if ( ( renderList.Count() == 1 ) &&
+       ( !renderList.GetRenderer( 0 )->RequiresDepthTest() ) &&
+       ( !renderList.GetItem(0).IsOpaque() ) )
+  {
+    //Nothing to do here
+  }
+  else if( !layer.IsDepthTestDisabled())
+  {
+    flags |= RenderList::DEPTH_BUFFER_ENABLED;
+    flags |= RenderList::DEPTH_CLEAR;
+  }
+
+  renderList.ClearFlags();
+  renderList.SetFlags( flags );
+}
+
+/**
+ * Add overlay renderers from the layer onto the next free render list
+ * @param updateBufferIndex to use
+ * @param layer to get the renderers from
+ * @param viewmatrix for the camera from rendertask
+ * @param stencilRenderablesExist is true if there are stencil renderers on this layer
+ * @param instruction to fill in
+ * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ */
+inline void AddOverlayRenderers( BufferIndex updateBufferIndex,
+                                 Layer& layer,
+                                 const Matrix& viewMatrix,
+                                 SceneGraph::CameraAttachment& cameraAttachment,
+                                 bool stencilRenderablesExist,
+                                 RenderInstruction& instruction,
+                                 bool tryReuseRenderList )
+{
+  RenderList& overlayRenderList = instruction.GetNextFreeRenderList( layer.overlayRenderables.size() );
+  overlayRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+  overlayRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  overlayRenderList.ClearFlags();
+  if(stencilRenderablesExist)
+  {
+    overlayRenderList.SetFlags(RenderList::STENCIL_BUFFER_ENABLED);
+  }
+
+  // try to reuse cached renderitems from last time around
+  if( tryReuseRenderList )
+  {
+    if( TryReuseCachedRenderers( layer, overlayRenderList, layer.overlayRenderables ) )
+    {
+      return;
+    }
+  }
+  AddRenderersToRenderList( updateBufferIndex, overlayRenderList, layer.overlayRenderables, viewMatrix, cameraAttachment, layer.GetBehavior() == Dali::Layer::LAYER_3D );
+}
+
+/**
+ * Add stencil renderers from the layer onto the next free render list
+ * @param updateBufferIndex to use
+ * @param layer to get the renderers from
+ * @param viewmatrix for the camera from rendertask
+ * @param instruction to fill in
+ * @param tryReuseRenderList whether to try to reuse the cached items from the instruction
+ */
+inline void AddStencilRenderers( BufferIndex updateBufferIndex,
+                                 Layer& layer,
+                                 const Matrix& viewMatrix,
+                                 SceneGraph::CameraAttachment& cameraAttachment,
+                                 RenderInstruction& instruction,
+                                 bool tryReuseRenderList )
+{
+  RenderList& stencilRenderList = instruction.GetNextFreeRenderList( layer.stencilRenderables.size() );
+  stencilRenderList.SetClipping( layer.IsClipping(), layer.GetClippingBox() );
+  stencilRenderList.SetHasColorRenderItems( false );
+
+  //Set render flags
+  stencilRenderList.ClearFlags();
+  stencilRenderList.SetFlags(RenderList::STENCIL_CLEAR | RenderList::STENCIL_WRITE | RenderList::STENCIL_BUFFER_ENABLED );
+
+  // try to reuse cached renderitems from last time around
+  if( tryReuseRenderList )
+  {
+    if( TryReuseCachedRenderers( layer, stencilRenderList, layer.stencilRenderables ) )
+    {
+      return;
+    }
+  }
+  AddRenderersToRenderList( updateBufferIndex, stencilRenderList, layer.stencilRenderables, viewMatrix, cameraAttachment, layer.GetBehavior() == Dali::Layer::LAYER_3D );
+}
+
+/**
+ * Prepare a single render instruction
+ * @param updateBufferIndex to use
+ * @param sortedLayers to prepare the instruction from
+ * @param renderTask to get the view matrix
+ * @param sortingHelper to use for sorting the renderitems (to avoid reallocating)
+ * @param renderTracker An optional render tracker object
+ * @param instructions container
+ */
+void PrepareRenderInstruction( BufferIndex updateBufferIndex,
+                               SortedLayerPointers& sortedLayers,
+                               RenderTask& renderTask,
+                               RendererSortingHelper& sortingHelper,
+                               RenderTracker* renderTracker,
+                               RenderInstructionContainer& instructions )
+{
+  // Retrieve the RenderInstruction buffer from the RenderInstructionContainer
+  // then populate with instructions.
+  RenderInstruction& instruction = instructions.GetNextInstruction( updateBufferIndex );
+  renderTask.PrepareRenderInstruction( instruction, updateBufferIndex );
+  bool viewMatrixHasNotChanged = !renderTask.ViewMatrixUpdated();
+
+  const Matrix& viewMatrix = renderTask.GetViewMatrix( updateBufferIndex );
+  SceneGraph::CameraAttachment& cameraAttachment = renderTask.GetCameraAttachment();
+
+  const SortedLayersIter endIter = sortedLayers.end();
+  for ( SortedLayersIter iter = sortedLayers.begin(); iter != endIter; ++iter )
+  {
+    Layer& layer = **iter;
+
+    const bool stencilRenderablesExist( !layer.stencilRenderables.empty() );
+    const bool colorRenderablesExist( !layer.colorRenderables.empty() );
+    const bool overlayRenderablesExist( !layer.overlayRenderables.empty() );
+    const bool tryReuseRenderList( viewMatrixHasNotChanged && layer.CanReuseRenderers(renderTask.GetCamera()) );
+
+    // Ignore stencils if there's nothing to test
+    if( stencilRenderablesExist &&
+        ( colorRenderablesExist || overlayRenderablesExist ) )
+    {
+      AddStencilRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, instruction, tryReuseRenderList );
+    }
+
+    if ( colorRenderablesExist )
+    {
+      AddColorRenderers( updateBufferIndex,
+                         layer,
+                         viewMatrix,
+                         cameraAttachment,
+                         stencilRenderablesExist,
+                         instruction,
+                         sortingHelper,
+                         tryReuseRenderList );
+    }
+
+    if ( overlayRenderablesExist )
+    {
+      AddOverlayRenderers( updateBufferIndex, layer, viewMatrix, cameraAttachment, stencilRenderablesExist,
+                           instruction, tryReuseRenderList );
+    }
+  }
+
+  instruction.mRenderTracker = renderTracker;
+  instruction.mCullMode = renderTask.GetCullMode();
+
+  // inform the render instruction that all renderers have been added and this frame is complete
+  instruction.UpdateCompleted();
+}
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/update/manager/prepare-render-instructions.h b/dali/internal/update/manager/prepare-render-instructions.h
new file mode 100644 (file)
index 0000000..d8e794f
--- /dev/null
@@ -0,0 +1,96 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/manager/sorted-layers.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderTracker;
+class RenderItem;
+class Shader;
+class Material;
+class Geometry;
+
+/**
+ * Structure to store information for sorting the renderers.
+ * (Note, depthIndex is stored within the renderItem).
+ */
+struct RendererWithSortAttributes
+{
+  RendererWithSortAttributes()
+  : renderItem( NULL ),
+    shader(NULL),
+    material(NULL),
+    geometry(NULL),
+    zValue(0.0f)
+  {
+  }
+
+  RenderItem* renderItem;       ///< The render item that is being sorted (includes depth index)
+  Shader*     shader;           ///< The shader instance
+  Material*   material;         ///< The material instance
+  Geometry*   geometry;         ///< The geometry instance
+  float       zValue;           // The zValue of the given renderer (either distance from camera, or a custom calculated value)
+};
+
+typedef std::vector< RendererWithSortAttributes > RendererSortingHelper;
+
+class RenderTask;
+class RenderInstructionContainer;
+
+/**
+ * Sorts and prepares the list of opaque/transparent renderable
+ * attachments for each layer.  Whilst iterating through each layer,
+ * update the attachments ModelView matrices
+ *
+ * The opaque and transparent render lists are sorted first by depth
+ * index, then by Z (for transparent only), then by shader, material
+ * and geometry. The render algorithm should then work through both
+ * lists simultaneously, working through opaque then transparent
+ * items at each depth index, resetting the flags appropriately.
+ *
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables.
+ * @param[in] renderTask The rendering task information.
+ * @param[in] renderTracker A tracker object if we need to know when this render instruction has actually rendered, or NULL if tracking is not required
+ * @param[out] instructions The rendering instructions for the next frame.
+ */
+void PrepareRenderInstruction( BufferIndex updateBufferIndex,
+                               SortedLayerPointers& sortedLayers,
+                               RenderTask& renderTask,
+                               RendererSortingHelper& sortingHelper,
+                               RenderTracker* renderTracker,
+                               RenderInstructionContainer& instructions );
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PREPARE_RENDER_INSTRUCTIONS_H__
diff --git a/dali/internal/update/manager/process-render-tasks.cpp b/dali/internal/update/manager/process-render-tasks.cpp
new file mode 100644 (file)
index 0000000..1bf0e85
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/process-render-tasks.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/manager/prepare-render-instructions.h>
+#include <dali/internal/update/manager/prepare-render-algorithms.h>
+#include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+#include <dali/internal/update/resources/sync-resource-tracker.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/render/common/render-item.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/render/common/render-instruction.h>
+#include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/integration-api/debug.h>
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gRenderTaskLogFilter;
+#endif
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+// Return false if the node or it's parents are exclusive to another render-task
+static bool CheckExclusivity( const Node& node, const RenderTask& task )
+{
+  const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
+  if ( exclusiveTo )
+  {
+    if ( exclusiveTo == &task )
+    {
+      // Exclusive to the same render-task
+      return true;
+    }
+    else
+    {
+      // Exclusive to another render-task
+      return false;
+    }
+  }
+
+  const Node* parent = node.GetParent();
+  if ( parent )
+  {
+    return CheckExclusivity( *parent, task );
+  }
+
+  // No exclusive flags set
+  return true;
+}
+
+static Layer* FindLayer( Node& node )
+{
+  if ( node.IsLayer() )
+  {
+    return node.GetLayer();
+  }
+
+  Node* parent = node.GetParent();
+  // if the node is taken off stage we may get NULL parent
+  if( NULL == parent )
+  {
+    return NULL;
+  }
+
+
+  return FindLayer( *parent );
+}
+
+/**
+ * Rebuild the Layer::opaqueRenderables, transparentRenderables and overlayRenderables members,
+ * including only renderable-attachments which are included in the current render-task.
+ * Returns true if all renderable attachments have finshed acquiring resources.
+ */
+static bool AddRenderablesForTask( BufferIndex updateBufferIndex,
+                                   Node& node,
+                                   Layer& currentLayer,
+                                   RenderTask& renderTask,
+                                   int inheritedDrawMode )
+{
+  bool resourcesFinished = true;
+  bool forceRender = false;
+  const RenderTask* exclusiveTo = node.GetExclusiveRenderTask();
+
+  // Cater for edge case where node is exclusively owned, the render task is REFRESH_ONCE, but the parent may be invisible.
+  if ( exclusiveTo && Dali::RenderTask::REFRESH_ONCE == renderTask.GetRefreshRate() )
+  {
+    forceRender = true;
+  }
+
+  // Short-circuit for invisible nodes
+  if ( !node.IsVisible( updateBufferIndex ) )
+  {
+    return resourcesFinished;
+  }
+
+  // Check whether node is exclusive to a different render-task
+  if ( exclusiveTo &&
+       exclusiveTo != &renderTask )
+  {
+    return resourcesFinished;
+  }
+
+  Layer* layer = &currentLayer;
+
+  if ( node.IsLayer() )
+  {
+    // All children go to this layer
+    layer = node.GetLayer();
+
+    // Layers do not inherit the DrawMode from their parents
+    inheritedDrawMode = DrawMode::NORMAL;
+  }
+  DALI_ASSERT_DEBUG( NULL != layer );
+
+  inheritedDrawMode |= node.GetDrawMode();
+
+  if ( node.HasAttachment() )
+  {
+    RenderableAttachment* renderable = node.GetAttachment().GetRenderable(); // not all attachments render
+    if ( renderable )
+    {
+      bool visible = renderable->HasVisibleSizeAndColor();
+      // if its not potentially visible, then don't consider this renderable for render complete checking
+      // note that whilst visibility is inherited (if parent is insible, skip the sub-tree),
+      // size and color may not be so this needs to be done per renderable
+      if( visible || forceRender ) // i.e. some resources are ready
+      {
+        bool ready = false;
+        bool complete = false;
+        renderable->GetReadyAndComplete(ready, complete);
+
+        DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Testing renderable:%p ready:%s complete:%s\n", renderable, ready?"T":"F", complete?"T":"F");
+
+        resourcesFinished = !complete ? complete : resourcesFinished;
+
+        if( ready ) // i.e. some resources are ready
+        {
+          if( DrawMode::STENCIL == inheritedDrawMode )
+          {
+            layer->stencilRenderables.push_back( renderable );
+          }
+          else if( DrawMode::OVERLAY_2D == inheritedDrawMode )
+          {
+            layer->overlayRenderables.push_back( renderable );
+          }
+          else
+          {
+            layer->colorRenderables.push_back( renderable );
+          }
+        }
+      }
+    }
+  }
+
+  // Recurse children
+  NodeContainer& children = node.GetChildren();
+  const NodeIter endIter = children.End();
+  for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
+  {
+    Node& child = **iter;
+    bool childResourcesComplete = AddRenderablesForTask( updateBufferIndex, child, *layer, renderTask, inheritedDrawMode );
+    resourcesFinished = !childResourcesComplete ? childResourcesComplete : resourcesFinished;
+  }
+
+  return resourcesFinished;
+}
+
+void ProcessRenderTasks( BufferIndex updateBufferIndex,
+                         CompleteStatusManager& completeStatusManager,
+                         RenderTaskList& renderTasks,
+                         Layer& rootNode,
+                         SortedLayerPointers& sortedLayers,
+                         RendererSortingHelper& sortingHelper,
+                         RenderInstructionContainer& instructions )
+{
+  RenderTaskList::RenderTaskContainer& taskContainer = renderTasks.GetTasks();
+
+  if ( taskContainer.IsEmpty() )
+  {
+    // Early-exit if there are no tasks to process
+    return;
+  }
+
+  // For each render-task:
+  //   1) Prepare the render-task
+  //   2) Clear the layer-stored lists of attachments (TODO check if the layer is not changed and don't clear in this case)
+  //   3) Traverse the scene-graph, filling the lists for the current render-task
+  //   4) Prepare render-instructions
+
+  DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Offscreens first\n");
+
+  // First process off screen render tasks - we may need the results of these for the on screen renders
+  RenderTaskList::RenderTaskContainer::ConstIterator endIter = taskContainer.End();
+  for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
+  {
+    RenderTask& renderTask = **iter;
+
+    // off screen only
+    if(0 == renderTask.GetFrameBufferId())
+    {
+      // Skip to next task
+      continue;
+    }
+
+    if ( !renderTask.ReadyToRender( updateBufferIndex ) )
+    {
+      // Skip to next task
+      continue;
+    }
+
+    Node* sourceNode = renderTask.GetSourceNode();
+    DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
+
+    // Check that the source node is not exclusive to another task
+    if ( ! CheckExclusivity( *sourceNode, renderTask ) )
+    {
+      continue;
+    }
+
+    Layer* layer = FindLayer( *sourceNode );
+    if( !layer )
+    {
+      // Skip to next task as no layer
+      continue;
+    }
+
+    bool resourcesFinished = false;
+    if( renderTask.IsRenderRequired() )
+    {
+      ClearRenderables( sortedLayers );
+
+      resourcesFinished = AddRenderablesForTask( updateBufferIndex,
+                                                 *sourceNode,
+                                                 *layer,
+                                                 renderTask,
+                                                 sourceNode->GetDrawMode() );
+
+      // Set update trackers to complete, or get render trackers to pass onto render thread
+      RenderTracker* renderTracker = NULL;
+      if( resourcesFinished )
+      {
+        Integration::ResourceId id = renderTask.GetFrameBufferId();
+        ResourceTracker* resourceTracker = completeStatusManager.FindResourceTracker( id );
+        if( resourceTracker != NULL )
+        {
+          resourceTracker->SetComplete(); // Has no effect on GlResourceTracker
+
+          SyncResourceTracker* syncResourceTracker = dynamic_cast<SyncResourceTracker*>(resourceTracker);
+          if( syncResourceTracker != NULL )
+          {
+            renderTracker = syncResourceTracker->GetRenderTracker();
+          }
+        }
+      }
+
+      PrepareRenderInstruction( updateBufferIndex,
+                                sortedLayers,
+                                renderTask,
+                                sortingHelper,
+                                renderTracker,
+                                instructions );
+    }
+
+    renderTask.SetResourcesFinished( resourcesFinished );
+  }
+
+  DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "ProcessRenderTasks() Onscreen\n");
+
+  // Now that the off screen renders are done we can process on screen render tasks
+  for ( RenderTaskList::RenderTaskContainer::Iterator iter = taskContainer.Begin(); endIter != iter; ++iter )
+  {
+    RenderTask& renderTask = **iter;
+
+    // on screen only
+    if(0 != renderTask.GetFrameBufferId())
+    {
+      // Skip to next task
+      continue;
+    }
+    if ( !renderTask.ReadyToRender( updateBufferIndex ) )
+    {
+      // Skip to next task
+      continue;
+    }
+
+    Node* sourceNode = renderTask.GetSourceNode();
+    DALI_ASSERT_DEBUG( NULL != sourceNode ); // otherwise Prepare() should return false
+
+    // Check that the source node is not exclusive to another task
+    if ( ! CheckExclusivity( *sourceNode, renderTask ) )
+    {
+      continue;
+    }
+
+    Layer* layer = FindLayer( *sourceNode );
+    if( !layer )
+    {
+      // Skip to next task as no layer
+      continue;
+    }
+
+    bool resourcesFinished = false;
+    if( renderTask.IsRenderRequired() )
+    {
+      ClearRenderables( sortedLayers );
+
+      resourcesFinished = AddRenderablesForTask( updateBufferIndex,
+                                                 *sourceNode,
+                                                 *layer,
+                                                 renderTask,
+                                                 sourceNode->GetDrawMode() );
+
+      PrepareRenderInstruction( updateBufferIndex,
+                                sortedLayers,
+                                renderTask,
+                                sortingHelper,
+                                NULL,
+                                instructions );
+    }
+
+    renderTask.SetResourcesFinished( resourcesFinished );
+  }
+}
+
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/update/manager/process-render-tasks.h b/dali/internal/update/manager/process-render-tasks.h
new file mode 100644 (file)
index 0000000..3607e49
--- /dev/null
@@ -0,0 +1,62 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/manager/prepare-render-instructions.h>
+
+namespace Dali
+{
+namespace Internal
+{
+class CompleteStatusManager;
+
+namespace SceneGraph
+{
+
+class RenderTaskList;
+
+/**
+ * Process the list of render-tasks; the output is a series of render instructions.
+ * @note When ProcessRenderTasks is called, the layers should already the transparent/opaque attachments which are ready to render.
+ * If there is only one default render-task, then no further processing is required.
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] completeStatusManager The resource complete state manager
+ * @param[in] renderTasks The list of render-tasks.
+ * @param[in] rootNode The root node of the scene-graph.
+ * @param[in] sortedLayers The layers containing lists of opaque/transparent renderables.
+ * @param[in] sortingHelper Helper container for sorting transparent renderables.
+ * @param[out] instructions The instructions for rendering the next frame.
+ */
+void ProcessRenderTasks( BufferIndex updateBufferIndex,
+                         CompleteStatusManager& completeStatusManager,
+                         RenderTaskList& renderTasks,
+                         Layer& rootNode,
+                         SortedLayerPointers& sortedLayers,
+                         RendererSortingHelper& sortingHelper,
+                         RenderInstructionContainer& instructions );
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_PROCESS_RENDER_TASKS_H__
diff --git a/dali/internal/update/manager/sorted-layers.h b/dali/internal/update/manager/sorted-layers.h
new file mode 100644 (file)
index 0000000..3e51fd1
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_SORTED_LAYERS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_SORTED_LAYERS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Layer;
+
+/**
+ * A container of Layer pointers sorted by depth
+ */
+typedef std::vector<Layer*> SortedLayerPointers;
+
+typedef SortedLayerPointers::iterator       SortedLayersIter;
+typedef SortedLayerPointers::const_iterator SortedLayersConstIter;
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_SORTED_LAYERS_H__
diff --git a/dali/internal/update/manager/update-algorithms.cpp b/dali/internal/update/manager/update-algorithms.cpp
new file mode 100644 (file)
index 0000000..2e296dc
--- /dev/null
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/update-algorithms.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/draw-mode.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/update/animation/scene-graph-constraint-base.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gUpdateFilter = Debug::Filter::New(Debug::Concise, false, "LOG_UPDATE_ALGORITHMS");
+#endif
+
+/******************************************************************************
+ *********************** Apply Constraints ************************************
+ ******************************************************************************/
+
+
+/**
+ * Constrain the local properties of the PropertyOwner.
+ * @param propertyOwner to constrain
+ * @param updateBufferIndex buffer index to use
+ * @return The number of constraints that are still being applied
+ */
+void ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex )
+{
+  ConstraintOwnerContainer& constraints = propertyOwner.GetConstraints();
+
+  const ConstraintIter endIter = constraints.End();
+  for( ConstraintIter iter = constraints.Begin(); iter != endIter; ++iter )
+  {
+    ConstraintBase& constraint = **iter;
+    constraint.Apply( updateBufferIndex );
+  }
+}
+
+/**
+ * Recursively apply the constraints on the nodes
+ * @param node to constraint
+ * @param updateBufferIndex buffer index to use
+ * @return number of active constraints
+ */
+void ConstrainNodes( Node& node, BufferIndex updateBufferIndex )
+{
+  ConstrainPropertyOwner( node, updateBufferIndex );
+
+  if( node.HasAttachment() )
+  {
+    // @todo MESH_REWORK Remove dynamic cast.
+    // (Or, if RendererAttachment split into RendererPropertyOwner(?),
+    // do as separate pass as per other mesh objects - see also
+    // UpdateManager::ResetNodeProperty())
+    NodeAttachment& attachment = node.GetAttachment();
+    PropertyOwner* propertyOwner = dynamic_cast< PropertyOwner* >( &attachment );
+    if( propertyOwner != NULL )
+    {
+      ConstrainPropertyOwner( *propertyOwner, updateBufferIndex );
+    }
+  }
+
+  /**
+   *  Constrain the children next
+   */
+  NodeContainer& children = node.GetChildren();
+  const NodeIter endIter = children.End();
+  for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
+  {
+    Node& child = **iter;
+    ConstrainNodes( child, updateBufferIndex );
+  }
+}
+
+/******************************************************************************
+ ************************** Update node hierarchy *****************************
+ ******************************************************************************/
+
+inline void UpdateRootNodeOpacity( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  if ( nodeDirtyFlags & ColorFlag )
+  {
+    rootNode.SetWorldColor( rootNode.GetColor( updateBufferIndex ), updateBufferIndex );
+  }
+  else
+  {
+    // Copy previous value, in case it changed in the previous frame
+    rootNode.CopyPreviousWorldColor( updateBufferIndex );
+  }
+}
+
+inline void UpdateNodeOpacity( Node& node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  // If opacity needs to be recalculated
+  if ( nodeDirtyFlags & ColorFlag )
+  {
+    node.InheritWorldColor( updateBufferIndex );
+  }
+  else
+  {
+    // Copy inherited value, if changed in the previous frame
+    node.CopyPreviousWorldColor( updateBufferIndex );
+  }
+}
+
+inline void UpdateRootNodeTransformValues( Layer& rootNode, int nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  // If the transform values need to be reinherited
+  if ( nodeDirtyFlags & TransformFlag )
+  {
+    rootNode.SetWorldPosition( updateBufferIndex, rootNode.GetPosition( updateBufferIndex ) );
+    rootNode.SetWorldOrientation( updateBufferIndex, rootNode.GetOrientation( updateBufferIndex ) );
+    rootNode.SetWorldScale   ( updateBufferIndex, rootNode.GetScale   ( updateBufferIndex ) );
+  }
+  else
+  {
+    // Copy previous value, in case they changed in the previous frame
+    rootNode.CopyPreviousWorldOrientation( updateBufferIndex );
+    rootNode.CopyPreviousWorldScale( updateBufferIndex );
+    rootNode.CopyPreviousWorldPosition( updateBufferIndex );
+  }
+}
+
+/**
+ * Updates transform values for the given node if the transform flag is dirty.
+  * Note that this will cause the size dirty flag to be set. This is why we pass
+ * the dirty flags in by reference.
+ * @param[in]     node The node to update
+ * @param[in,out] nodeDirtyFlags A reference to the dirty flags, these may be modified by this function
+ * @param[in]     updateBufferIndex The current index to use for this frame
+ */
+inline void UpdateNodeTransformValues( Node& node, int& nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  // If the transform values need to be reinherited
+  if( nodeDirtyFlags & TransformFlag )
+  {
+    // With a non-central anchor-point, the world rotation and scale affects the world position.
+    // Therefore the world rotation & scale must be updated before the world position.
+    if( node.IsOrientationInherited() )
+    {
+      node.InheritWorldOrientation( updateBufferIndex );
+    }
+    else
+    {
+      node.SetWorldOrientation( updateBufferIndex, node.GetOrientation( updateBufferIndex ) );
+    }
+
+    if( node.IsScaleInherited() )
+    {
+      node.InheritWorldScale( updateBufferIndex );
+    }
+    else
+    {
+      node.SetWorldScale( updateBufferIndex, node.GetScale( updateBufferIndex ) );
+    }
+
+    node.InheritWorldPosition( updateBufferIndex );
+  }
+  else
+  {
+    // Copy inherited values, if those changed in the previous frame
+    node.CopyPreviousWorldOrientation( updateBufferIndex );
+    node.CopyPreviousWorldScale( updateBufferIndex );
+    node.CopyPreviousWorldPosition( updateBufferIndex );
+    node.CopyPreviousSize( updateBufferIndex );
+  }
+}
+
+inline void UpdateNodeWorldMatrix( Node &node, int nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  // If world-matrix needs to be recalculated
+  if ( nodeDirtyFlags & TransformFlag )
+  {
+    if( node.GetInhibitLocalTransform() )
+    {
+      node.SetWorldMatrix( updateBufferIndex,
+                           node.GetWorldScale(updateBufferIndex),
+                           node.GetWorldOrientation(updateBufferIndex) / node.GetOrientation(updateBufferIndex),
+                           node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
+    }
+    else
+    {
+      node.SetWorldMatrix( updateBufferIndex,
+                           node.GetWorldScale(updateBufferIndex),
+                           node.GetWorldOrientation(updateBufferIndex),
+                           node.GetWorldPosition(updateBufferIndex) );
+    }
+  }
+  else
+  {
+    node.CopyPreviousWorldMatrix( updateBufferIndex );
+  }
+}
+
+inline void UpdateNodeWorldMatrix( Node& node, RenderableAttachment& updatedRenderable, int nodeDirtyFlags, BufferIndex updateBufferIndex )
+{
+  /**
+   * If world-matrix needs to be recalculated.
+   */
+  if ( ( nodeDirtyFlags & TransformFlag ) ||
+         updatedRenderable.IsScaleForSizeDirty() )
+  {
+    if( updatedRenderable.UsesGeometryScaling() )
+    {
+      // TODO: MESH_REWORK : remove scale for size
+      Vector3 scaling;
+      updatedRenderable.GetScaleForSize( node.GetSize( updateBufferIndex ), scaling );
+      if( node.GetInhibitLocalTransform() )
+      {
+        node.SetWorldMatrix( updateBufferIndex,
+                             node.GetWorldScale(updateBufferIndex) * scaling,
+                             node.GetWorldOrientation(updateBufferIndex) / node.GetOrientation(updateBufferIndex),
+                             node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
+      }
+      else
+      {
+        node.SetWorldMatrix( updateBufferIndex,
+                             node.GetWorldScale(updateBufferIndex) * scaling,
+                             node.GetWorldOrientation(updateBufferIndex),
+                             node.GetWorldPosition(updateBufferIndex) );
+      }
+    }
+    else
+    {
+      // no scaling, i.e. Image
+      if( node.GetInhibitLocalTransform() )
+      {
+        node.SetWorldMatrix( updateBufferIndex,
+                             node.GetWorldScale(updateBufferIndex),
+                             node.GetWorldOrientation(updateBufferIndex) / node.GetOrientation(updateBufferIndex),
+                             node.GetWorldPosition(updateBufferIndex) - node.GetPosition(updateBufferIndex) );
+      }
+      else
+      {
+        node.SetWorldMatrix( updateBufferIndex,
+                             node.GetWorldScale(updateBufferIndex),
+                             node.GetWorldOrientation(updateBufferIndex),
+                             node.GetWorldPosition(updateBufferIndex) );
+      }
+    }
+  }
+  else
+  {
+    node.CopyPreviousWorldMatrix( updateBufferIndex );
+  }
+}
+
+/**
+ * Update an attachment.
+ * @return An updated renderable attachment if one was ready.
+ */
+inline RenderableAttachment* UpdateAttachment( NodeAttachment& attachment,
+                                               Node& node,
+                                               BufferIndex updateBufferIndex,
+                                               ResourceManager& resourceManager,
+                                               int nodeDirtyFlags )
+{
+  // Allow attachments to do specialised processing during updates
+  attachment.Update( updateBufferIndex, node, nodeDirtyFlags );
+
+  RenderableAttachment* renderable = attachment.GetRenderable(); // not all scene objects render
+  if( renderable )
+  {
+    // Notify renderables when size has changed
+    // Size can change while node was invisible so we need to check size again if we were previously invisible
+    if( nodeDirtyFlags & (SizeFlag|VisibleFlag) )
+    {
+      renderable->SizeChanged( updateBufferIndex );
+    }
+
+    // check if node is visible
+    if( renderable->ResolveVisibility( updateBufferIndex ) )
+    {
+      renderable->PrepareResources( updateBufferIndex, resourceManager );
+    }
+  }
+  return renderable;
+}
+
+inline void AddRenderableToLayer( Layer& layer,
+                                  RenderableAttachment& renderable,
+                                  BufferIndex updateBufferIndex,
+                                  int inheritedDrawMode )
+{
+  // The renderables are stored into the opaque list temporarily for PrepareRenderables()
+  // step. The list is cleared by ProcessRenderTasks().
+  layer.colorRenderables.push_back( &renderable );
+}
+
+/**
+ * This is called recursively for all children of the root Node
+ */
+inline int UpdateNodesAndAttachments( Node& node,
+                                      int parentFlags,
+                                      BufferIndex updateBufferIndex,
+                                      ResourceManager& resourceManager,
+                                      RenderQueue& renderQueue,
+                                      Layer& currentLayer,
+                                      int inheritedDrawMode )
+{
+  Layer* layer = &currentLayer;
+
+  // Short-circuit for invisible nodes
+  if ( !node.IsVisible( updateBufferIndex ) )
+  {
+    return 0;
+  }
+
+  // If the node was not previously visible
+  BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
+  if ( !node.IsVisible( previousBuffer ) )
+  {
+    // The node was skipped in the previous update; it must recalculate everything
+    node.SetAllDirtyFlags();
+  }
+
+  // Some dirty flags are inherited from parent
+  int nodeDirtyFlags( node.GetDirtyFlags() | ( parentFlags & InheritedDirtyFlags ) );
+
+  int cumulativeDirtyFlags = nodeDirtyFlags;
+
+  if ( node.IsLayer() )
+  {
+    // all childs go to this layer
+    layer = node.GetLayer();
+
+    // assume layer is clean to begin with
+    layer->SetReuseRenderers( updateBufferIndex, true );
+
+    // Layers do not inherit the DrawMode from their parents
+    inheritedDrawMode = DrawMode::NORMAL;
+  }
+  DALI_ASSERT_DEBUG( NULL != layer );
+
+  UpdateNodeOpacity( node, nodeDirtyFlags, updateBufferIndex );
+
+  // Note: nodeDirtyFlags are passed in by reference and may be modified by the following function.
+  // It is important that the modified version of these flags are used by the RenderableAttachment.
+  UpdateNodeTransformValues( node, nodeDirtyFlags, updateBufferIndex );
+
+  // Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited.
+  inheritedDrawMode |= node.GetDrawMode();
+
+  if ( node.HasAttachment() )
+  {
+    /*
+     * Add renderables for the children into the current Layer
+     */
+    RenderableAttachment* renderable = UpdateAttachment( node.GetAttachment(),
+                                                         node,
+                                                         updateBufferIndex,
+                                                         resourceManager,
+                                                         nodeDirtyFlags );
+
+
+    if( NULL != renderable )
+    {
+      // Update the world matrix after renderable update; the ScaleForSize property should now be calculated
+      UpdateNodeWorldMatrix( node, *renderable, nodeDirtyFlags, updateBufferIndex );
+
+      // The attachment is ready to render, so it is added to a set of renderables.
+      AddRenderableToLayer( *layer, *renderable, updateBufferIndex, inheritedDrawMode );
+    }
+  }
+  else if( node.IsObserved() )
+  {
+    // This node is being used as a property input for an animation, constraint,
+    // camera or bone. Ensure it's matrix is updated
+    UpdateNodeWorldMatrix( node, nodeDirtyFlags, updateBufferIndex );
+  }
+
+  // if any child node has moved or had its sort modifier changed, layer is not clean and old frame cannot be reused
+  // also if node has been deleted, dont reuse old render items
+  if( nodeDirtyFlags & RenderableUpdateFlags )
+  {
+    layer->SetReuseRenderers( updateBufferIndex, false );
+  }
+
+  // recurse children
+  NodeContainer& children = node.GetChildren();
+  const NodeIter endIter = children.End();
+  for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
+  {
+    Node& child = **iter;
+    cumulativeDirtyFlags |=UpdateNodesAndAttachments( child,
+                                                      nodeDirtyFlags,
+                                                      updateBufferIndex,
+                                                      resourceManager,
+                                                      renderQueue,
+                                                      *layer,
+                                                      inheritedDrawMode );
+  }
+
+  return cumulativeDirtyFlags;
+}
+
+/**
+ * The root node is treated separately; it cannot inherit values since it has no parent
+ */
+int UpdateNodesAndAttachments( Layer& rootNode,
+                               BufferIndex updateBufferIndex,
+                               ResourceManager& resourceManager,
+                               RenderQueue& renderQueue )
+{
+  DALI_ASSERT_DEBUG( rootNode.IsRoot() );
+
+  // Short-circuit for invisible nodes
+  if ( !rootNode.IsVisible( updateBufferIndex ) )
+  {
+    return 0;
+  }
+
+  // If the root node was not previously visible
+  BufferIndex previousBuffer = updateBufferIndex ? 0u : 1u;
+  if ( !rootNode.IsVisible( previousBuffer ) )
+  {
+    // The node was skipped in the previous update; it must recalculate everything
+    rootNode.SetAllDirtyFlags();
+  }
+
+  int nodeDirtyFlags( rootNode.GetDirtyFlags() );
+
+  int cumulativeDirtyFlags = nodeDirtyFlags;
+
+  UpdateRootNodeOpacity( rootNode, nodeDirtyFlags, updateBufferIndex );
+
+  UpdateRootNodeTransformValues( rootNode, nodeDirtyFlags, updateBufferIndex );
+
+  DrawMode::Type drawMode( rootNode.GetDrawMode() );
+
+  // recurse children
+  NodeContainer& children = rootNode.GetChildren();
+  const NodeIter endIter = children.End();
+  for ( NodeIter iter = children.Begin(); iter != endIter; ++iter )
+  {
+    Node& child = **iter;
+    cumulativeDirtyFlags |= UpdateNodesAndAttachments( child,
+                                                       nodeDirtyFlags,
+                                                       updateBufferIndex,
+                                                       resourceManager,
+                                                       renderQueue,
+                                                       rootNode,
+                                                       drawMode );
+  }
+
+  return cumulativeDirtyFlags;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/manager/update-algorithms.h b/dali/internal/update/manager/update-algorithms.h
new file mode 100644 (file)
index 0000000..118b264
--- /dev/null
@@ -0,0 +1,77 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_UPDATE_ALGORITHMS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_UPDATE_ALGORITHMS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class ResourceManager;
+
+namespace SceneGraph
+{
+
+class Layer;
+class Node;
+class PropertyOwner;
+class RenderQueue;
+
+/**
+ * Recursively apply the constraints on the nodes.
+ * @param[in] node to constraint.
+ * @param[in] updateBufferIndex The current update buffer index.
+  */
+void ConstrainNodes( Node& node, BufferIndex updateBufferIndex );
+
+/**
+ * Constrain the local properties of the PropertyOwner.
+ * @param[in] propertyOwner The PropertyOwner to constrain
+ * @param[in] updateBufferIndex The current update buffer index.
+ */
+void ConstrainPropertyOwner( PropertyOwner& propertyOwner, BufferIndex updateBufferIndex );
+
+/**
+ * Update a tree of nodes, and attached objects.
+ * The inherited properties of each node are recalculated if necessary.
+ * When a renderable attachment is ready to render, PrepareResources() is called and
+ * it is added to the list for its Layer.
+ * @param[in] rootNode The root of a tree of nodes.
+ * @param[in] updateBufferIndex The current update buffer index.
+ * @param[in] resourceManager The resource manager.
+ * @param[in] renderQueue Used to query messages for the next Render.
+ * @return The cumulative (ORed) dirty flags for the updated nodes
+ */
+int UpdateNodesAndAttachments( Layer& rootNode,
+                               BufferIndex updateBufferIndex,
+                               ResourceManager& resourceManager,
+                               RenderQueue& renderQueue );
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_UPDATE_ALGORITHMS_H__
+
diff --git a/dali/internal/update/manager/update-manager-debug.cpp b/dali/internal/update/manager/update-manager-debug.cpp
new file mode 100644 (file)
index 0000000..1c21fe4
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/update-manager-debug.h>
+
+// EXTERNAL INCLUDES
+#include <sstream>
+#include <iomanip>
+#include <ios>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+#if defined(DEBUG_ENABLED)
+static Debug::Filter* gNodeLogFilter = Debug::Filter::New(Debug::Verbose, false, "LOG_UPDATE_MANAGER");
+#endif
+
+/**
+ * Debug helper function.
+ */
+void PrintNodes( const Node& node, BufferIndex updateBufferIndex, int level )
+{
+#if defined(DEBUG_ENABLED)
+  const Vector3& position = node.GetPosition(updateBufferIndex);
+  const Vector3& scale = node.GetScale(updateBufferIndex);
+  const Vector3& fullPos = node.GetWorldPosition(updateBufferIndex);
+  const Quaternion& rotation = node.GetOrientation(updateBufferIndex);
+  Vector3 axis;
+  Radian angle;
+  rotation.ToAxisAngle(axis, angle);
+
+  std::string nodeName= DALI_LOG_GET_OBJECT_STRING((&node));
+
+  {
+    std::ostringstream oss;
+    std::ios_base::fmtflags mask = oss.flags();
+    mask &= ~std::ios_base::scientific;
+    mask |=  std::ios_base::fixed;
+    oss << std::setprecision(2) << std::setiosflags(mask)
+        << std::setw(level*2) << std::setfill(' ') << "";
+    oss << "Node "  << nodeName << " " << &node
+        << "  Position (" << position.x << ", " << position.y << ", " << position.z << ")"
+        << "  WorldPosition (" << fullPos.x << ", " << fullPos.y << ", " << fullPos.z << ")"
+        << "  Orientation (" << Degree(angle).degree << "degrees <" << axis.x << ", " << axis.y << ", " << axis.z << ">)"
+        << "  Scale (" << scale.x << ", " << scale.y << ", " << scale.z << ")"
+        << std::endl;
+
+    DALI_LOG_INFO(gNodeLogFilter, Debug::Verbose, "%s", oss.str().c_str());
+  }
+
+  {
+    std::ostringstream oss;
+    std::ios_base::fmtflags mask = oss.flags();
+    mask &= ~std::ios_base::scientific;
+    mask |=  std::ios_base::fixed;
+    oss << std::setprecision(2) << std::setiosflags(mask)
+        << std::setw(level*2) << std::setfill(' ') << "";
+
+    std::string trafoMatrix = Debug::MatrixToString(node.GetWorldMatrix(updateBufferIndex), 2, level*2);
+    DALI_LOG_INFO(gNodeLogFilter, Debug::Verbose, "%s", trafoMatrix.c_str());
+  }
+
+  ++level;
+
+  for ( NodeConstIter iter = node.GetChildren().Begin(); iter != node.GetChildren().End(); ++iter )
+  {
+    PrintNodes(**iter, updateBufferIndex, level);
+  }
+#endif // DEBUG_ENABLED
+}
+
+void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string indentation )
+{
+#if defined(DEBUG_ENABLED)
+
+  std::cout << "Node " << &node
+            << " \"" << node.mDebugString << "\""
+            << " Origin: "       << node.GetParentOrigin()
+            << " Anchor: "       << node.GetAnchorPoint()
+            << " Size: "         << node.GetSize(bufferIndex)
+            << " Pos: "          << node.GetPosition(bufferIndex)
+            << " Ori: "          << node.GetOrientation(bufferIndex)
+            << " Scale: "        << node.GetScale(bufferIndex)
+            << " Color: "        << node.GetColor(bufferIndex)
+            << " Visible: "      << node.IsVisible(bufferIndex)
+            << " World Pos: "    << node.GetWorldPosition(bufferIndex)
+            << " World Ori: "    << node.GetWorldOrientation(bufferIndex)
+            << " World Scale: "  << node.GetWorldScale(bufferIndex)
+            << " World Color: "  << node.GetWorldColor(bufferIndex)
+            << " World Matrix: " << node.GetWorldMatrix(bufferIndex)
+            << std::endl;
+
+  for ( NodeConstIter iter = node.GetChildren().Begin(); iter != node.GetChildren().End(); ++iter)
+  {
+    std::cout << indentation << "|" << std::endl
+              << indentation << "---->";
+
+    std::string nextIndent = indentation;
+    if ( (iter + 1) != node.GetChildren().End() )
+    {
+      nextIndent += "|    ";
+    }
+    else
+    {
+      nextIndent += "     ";
+    }
+
+    PrintNodeTree(**iter, bufferIndex, nextIndent);
+  }
+
+#endif // DEBUG_ENABLED
+}
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
diff --git a/dali/internal/update/manager/update-manager-debug.h b/dali/internal/update/manager/update-manager-debug.h
new file mode 100644 (file)
index 0000000..a5f98f4
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/nodes/node.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+void PrintNodes( const Node& node, BufferIndex updateBufferIndex, int level);
+
+void PrintNodeTree( const Node& node, BufferIndex bufferIndex, std::string indentation="" );
+
+} // SceneGraph
+
+} // Internal
+
+} // Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_DEBUG_H__
diff --git a/dali/internal/update/manager/update-manager.cpp b/dali/internal/update/manager/update-manager.cpp
new file mode 100644 (file)
index 0000000..8c20897
--- /dev/null
@@ -0,0 +1,1229 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/manager/update-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/stage.h>
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/devel-api/common/mutex.h>
+
+#include <dali/integration-api/core.h>
+#include <dali/integration-api/render-controller.h>
+#include <dali/internal/common/shader-data.h>
+#include <dali/integration-api/debug.h>
+
+#include <dali/internal/common/core-impl.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/common/message.h>
+
+#include <dali/internal/event/common/notification-manager.h>
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <dali/internal/event/common/property-notifier.h>
+#include <dali/internal/event/effects/shader-factory.h>
+
+#include <dali/internal/update/animation/scene-graph-animator.h>
+#include <dali/internal/update/animation/scene-graph-animation.h>
+#include <dali/internal/update/common/discard-queue.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/update/controllers/scene-controller-impl.h>
+#include <dali/internal/update/gestures/scene-graph-pan-gesture.h>
+#include <dali/internal/update/manager/object-owner-container.h>
+#include <dali/internal/update/manager/prepare-render-algorithms.h>
+#include <dali/internal/update/manager/process-render-tasks.h>
+#include <dali/internal/update/manager/sorted-layers.h>
+#include <dali/internal/update/manager/update-algorithms.h>
+#include <dali/internal/update/manager/update-manager-debug.h>
+#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderer-attachment.h>
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/update/queue/update-message-queue.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+#include <dali/internal/update/touch/touch-resampler.h>
+
+#include <dali/internal/render/common/render-instruction-container.h>
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/gl-resources/texture-cache.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+// Un-comment to enable node tree debug logging
+//#define NODE_TREE_LOGGING 1
+
+#if ( defined( DEBUG_ENABLED ) && defined( NODE_TREE_LOGGING ) )
+#define SNAPSHOT_NODE_LOGGING \
+const int FRAME_COUNT_TRIGGER = 16;\
+if( mImpl->frameCounter >= FRAME_COUNT_TRIGGER )\
+  {\
+    if ( NULL != mImpl->root )\
+    {\
+      mImpl->frameCounter = 0;\
+      PrintNodeTree( *mImpl->root, mSceneGraphBuffers.GetUpdateBufferIndex(), "" );\
+    }\
+  }\
+mImpl->frameCounter++;
+#else
+#define SNAPSHOT_NODE_LOGGING
+#endif
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gRenderTaskLogFilter;
+#endif
+
+
+using namespace Dali::Integration;
+using Dali::Internal::Update::MessageQueue;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+void DestroyNodeSet( std::set<Node*>& nodeSet )
+{
+  for( std::set<Node*>::iterator iter = nodeSet.begin(); iter != nodeSet.end(); ++iter )
+  {
+    Node* node( *iter );
+
+    // Call Node::OnDestroy as each node is destroyed
+    node->OnDestroy();
+
+    delete node;
+  }
+  nodeSet.clear();
+}
+
+} //namespace
+
+typedef OwnerContainer< Shader* >              ShaderContainer;
+typedef ShaderContainer::Iterator              ShaderIter;
+typedef ShaderContainer::ConstIterator         ShaderConstIter;
+
+typedef std::vector<Internal::ShaderDataPtr>   ShaderDataBinaryQueue;
+
+typedef OwnerContainer<PanGesture*>            GestureContainer;
+typedef GestureContainer::Iterator             GestureIter;
+typedef GestureContainer::ConstIterator        GestureConstIter;
+
+
+/**
+ * Structure to contain UpdateManager internal data
+ */
+struct UpdateManager::Impl
+{
+  Impl( NotificationManager& notificationManager,
+        GlSyncAbstraction& glSyncAbstraction,
+        CompleteNotificationInterface& animationFinishedNotifier,
+        PropertyNotifier& propertyNotifier,
+        ResourceManager& resourceManager,
+        DiscardQueue& discardQueue,
+        RenderController& renderController,
+        RenderManager& renderManager,
+        RenderQueue& renderQueue,
+        TextureCache& textureCache,
+        TouchResampler& touchResampler,
+        SceneGraphBuffers& sceneGraphBuffers )
+  :
+    renderMessageDispatcher( renderManager, renderQueue, sceneGraphBuffers ),
+    notificationManager( notificationManager ),
+    animationFinishedNotifier( animationFinishedNotifier ),
+    propertyNotifier( propertyNotifier ),
+    shaderSaver( NULL ),
+    resourceManager( resourceManager ),
+    discardQueue( discardQueue ),
+    renderController( renderController ),
+    sceneController( NULL ),
+    renderManager( renderManager ),
+    renderQueue( renderQueue ),
+    renderInstructions( renderManager.GetRenderInstructionContainer() ),
+    completeStatusManager( glSyncAbstraction, renderMessageDispatcher, resourceManager ),
+    touchResampler( touchResampler ),
+    backgroundColor( Dali::Stage::DEFAULT_BACKGROUND_COLOR ),
+    taskList ( completeStatusManager ),
+    systemLevelTaskList ( completeStatusManager ),
+    root( NULL ),
+    systemLevelRoot( NULL ),
+    geometries(  sceneGraphBuffers, discardQueue ),
+    materials( sceneGraphBuffers, discardQueue ),
+    samplers( sceneGraphBuffers, discardQueue ),
+    propertyBuffers( sceneGraphBuffers, discardQueue ),
+    messageQueue( renderController, sceneGraphBuffers ),
+    keepRenderingSeconds( 0.0f ),
+    animationFinishedDuringUpdate( false ),
+    nodeDirtyFlags( TransformFlag ), // set to TransformFlag to ensure full update the first time through Update()
+    previousUpdateScene( false ),
+    frameCounter( 0 ),
+    renderSortingHelper(),
+    renderTaskWaiting( false )
+  {
+    sceneController = new SceneControllerImpl( renderMessageDispatcher, renderQueue, discardQueue, textureCache, completeStatusManager );
+
+    geometries.SetSceneController( *sceneController );
+    materials.SetSceneController( *sceneController );
+    propertyBuffers.SetSceneController( *sceneController );
+    samplers.SetSceneController( *sceneController );
+  }
+
+  ~Impl()
+  {
+    // Disconnect render tasks from nodes, before destroying the nodes
+    RenderTaskList::RenderTaskContainer& tasks = taskList.GetTasks();
+    for (RenderTaskList::RenderTaskContainer::Iterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
+    {
+      (*iter)->SetSourceNode( NULL );
+    }
+    // ..repeat for system level RenderTasks
+    RenderTaskList::RenderTaskContainer& systemLevelTasks = systemLevelTaskList.GetTasks();
+    for (RenderTaskList::RenderTaskContainer::Iterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
+    {
+      (*iter)->SetSourceNode( NULL );
+    }
+
+    // UpdateManager owns the Nodes
+    DestroyNodeSet( activeDisconnectedNodes );
+    DestroyNodeSet( connectedNodes );
+    DestroyNodeSet( disconnectedNodes );
+
+    // If there is root, reset it, otherwise do nothing as rendering was never started
+    if( root )
+    {
+      root->OnDestroy();
+
+      delete root;
+      root = NULL;
+    }
+
+    if( systemLevelRoot )
+    {
+      systemLevelRoot->OnDestroy();
+
+      delete systemLevelRoot;
+      systemLevelRoot = NULL;
+    }
+
+    sceneController->GetTextureCache().SetBufferIndices(NULL); // TODO - Remove
+    delete sceneController;
+  }
+
+  SceneGraphBuffers                   sceneGraphBuffers;             ///< Used to keep track of which buffers are being written or read
+  RenderMessageDispatcher             renderMessageDispatcher;       ///< Used for passing messages to the render-thread
+  NotificationManager&                notificationManager;           ///< Queues notification messages for the event-thread.
+  CompleteNotificationInterface&      animationFinishedNotifier;     ///< Provides notification to applications when animations are finished.
+  PropertyNotifier&                   propertyNotifier;              ///< Provides notification to applications when properties are modified.
+  ShaderSaver*                        shaderSaver;                   ///< Saves shader binaries.
+  ResourceManager&                    resourceManager;               ///< resource manager
+  DiscardQueue&                       discardQueue;                  ///< Nodes are added here when disconnected from the scene-graph.
+  RenderController&                   renderController;              ///< render controller
+  SceneControllerImpl*                sceneController;               ///< scene controller
+  RenderManager&                      renderManager;                 ///< This is responsible for rendering the results of each "update"
+  RenderQueue&                        renderQueue;                   ///< Used to queue messages for the next render
+  RenderInstructionContainer&         renderInstructions;            ///< Used to prepare the render instructions
+  CompleteStatusManager               completeStatusManager;         ///< Complete Status Manager
+  TouchResampler&                     touchResampler;                ///< Used to resample touch events on every update.
+
+  Vector4                             backgroundColor;               ///< The glClear color used at the beginning of each frame.
+
+  RenderTaskList                      taskList;                      ///< The list of scene graph render-tasks
+  RenderTaskList                      systemLevelTaskList;           ///< Separate render-tasks for system-level content
+
+  Layer*                              root;                          ///< The root node (root is a layer)
+  Layer*                              systemLevelRoot;               ///< A separate root-node for system-level content
+  std::set< Node* >                   activeDisconnectedNodes;       ///< A container of new or modified nodes (without parent) owned by UpdateManager
+  std::set< Node* >                   connectedNodes;                ///< A container of connected (with parent) nodes owned by UpdateManager
+  std::set< Node* >                   disconnectedNodes;             ///< A container of inactive disconnected nodes (without parent) owned by UpdateManager
+
+  SortedLayerPointers                 sortedLayers;                  ///< A container of Layer pointers sorted by depth
+  SortedLayerPointers                 systemLevelSortedLayers;       ///< A separate container of system-level Layers
+
+  OwnerContainer< PropertyOwner* >    customObjects;                 ///< A container of owned objects (with custom properties)
+
+  AnimationContainer                  animations;                    ///< A container of owned animations
+  PropertyNotificationContainer       propertyNotifications;         ///< A container of owner property notifications.
+
+  ObjectOwnerContainer<Geometry>      geometries;                    ///< A container of geometries
+  ObjectOwnerContainer<Material>      materials;                     ///< A container of materials
+  ObjectOwnerContainer<Sampler>       samplers;                      ///< A container of samplers
+  ObjectOwnerContainer<PropertyBuffer> propertyBuffers;              ///< A container of property buffers
+
+  ShaderContainer                     shaders;                       ///< A container of owned shaders
+
+  MessageQueue                        messageQueue;                  ///< The messages queued from the event-thread
+  ShaderDataBinaryQueue               renderCompiledShaders;         ///< Shaders compiled on Render thread are inserted here for update thread to pass on to event thread.
+  ShaderDataBinaryQueue               updateCompiledShaders;         ///< Shaders to be sent from Update to Event
+  Mutex                               compiledShaderMutex;           ///< lock to ensure no corruption on the renderCompiledShaders
+
+  float                               keepRenderingSeconds;          ///< Set via Dali::Stage::KeepRendering
+  bool                                animationFinishedDuringUpdate; ///< Flag whether any animations finished during the Update()
+
+  int                                 nodeDirtyFlags;                ///< cumulative node dirty flags from previous frame
+  bool                                previousUpdateScene;           ///< True if the scene was updated in the previous frame (otherwise it was optimized out)
+
+  int                                 frameCounter;                  ///< Frame counter used in debugging to choose which frame to debug and which to ignore.
+  RendererSortingHelper               renderSortingHelper;           ///< helper used to sort transparent renderers
+
+  GestureContainer                    gestures;                      ///< A container of owned gesture detectors
+  bool                                renderTaskWaiting;             ///< A REFRESH_ONCE render task is waiting to be rendered
+};
+
+UpdateManager::UpdateManager( NotificationManager& notificationManager,
+                              GlSyncAbstraction& glSyncAbstraction,
+                              CompleteNotificationInterface& animationFinishedNotifier,
+                              PropertyNotifier& propertyNotifier,
+                              ResourceManager& resourceManager,
+                              DiscardQueue& discardQueue,
+                              RenderController& controller,
+                              RenderManager& renderManager,
+                              RenderQueue& renderQueue,
+                              TextureCache& textureCache,
+                              TouchResampler& touchResampler )
+  : mImpl(NULL)
+{
+  mImpl = new Impl( notificationManager,
+                    glSyncAbstraction,
+                    animationFinishedNotifier,
+                    propertyNotifier,
+                    resourceManager,
+                    discardQueue,
+                    controller,
+                    renderManager,
+                    renderQueue,
+                    textureCache,
+                    touchResampler,
+                    mSceneGraphBuffers );
+
+  textureCache.SetBufferIndices( &mSceneGraphBuffers );
+}
+
+UpdateManager::~UpdateManager()
+{
+  delete mImpl;
+}
+
+void UpdateManager::InstallRoot( SceneGraph::Layer* layer, bool systemLevel )
+{
+  DALI_ASSERT_DEBUG( layer->IsLayer() );
+  DALI_ASSERT_DEBUG( layer->GetParent() == NULL);
+
+  if ( !systemLevel )
+  {
+    DALI_ASSERT_DEBUG( mImpl->root == NULL && "Root Node already installed" );
+    mImpl->root = layer;
+  }
+  else
+  {
+    DALI_ASSERT_DEBUG( mImpl->systemLevelRoot == NULL && "System-level Root Node already installed" );
+    mImpl->systemLevelRoot = layer;
+  }
+
+  layer->SetRoot(true);
+}
+
+void UpdateManager::AddNode( Node* node )
+{
+  DALI_ASSERT_ALWAYS( NULL != node );
+  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+
+  mImpl->activeDisconnectedNodes.insert( node ); // Takes ownership of node
+}
+
+void UpdateManager::ConnectNode( Node* parent, Node* node, int index )
+{
+  DALI_ASSERT_ALWAYS( NULL != parent );
+  DALI_ASSERT_ALWAYS( NULL != node );
+  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+
+  // Move from active/disconnectedNodes to connectedNodes
+  std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
+  if( !removed )
+  {
+    removed = mImpl->disconnectedNodes.erase( node );
+    DALI_ASSERT_ALWAYS( removed );
+  }
+  mImpl->connectedNodes.insert( node );
+
+  node->SetActive( true );
+
+  parent->ConnectChild( node, index );
+}
+
+void UpdateManager::DisconnectNode( Node* node )
+{
+  Node* parent = node->GetParent();
+  DALI_ASSERT_ALWAYS( NULL != parent );
+  parent->SetDirtyFlag( ChildDeletedFlag ); // make parent dirty so that render items dont get reused
+
+  // Move from connectedNodes to activeDisconnectedNodes (reset properties next frame)
+  parent->DisconnectChild( mSceneGraphBuffers.GetUpdateBufferIndex(), *node, mImpl->connectedNodes, mImpl->activeDisconnectedNodes );
+}
+
+void UpdateManager::SetNodeActive( Node* node )
+{
+  DALI_ASSERT_ALWAYS( NULL != node );
+  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should not have a parent yet
+
+  // Move from disconnectedNodes to activeDisconnectedNodes (reset properties next frame)
+  std::set<Node*>::size_type removed = mImpl->disconnectedNodes.erase( node );
+  DALI_ASSERT_ALWAYS( removed );
+  mImpl->activeDisconnectedNodes.insert( node );
+
+  node->SetActive( true );
+}
+
+void UpdateManager::DestroyNode( Node* node )
+{
+  DALI_ASSERT_ALWAYS( NULL != node );
+  DALI_ASSERT_ALWAYS( NULL == node->GetParent() ); // Should have been disconnected
+
+  // Transfer ownership from new/disconnectedNodes to the discard queue
+  // This keeps the nodes alive, until the render-thread has finished with them
+  std::set<Node*>::size_type removed = mImpl->activeDisconnectedNodes.erase( node );
+  if( !removed )
+  {
+    removed = mImpl->disconnectedNodes.erase( node );
+    DALI_ASSERT_ALWAYS( removed );
+  }
+  mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), node );
+
+  // Notify the Node about impending destruction
+  node->OnDestroy();
+}
+
+//@todo MESH_REWORK Extend to allow arbitrary scene objects to connect to each other
+void UpdateManager::AttachToNode( Node* node, NodeAttachment* attachment )
+{
+  DALI_ASSERT_DEBUG( node != NULL );
+  DALI_ASSERT_DEBUG( attachment != NULL );
+
+  // attach node to attachment first so that parent is known by the time attachment is connected
+  node->Attach( *attachment ); // node takes ownership
+
+  // @todo MESH_REWORK Remove after merge of SceneGraph::RenderableAttachment and SceneGraph::RendererAttachment
+  if( dynamic_cast<SceneGraph::ImageAttachment*>( attachment ) != NULL )
+  {
+    attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+  }
+}
+
+void UpdateManager::AttachToSceneGraph( RendererAttachment* renderer )
+{
+  // @todo MESH_REWORK Take ownership of this object after merge with SceneGraph::RenderableAttachment
+
+  SceneGraph::NodeAttachment* attachment = static_cast<SceneGraph::NodeAttachment*>(renderer);
+  attachment->Initialize( *mImpl->sceneController, mSceneGraphBuffers.GetUpdateBufferIndex() );
+}
+
+void UpdateManager::AddObject( PropertyOwner* object )
+{
+  DALI_ASSERT_DEBUG( NULL != object );
+
+  mImpl->customObjects.PushBack( object );
+}
+
+void UpdateManager::RemoveObject( PropertyOwner* object )
+{
+  DALI_ASSERT_DEBUG( NULL != object );
+
+  OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
+
+  // Find the object and destroy it
+  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); iter != customObjects.End(); ++iter )
+  {
+    PropertyOwner* current = *iter;
+    if ( current == object )
+    {
+      customObjects.Erase( iter );
+      return;
+    }
+  }
+
+  // Should not reach here
+  DALI_ASSERT_DEBUG(false);
+}
+
+void UpdateManager::AddAnimation( Animation* animation )
+{
+  mImpl->animations.PushBack( animation );
+}
+
+void UpdateManager::StopAnimation( Animation* animation )
+{
+  DALI_ASSERT_DEBUG( animation && "NULL animation called to stop" );
+
+  bool animationFinished = animation->Stop( mSceneGraphBuffers.GetUpdateBufferIndex() );
+
+  mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || animationFinished;
+}
+
+void UpdateManager::RemoveAnimation( Animation* animation )
+{
+  DALI_ASSERT_DEBUG( animation && "NULL animation called to remove" );
+
+  animation->OnDestroy( mSceneGraphBuffers.GetUpdateBufferIndex() );
+
+  DALI_ASSERT_DEBUG( animation->GetState() == Animation::Destroyed );
+}
+
+bool UpdateManager::IsAnimationRunning() const
+{
+  bool isRunning(false);
+  AnimationContainer& animations = mImpl->animations;
+
+  // Find any animation that isn't stopped or paused
+
+  const AnimationIter endIter = animations.End();
+  for ( AnimationIter iter = animations.Begin(); !isRunning && iter != endIter; ++iter )
+  {
+    const Animation::State state = (*iter)->GetState();
+
+    if (state != Animation::Stopped &&
+        state != Animation::Paused)
+    {
+      isRunning = true;
+    }
+  }
+
+  return isRunning;
+}
+
+void UpdateManager::AddPropertyNotification( PropertyNotification* propertyNotification )
+{
+  mImpl->propertyNotifications.PushBack( propertyNotification );
+}
+
+void UpdateManager::RemovePropertyNotification( PropertyNotification* propertyNotification )
+{
+  PropertyNotificationContainer &propertyNotifications = mImpl->propertyNotifications;
+  PropertyNotificationIter iter = propertyNotifications.Begin();
+
+  while ( iter != propertyNotifications.End() )
+  {
+    if( *iter == propertyNotification )
+    {
+      propertyNotifications.Erase(iter);
+      break;
+    }
+    ++iter;
+  }
+}
+
+void UpdateManager::PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode )
+{
+  DALI_ASSERT_DEBUG( propertyNotification && "propertyNotification scene graph object missing" );
+  propertyNotification->SetNotifyMode( notifyMode );
+}
+
+ObjectOwnerContainer<Geometry>& UpdateManager::GetGeometryOwner()
+{
+  return mImpl->geometries;
+}
+
+ObjectOwnerContainer<Material>& UpdateManager::GetMaterialOwner()
+{
+  return mImpl->materials;
+}
+
+ObjectOwnerContainer<Sampler>& UpdateManager::GetSamplerOwner()
+{
+  return mImpl->samplers;
+}
+
+ObjectOwnerContainer<PropertyBuffer>& UpdateManager::GetPropertyBufferOwner()
+{
+  return mImpl->propertyBuffers;
+}
+
+void UpdateManager::AddShader( Shader* shader )
+{
+  DALI_ASSERT_DEBUG( NULL != shader );
+
+  if( mImpl->shaders.Count() == 0 )
+  {
+    // the first added shader becomes our default shader
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    typedef MessageValue1< RenderManager, Shader* > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetDefaultShader, shader );
+  }
+
+  mImpl->shaders.PushBack( shader );
+
+  // Allows the shader to dispatch texture requests to the cache
+  shader->Initialize( mImpl->renderQueue, mImpl->sceneController->GetTextureCache() );
+}
+
+void UpdateManager::RemoveShader( Shader* shader )
+{
+  DALI_ASSERT_DEBUG(shader != NULL);
+
+  ShaderContainer& shaders = mImpl->shaders;
+
+  // Find the shader and destroy it
+  for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
+  {
+    Shader& current = **iter;
+    if ( &current == shader )
+    {
+      // Transfer ownership to the discard queue
+      // This keeps the shader alive, until the render-thread has finished with it
+      mImpl->discardQueue.Add( mSceneGraphBuffers.GetUpdateBufferIndex(), shaders.Release( iter ) );
+
+      return;
+    }
+  }
+  // Should not reach here
+  DALI_ASSERT_DEBUG(false);
+}
+
+void UpdateManager::SetShaderProgram( Shader* shader,
+                                      Internal::ShaderDataPtr shaderData, bool modifiesGeometry )
+{
+  if( shaderData )
+  {
+
+    typedef MessageValue3< Shader, Internal::ShaderDataPtr, ProgramCache*, bool> DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( shader, &Shader::SetProgram, shaderData, mImpl->renderManager.GetProgramCache(), modifiesGeometry );
+  }
+}
+
+void UpdateManager::SaveBinary( Internal::ShaderDataPtr shaderData )
+{
+  DALI_ASSERT_DEBUG( shaderData && "No NULL shader data pointers please." );
+  DALI_ASSERT_DEBUG( shaderData->GetBufferSize() > 0 && "Shader binary empty so nothing to save." );
+  {
+    // lock as update might be sending previously compiled shaders to event thread
+    Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
+    mImpl->renderCompiledShaders.push_back( shaderData );
+  }
+}
+
+RenderTaskList* UpdateManager::GetRenderTaskList( bool systemLevel )
+{
+  if ( !systemLevel )
+  {
+    // copy the list, this is only likely to happen once in application life cycle
+    return &(mImpl->taskList);
+  }
+  else
+  {
+    // copy the list, this is only likely to happen once in application life cycle
+    return &(mImpl->systemLevelTaskList);
+  }
+}
+
+void UpdateManager::AddGesture( PanGesture* gesture )
+{
+  DALI_ASSERT_DEBUG( NULL != gesture );
+
+  mImpl->gestures.PushBack( gesture );
+}
+
+void UpdateManager::RemoveGesture( PanGesture* gesture )
+{
+  DALI_ASSERT_DEBUG( gesture != NULL );
+
+  GestureContainer& gestures = mImpl->gestures;
+
+  // Find the gesture and destroy it
+  for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
+  {
+    PanGesture& current = **iter;
+    if ( &current == gesture )
+    {
+      mImpl->gestures.Erase( iter );
+      return;
+    }
+  }
+  // Should not reach here
+  DALI_ASSERT_DEBUG(false);
+}
+
+unsigned int* UpdateManager::ReserveMessageSlot( std::size_t size, bool updateScene )
+{
+  return mImpl->messageQueue.ReserveMessageSlot( size, updateScene );
+}
+
+void UpdateManager::EventProcessingStarted()
+{
+  mImpl->messageQueue.EventProcessingStarted();
+}
+
+bool UpdateManager::FlushQueue()
+{
+  return mImpl->messageQueue.FlushQueue();
+}
+
+void UpdateManager::ResetNodeProperty( Node& node )
+{
+  BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
+  node.ResetToBaseValues( bufferIndex );
+}
+
+void UpdateManager::ResetProperties()
+{
+  PERF_MONITOR_START(PerformanceMonitor::RESET_PROPERTIES);
+
+  BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
+  // Clear the "animations finished" flag; This should be set if any (previously playing) animation is stopped
+  mImpl->animationFinishedDuringUpdate = false;
+
+  // Animated properties have to be reset to their original value each frame
+
+  // Reset node properties
+  if ( mImpl->root )
+  {
+    ResetNodeProperty( *mImpl->root );
+  }
+
+  if ( mImpl->systemLevelRoot )
+  {
+    ResetNodeProperty( *mImpl->systemLevelRoot );
+  }
+
+  // Reset the Connected Nodes
+  const std::set<Node*>::iterator endIter = mImpl->connectedNodes.end();
+  for( std::set<Node*>::iterator iter = mImpl->connectedNodes.begin(); endIter != iter; ++iter )
+  {
+    ResetNodeProperty( **iter );
+  }
+
+  // If a Node is disconnected, it may still be "active" (requires a reset in next frame)
+  for( std::set<Node*>::iterator iter = mImpl->activeDisconnectedNodes.begin(); mImpl->activeDisconnectedNodes.end() != iter; iter = mImpl->activeDisconnectedNodes.begin() )
+  {
+    Node* node = *iter;
+    node->ResetToBaseValues( bufferIndex );
+    node->SetActive( false );
+
+    // Move everything from activeDisconnectedNodes to disconnectedNodes (no need to reset again)
+    mImpl->activeDisconnectedNodes.erase( iter );
+    mImpl->disconnectedNodes.insert( node );
+  }
+
+  // Reset system-level render-task list properties to base values
+  const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
+
+  for (RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter)
+  {
+    (*iter)->ResetToBaseValues( bufferIndex );
+  }
+
+  // Reset render-task list properties to base values.
+  const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
+
+  for (RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter)
+  {
+    (*iter)->ResetToBaseValues( bufferIndex );
+  }
+
+  // Reset custom object properties to base values
+  for (OwnerContainer<PropertyOwner*>::Iterator iter = mImpl->customObjects.Begin(); iter != mImpl->customObjects.End(); ++iter)
+  {
+    (*iter)->ResetToBaseValues( bufferIndex );
+  }
+
+  mImpl->materials.ResetToBaseValues( bufferIndex );
+  mImpl->geometries.ResetToBaseValues( bufferIndex );
+  mImpl->propertyBuffers.ResetToBaseValues( bufferIndex );
+  mImpl->samplers.ResetToBaseValues( bufferIndex );
+
+
+  // Reset animatable shader properties to base values
+  for (ShaderIter iter = mImpl->shaders.Begin(); iter != mImpl->shaders.End(); ++iter)
+  {
+    (*iter)->ResetToBaseValues( bufferIndex );
+  }
+
+  PERF_MONITOR_END(PerformanceMonitor::RESET_PROPERTIES);
+}
+
+bool UpdateManager::ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds )
+{
+  bool gestureUpdated( false );
+
+  // constrain gestures... (in construction order)
+  GestureContainer& gestures = mImpl->gestures;
+
+  for ( GestureIter iter = gestures.Begin(), endIter = gestures.End(); iter != endIter; ++iter )
+  {
+    PanGesture& gesture = **iter;
+    gesture.ResetToBaseValues( mSceneGraphBuffers.GetUpdateBufferIndex() ); // Needs to be done every time as gesture data is written directly to an update-buffer rather than via a message
+    gestureUpdated |= gesture.UpdateProperties( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
+  }
+
+  return gestureUpdated;
+}
+
+void UpdateManager::Animate( float elapsedSeconds )
+{
+  PERF_MONITOR_START(PerformanceMonitor::ANIMATE_NODES);
+
+  AnimationContainer &animations = mImpl->animations;
+  AnimationIter iter = animations.Begin();
+  while ( iter != animations.End() )
+  {
+    Animation* animation = *iter;
+    bool finished = animation->Update(mSceneGraphBuffers.GetUpdateBufferIndex(), elapsedSeconds);
+
+    mImpl->animationFinishedDuringUpdate = mImpl->animationFinishedDuringUpdate || finished;
+
+    // Remove animations that had been destroyed but were still waiting for an update
+    if (animation->GetState() == Animation::Destroyed)
+    {
+      iter = animations.Erase(iter);
+    }
+    else
+    {
+      ++iter;
+    }
+  }
+
+  if ( mImpl->animationFinishedDuringUpdate )
+  {
+    // The application should be notified by NotificationManager, in another thread
+    mImpl->notificationManager.QueueCompleteNotification( &mImpl->animationFinishedNotifier );
+  }
+
+  PERF_MONITOR_END(PerformanceMonitor::ANIMATE_NODES);
+}
+
+void UpdateManager::ApplyConstraints()
+{
+  PERF_MONITOR_START(PerformanceMonitor::APPLY_CONSTRAINTS);
+
+  BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
+  // constrain custom objects... (in construction order)
+  OwnerContainer< PropertyOwner* >& customObjects = mImpl->customObjects;
+
+  const OwnerContainer< PropertyOwner* >::Iterator endIter = customObjects.End();
+  for ( OwnerContainer< PropertyOwner* >::Iterator iter = customObjects.Begin(); endIter != iter; ++iter )
+  {
+    PropertyOwner& object = **iter;
+    ConstrainPropertyOwner( object, bufferIndex );
+  }
+
+  // constrain nodes... (in Depth First traversal order)
+  if ( mImpl->root )
+  {
+    ConstrainNodes( *(mImpl->root), bufferIndex );
+  }
+
+  if ( mImpl->systemLevelRoot )
+  {
+    ConstrainNodes( *(mImpl->systemLevelRoot), bufferIndex );
+  }
+
+  // constrain other property-owners after nodes as they are more likely to depend on a node's
+  // current frame property than vice versa. They tend to be final constraints (no further
+  // constraints depend on their properties)
+  // e.g. ShaderEffect uniform a function of Actor's position.
+  // Mesh vertex a function of Actor's position or world position.
+
+  // TODO: refactor this code (and reset nodes) as these are all just lists of property-owners
+  // they can be all processed in a super-list of property-owners.
+
+  // Constrain system-level render-tasks
+  const RenderTaskList::RenderTaskContainer& systemLevelTasks = mImpl->systemLevelTaskList.GetTasks();
+
+  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = systemLevelTasks.Begin(); iter != systemLevelTasks.End(); ++iter )
+  {
+    RenderTask& task = **iter;
+    ConstrainPropertyOwner( task, bufferIndex );
+  }
+
+  // Constrain render-tasks
+  const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
+
+  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(); iter != tasks.End(); ++iter )
+  {
+    RenderTask& task = **iter;
+    ConstrainPropertyOwner( task, bufferIndex );
+  }
+
+  // Constrain Materials and geometries
+  mImpl->materials.ConstrainObjects( bufferIndex );
+  mImpl->geometries.ConstrainObjects( bufferIndex );
+  mImpl->samplers.ConstrainObjects( bufferIndex );
+  mImpl->propertyBuffers.ConstrainObjects( bufferIndex );
+
+  // constrain shaders... (in construction order)
+  ShaderContainer& shaders = mImpl->shaders;
+
+  for ( ShaderIter iter = shaders.Begin(); iter != shaders.End(); ++iter )
+  {
+    Shader& shader = **iter;
+    ConstrainPropertyOwner( shader, bufferIndex );
+  }
+
+  PERF_MONITOR_END(PerformanceMonitor::APPLY_CONSTRAINTS);
+}
+
+void UpdateManager::ProcessPropertyNotifications()
+{
+  PropertyNotificationContainer &notifications = mImpl->propertyNotifications;
+  PropertyNotificationIter iter = notifications.Begin();
+
+  BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
+  while ( iter != notifications.End() )
+  {
+    PropertyNotification* notification = *iter;
+    bool valid = notification->Check( bufferIndex );
+    if(valid)
+    {
+      mImpl->notificationManager.QueueMessage( PropertyChangedMessage( mImpl->propertyNotifier, notification, notification->GetValidity() ) );
+    }
+    ++iter;
+  }
+}
+
+void UpdateManager::ForwardCompiledShadersToEventThread()
+{
+  DALI_ASSERT_DEBUG( (mImpl->shaderSaver != 0) && "shaderSaver should be wired-up during startup." );
+  if( mImpl->shaderSaver )
+  {
+    // lock and swap the queues
+    {
+      // render might be attempting to send us more binaries at the same time
+      Mutex::ScopedLock lock( mImpl->compiledShaderMutex );
+      mImpl->renderCompiledShaders.swap( mImpl->updateCompiledShaders );
+    }
+
+    if( mImpl->updateCompiledShaders.size() > 0 )
+    {
+      ShaderSaver& factory = *mImpl->shaderSaver;
+      ShaderDataBinaryQueue::iterator i   = mImpl->updateCompiledShaders.begin();
+      ShaderDataBinaryQueue::iterator end = mImpl->updateCompiledShaders.end();
+      for( ; i != end; ++i )
+      {
+        mImpl->notificationManager.QueueMessage( ShaderCompiledMessage( factory, *i ) );
+      }
+      // we don't need them in update anymore
+      mImpl->updateCompiledShaders.clear();
+    }
+  }
+}
+
+void UpdateManager::UpdateNodes()
+{
+  mImpl->nodeDirtyFlags = NothingFlag;
+
+  if ( !mImpl->root )
+  {
+    return;
+  }
+
+  PERF_MONITOR_START( PerformanceMonitor::UPDATE_NODES );
+
+  // Prepare resources, update shaders, update attachments, for each node
+  // And add the renderers to the sorted layers. Start from root, which is also a layer
+  mImpl->nodeDirtyFlags = UpdateNodesAndAttachments( *( mImpl->root ),
+                                                     mSceneGraphBuffers.GetUpdateBufferIndex(),
+                                                     mImpl->resourceManager,
+                                                     mImpl->renderQueue );
+
+  if ( mImpl->systemLevelRoot )
+  {
+    mImpl->nodeDirtyFlags |= UpdateNodesAndAttachments( *( mImpl->systemLevelRoot ),
+                                                        mSceneGraphBuffers.GetUpdateBufferIndex(),
+                                                        mImpl->resourceManager,
+                                                        mImpl->renderQueue );
+  }
+
+  PERF_MONITOR_END( PerformanceMonitor::UPDATE_NODES );
+}
+
+unsigned int UpdateManager::Update( float elapsedSeconds,
+                                    unsigned int lastVSyncTimeMilliseconds,
+                                    unsigned int nextVSyncTimeMilliseconds )
+{
+  PERF_MONITOR_END(PerformanceMonitor::FRAME_RATE);   // Mark the End of the last frame
+  PERF_MONITOR_NEXT_FRAME();             // Prints out performance info for the last frame (if enabled)
+  PERF_MONITOR_START(PerformanceMonitor::FRAME_RATE); // Mark the start of this current frame
+
+  // Measure the time spent in UpdateManager::Update
+  PERF_MONITOR_START(PerformanceMonitor::UPDATE);
+
+  BufferIndex bufferIndex = mSceneGraphBuffers.GetUpdateBufferIndex();
+
+  // Update the frame time delta on the render thread.
+  mImpl->renderManager.SetFrameDeltaTime(elapsedSeconds);
+
+  // 1) Clear nodes/resources which were previously discarded
+  mImpl->discardQueue.Clear( bufferIndex );
+
+  // 2) Grab any loaded resources
+  bool resourceChanged = mImpl->resourceManager.UpdateCache( bufferIndex );
+
+  // 3) Process Touches & Gestures
+  mImpl->touchResampler.Update();
+  const bool gestureUpdated = ProcessGestures( lastVSyncTimeMilliseconds, nextVSyncTimeMilliseconds );
+
+  const bool updateScene =                                            // The scene-graph requires an update if..
+      (mImpl->nodeDirtyFlags & RenderableUpdateFlags) ||              // ..nodes were dirty in previous frame OR
+      IsAnimationRunning() ||                                         // ..at least one animation is running OR
+      mImpl->messageQueue.IsSceneUpdateRequired() ||                  // ..a message that modifies the scene graph node tree is queued OR
+      resourceChanged ||                                              // ..one or more resources were updated/changed OR
+      gestureUpdated;                                                // ..a gesture property was updated
+
+  // Although the scene-graph may not require an update, we still need to synchronize double-buffered
+  // values if the scene was updated in the previous frame.
+  if( updateScene || mImpl->previousUpdateScene )
+  {
+    // 4) Reset properties from the previous update
+    ResetProperties();
+  }
+
+  // 5) Process the queued scene messages
+  mImpl->messageQueue.ProcessMessages();
+
+  // 6) Post Process Ids of resources updated by renderer
+  mImpl->resourceManager.PostProcessResources( bufferIndex );
+
+  // 6.1) Forward compiled shader programs to event thread for saving
+  ForwardCompiledShadersToEventThread();
+
+  // Although the scene-graph may not require an update, we still need to synchronize double-buffered
+  // renderer lists if the scene was updated in the previous frame.
+  // We should not start skipping update steps or reusing lists until there has been two frames where nothing changes
+  if( updateScene || mImpl->previousUpdateScene )
+  {
+    // 7) Animate
+    Animate( elapsedSeconds );
+
+    // 8) Apply Constraints
+    ApplyConstraints();
+
+    // 9) Check Property Notifications
+    ProcessPropertyNotifications();
+
+    // 10) Clear the lists of renderable-attachments from the previous update
+    ClearRenderables( mImpl->sortedLayers );
+    ClearRenderables( mImpl->systemLevelSortedLayers );
+
+    // 11) Update node hierarchy and perform sorting / culling.
+    //     This will populate each Layer with a list of renderers which are ready.
+    UpdateNodes();
+
+    // 12) Prepare for the next render
+    PERF_MONITOR_START(PerformanceMonitor::PREPARE_RENDERABLES);
+
+    PrepareRenderables( bufferIndex, mImpl->sortedLayers );
+    PrepareRenderables( bufferIndex, mImpl->systemLevelSortedLayers );
+    PERF_MONITOR_END(PerformanceMonitor::PREPARE_RENDERABLES);
+
+    PERF_MONITOR_START(PerformanceMonitor::PROCESS_RENDER_TASKS);
+
+    // 14) Process the RenderTasks; this creates the instructions for rendering the next frame.
+    // reset the update buffer index and make sure there is enough room in the instruction container
+    mImpl->renderInstructions.ResetAndReserve( mSceneGraphBuffers.GetUpdateBufferIndex(),
+                                               mImpl->taskList.GetTasks().Count() + mImpl->systemLevelTaskList.GetTasks().Count() );
+
+    if ( NULL != mImpl->root )
+    {
+      ProcessRenderTasks(  bufferIndex,
+                           mImpl->completeStatusManager,
+                           mImpl->taskList,
+                           *mImpl->root,
+                           mImpl->sortedLayers,
+                           mImpl->renderSortingHelper,
+                           mImpl->renderInstructions );
+
+      // Process the system-level RenderTasks last
+      if ( NULL != mImpl->systemLevelRoot )
+      {
+        ProcessRenderTasks(  bufferIndex,
+                             mImpl->completeStatusManager,
+                             mImpl->systemLevelTaskList,
+                             *mImpl->systemLevelRoot,
+                             mImpl->systemLevelSortedLayers,
+                             mImpl->renderSortingHelper,
+                             mImpl->renderInstructions );
+      }
+    }
+  }
+
+  // check the countdown and notify (note, at the moment this is only done for normal tasks, not for systemlevel tasks)
+  bool doRenderOnceNotify = false;
+  mImpl->renderTaskWaiting = false;
+  const RenderTaskList::RenderTaskContainer& tasks = mImpl->taskList.GetTasks();
+  for ( RenderTaskList::RenderTaskContainer::ConstIterator iter = tasks.Begin(), endIter = tasks.End();
+        endIter != iter; ++iter )
+  {
+    RenderTask& renderTask(*(*iter));
+
+    renderTask.UpdateState();
+
+    if( renderTask.IsWaitingToRender() &&
+        renderTask.ReadyToRender( bufferIndex ) /*avoid updating forever when source actor is off-stage*/ )
+    {
+      mImpl->renderTaskWaiting = true; // keep update/render threads alive
+    }
+
+    if( renderTask.HasRendered() )
+    {
+      doRenderOnceNotify = true;
+    }
+  }
+
+  if( doRenderOnceNotify )
+  {
+    DALI_LOG_INFO(gRenderTaskLogFilter, Debug::General, "Notify a render task has finished\n");
+    mImpl->notificationManager.QueueCompleteNotification( mImpl->taskList.GetCompleteNotificationInterface() );
+  }
+
+  PERF_MONITOR_END(PerformanceMonitor::PROCESS_RENDER_TASKS);
+
+  // Macro is undefined in release build.
+  SNAPSHOT_NODE_LOGGING;
+
+  // A ResetProperties() may be required in the next frame
+  mImpl->previousUpdateScene = updateScene;
+
+  // Check whether further updates are required
+  unsigned int keepUpdating = KeepUpdatingCheck( elapsedSeconds );
+
+#ifdef PERFORMANCE_MONITOR_ENABLED
+  // Always keep rendering when measuring FPS
+  keepUpdating |= KeepUpdating::MONITORING_PERFORMANCE;
+#endif
+
+  // The update has finished; swap the double-buffering indices
+  mSceneGraphBuffers.Swap();
+
+  // tell the update manager that we're done so the queue can be given to event thread
+  mImpl->notificationManager.UpdateCompleted();
+
+  PERF_MONITOR_END(PerformanceMonitor::UPDATE);
+
+  return keepUpdating;
+}
+
+unsigned int UpdateManager::KeepUpdatingCheck( float elapsedSeconds ) const
+{
+  // Update the duration set via Stage::KeepRendering()
+  if ( mImpl->keepRenderingSeconds > 0.0f )
+  {
+    mImpl->keepRenderingSeconds -= elapsedSeconds;
+  }
+
+  unsigned int keepUpdatingRequest = KeepUpdating::NOT_REQUESTED;
+
+  // If Stage::KeepRendering() has been called, then continue until the duration has elapsed.
+  // Keep updating until no messages are received and no animations are running.
+  // If an animation has just finished, update at least once more for Discard end-actions.
+  // No need to check for renderQueue as there is always a render after update and if that
+  // render needs another update it will tell the adaptor to call update again
+
+  if ( mImpl->keepRenderingSeconds > 0.0f )
+  {
+    keepUpdatingRequest |= KeepUpdating::STAGE_KEEP_RENDERING;
+  }
+
+  if ( IsAnimationRunning() ||
+       mImpl->animationFinishedDuringUpdate )
+  {
+    keepUpdatingRequest |= KeepUpdating::ANIMATIONS_RUNNING;
+  }
+
+  if ( mImpl->renderTaskWaiting )
+  {
+    keepUpdatingRequest |= KeepUpdating::RENDER_TASK_SYNC;
+  }
+
+  return keepUpdatingRequest;
+}
+
+void UpdateManager::SetBackgroundColor( const Vector4& color )
+{
+  typedef MessageValue1< RenderManager, Vector4 > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mImpl->renderManager, &RenderManager::SetBackgroundColor, color );
+}
+
+void UpdateManager::SetDefaultSurfaceRect( const Rect<int>& rect )
+{
+  typedef MessageValue1< RenderManager, Rect<int> > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mImpl->renderQueue.ReserveMessageSlot( mSceneGraphBuffers.GetUpdateBufferIndex(), sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &mImpl->renderManager,  &RenderManager::SetDefaultSurfaceRect, rect );
+}
+
+void UpdateManager::KeepRendering( float durationSeconds )
+{
+  mImpl->keepRenderingSeconds = std::max( mImpl->keepRenderingSeconds, durationSeconds );
+}
+
+void UpdateManager::SetLayerDepths( const SortedLayerPointers& layers, bool systemLevel )
+{
+  if ( !systemLevel )
+  {
+    // just copy the vector of pointers
+    mImpl->sortedLayers = layers;
+  }
+  else
+  {
+    mImpl->systemLevelSortedLayers = layers;
+  }
+}
+
+void UpdateManager::SetShaderSaver( ShaderSaver& upstream )
+{
+  mImpl->shaderSaver = &upstream;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/manager/update-manager.h b/dali/internal/update/manager/update-manager.h
new file mode 100644 (file)
index 0000000..5c23c9f
--- /dev/null
@@ -0,0 +1,839 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+
+#include <dali/integration-api/resource-declarations.h>
+
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/type-abstraction-enums.h>
+#include <dali/internal/common/shader-saver.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/animation/scene-graph-animation.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/scene-graph-property-notification.h>
+#include <dali/internal/update/manager/object-owner-container.h>
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GlSyncAbstraction;
+class RenderController;
+
+} // namespace Integration
+
+namespace Internal
+{
+
+class PropertyNotifier;
+class NotificationManager;
+class CompleteNotificationInterface;
+class ResourceManager;
+class TouchResampler;
+
+// value types used by messages
+template <> struct ParameterType< PropertyNotification::NotifyMode >
+: public BasicType< PropertyNotification::NotifyMode > {};
+
+namespace SceneGraph
+{
+
+class Animation;
+class DiscardQueue;
+class PanGesture;
+class RenderManager;
+class RenderTaskList;
+class RenderQueue;
+class TextureCache;
+class Geometry;
+class PropertyBuffer;
+class Material;
+class Sampler;
+class RendererAttachment;
+
+/**
+ * UpdateManager maintains a scene graph i.e. a tree of nodes and attachments and
+ * other property owner objects.
+ * It controls the Update traversal, in which nodes are repositioned/animated,
+ * and organizes the the culling and rendering of the scene.
+ * It also maintains the lifecycle of nodes and other property owners that are
+ * disconnected from the scene graph.
+ */
+class UpdateManager : public ShaderSaver
+{
+public:
+
+  /**
+   * Construct a new UpdateManager.
+   * @param[in] notificationManager This should be notified when animations have finished.
+   * @param[in] glSyncAbstraction Used to determine when framebuffers are ready
+   * @param[in] animationFinishedNotifier The CompleteNotificationInterface that handles animation completions
+   * @param[in] propertyNotifier The PropertyNotifier
+   * @param[in] resourceManager The resource manager used to load textures etc.
+   * @param[in] discardQueue Nodes are added here when disconnected from the scene-graph.
+   * @param[in] controller After messages are flushed, we request a render from the RenderController.
+   * @param[in] renderManager This is responsible for rendering the results of each "update".
+   * @param[in] renderQueue Used to queue messages for the next render.
+   * @param[in] textureCache Used for caching textures.
+   * @param[in] touchResampler Used for re-sampling touch events.
+   */
+  UpdateManager( NotificationManager& notificationManager,
+                 Integration::GlSyncAbstraction& glSyncAbstraction,
+                 CompleteNotificationInterface& animationFinishedNotifier,
+                 PropertyNotifier& propertyNotifier,
+                 ResourceManager& resourceManager,
+                 DiscardQueue& discardQueue,
+                 Integration::RenderController& controller,
+                 RenderManager& renderManager,
+                 RenderQueue& renderQueue,
+                 TextureCache& textureCache,
+                 TouchResampler& touchResampler );
+
+  /**
+   * Destructor.
+   */
+  virtual ~UpdateManager();
+
+  // Node connection methods
+
+  /**
+   * Get the scene graph side list of RenderTasks.
+   * @param[in] systemLevel True if using the system-level overlay.
+   * @return The list of render tasks
+   */
+  RenderTaskList* GetRenderTaskList( bool systemLevel );
+
+  /**
+   * Installs a new layer as the root node.
+   * @pre The UpdateManager does not already have an installed root node.
+   * @pre The layer is of derived Node type Layer.
+   * @pre The layer does not have a parent.
+   * @param[in] layer The new root node.
+   * @param[in] systemLevel True if using the system-level overlay.
+   * @post The node is owned by UpdateManager.
+   */
+  void InstallRoot( Layer* layer, bool systemLevel );
+
+  /**
+   * Add a Node; UpdateManager takes ownership.
+   * @pre The node does not have a parent.
+   * @param[in] node The node to add.
+   */
+  void AddNode( Node* node );
+
+  /**
+   * Connect a Node to the scene-graph.
+   * A disconnected Node has has no parent or children, and its properties cannot be animated/constrained.
+   * @pre The node does not already have a parent.
+   * @param[in] node The new parent node.
+   * @param[in] node The node to connect.
+   */
+  void ConnectNode( Node* parent, Node* node, int index );
+
+  /**
+   * Disconnect a Node from the scene-graph.
+   * A disconnected Node has has no parent or children, and its properties cannot be animated/constrained.
+   * @pre The node has a parent.
+   * @param[in] node The node to disconnect.
+   */
+  void DisconnectNode( Node* node );
+
+  /**
+   * Called when a property is set on a disconnected Node (via public API)
+   * A disconnected Node has has no parent or children, and its properties cannot be animated/constrained.
+   * @pre The node does not have a parent.
+   * @param[in] node The node to set as "active".
+   */
+  void SetNodeActive( Node* node );
+
+  /**
+   * Destroy a Node owned by UpdateManager.
+   * This is not immediate; Nodes are passed to the RenderQueue to allow GL resources to be deleted.
+   * In the following update, the previously queued Nodes may be deleted.
+   * @pre The node has been disconnected from the scene-graph i.e. has no parent or children.
+   * @param[in] node The node to destroy.
+   */
+  void DestroyNode( Node* node );
+
+  /**
+   * Attach an object to a Node.
+   * The UpdateManager is responsible for calling NodeAttachment::Initialize().
+   * @param[in] node The node which will own the attachment.
+   * @param[in] attachment The object to attach.
+   */
+  void AttachToNode( Node* node, NodeAttachment* attachment );
+
+  /**
+   * Attach a renderer to the scene graph
+   */
+  void AttachToSceneGraph( RendererAttachment* renderer );
+
+
+  /**
+   * Add a newly created object.
+   * @param[in] object The object to add.
+   * @post The object is owned by UpdateManager.
+   */
+  void AddObject( PropertyOwner* object );
+
+  /**
+   * Remove an object.
+   * @param[in] object The object to remove.
+   */
+  void RemoveObject( PropertyOwner* object );
+
+  // Animations
+
+  /**
+   * Add a newly created animation.
+   * @param[in] animation The animation to add.
+   * @post The animation is owned by UpdateManager.
+   */
+  void AddAnimation( Animation* animation );
+
+  /**
+   * Stop an animation.
+   * @param[in] animation The animation to stop.
+   */
+  void StopAnimation( Animation* animation );
+
+  /**
+   * Remove an animation.
+   * @param[in] animation The animation to remove.
+   */
+  void RemoveAnimation( Animation* animation );
+
+  /**
+   * Query whether any animations are currently running.
+   * @return True if any animations are running.
+   */
+  bool IsAnimationRunning() const;
+
+  // Property Notification
+
+  /**
+   * Add a newly created property notification
+   * @param[in] propertyNotification The notification to add
+   * @post The propertyNotification is owned by UpdateManager.
+   */
+  void AddPropertyNotification( PropertyNotification* propertyNotification );
+
+  /**
+   * Remove a property notification
+   * @param[in] propertyNotification The notification to remove
+   */
+  void RemovePropertyNotification( PropertyNotification* propertyNotification );
+
+  /**
+   * Set Notify state for PropertyNotification
+   * @param[in] propertyNotification The notification to remove
+   * @param[in] notifyMode The notification mode.
+   */
+  void PropertyNotificationSetNotify( PropertyNotification* propertyNotification, PropertyNotification::NotifyMode notifyMode );
+
+  /**
+   * @brief Get the geometry owner
+   *
+   * @return The geometry owner
+   */
+  ObjectOwnerContainer< Geometry >& GetGeometryOwner();
+
+  /**
+   * @brief Get the material owner
+   *
+   * @return The material owner
+   */
+  ObjectOwnerContainer< Material >& GetMaterialOwner();
+
+  /**
+   * @brief Get the sampler owner
+   *
+   * @return The sampler owner
+   */
+  ObjectOwnerContainer< Sampler >& GetSamplerOwner();
+
+  /**
+   * @brief Get the property buffer owner
+   *
+   * @return The property buffer owner
+   */
+  ObjectOwnerContainer< PropertyBuffer >& GetPropertyBufferOwner();
+
+
+  // Shaders
+
+  /**
+   * Add a newly created shader.
+   * @param[in] shader The shader to add.
+   * @post The shader is owned by the UpdateManager.
+   */
+  void AddShader(Shader* shader);
+
+  /**
+   * Remove a shader.
+   * @pre The shader has been added to the UpdateManager.
+   * @param[in] shader The shader to remove.
+   * @post The shader is destroyed.
+   */
+  void RemoveShader(Shader* shader);
+
+  /**
+   * Set the shader program for a Shader object
+   * @param[in] shader        The shader to modify
+   * @param[in] shaderData    Source code, hash over source, and optional compiled binary for the shader program
+   * @param[in] modifiesGeometry True if the vertex shader modifies geometry
+   */
+  void SetShaderProgram( Shader* shader, Internal::ShaderDataPtr shaderData, bool modifiesGeometry );
+
+  /**
+   * @brief Accept compiled shaders passed back on render thread for saving.
+   * @param[in] shaderData Source code, hash over source, and corresponding compiled binary to be saved.
+   */
+  virtual void SaveBinary( Internal::ShaderDataPtr shaderData );
+
+  /**
+   * @brief Set the destination for compiled shader binaries to be passed on to.
+   * The dispatcher passed in will be called from the update thread.
+   * @param[in] upstream A sink for ShaderDatas to be passed into.
+   */
+  void SetShaderSaver( ShaderSaver& upstream );
+
+  // Gestures
+
+  /**
+   * Add a newly created gesture.
+   * @param[in] gesture The gesture to add.
+   * @post The gesture is owned by the UpdateManager.
+   */
+  void AddGesture( PanGesture* gesture );
+
+  /**
+   * Remove a gesture.
+   * @pre The gesture has been added to the UpdateManager.
+   * @param[in] gesture The gesture to remove.
+   * @post The gesture is destroyed.
+   */
+  void RemoveGesture( PanGesture* gesture );
+
+// Message queue handling
+
+  /**
+   * Reserve space for another message in the queue; this must then be initialized by the caller.
+   * The message will be read from the update-thread after the next FlushMessages is called.
+   * @post Calling this method may invalidate any previously returned slots.
+   * @param[in] size The message size with respect to the size of type "char".
+   * @param[in] updateScene A flag, when true denotes that the message will cause the scene-graph node tree to require an update.
+   * @note the default value of updateScene should match that in EventThreadServices::ReserveMessageSlot.
+   * @return A pointer to the first char allocated for the message.
+   */
+  unsigned int* ReserveMessageSlot( std::size_t size, bool updateScene = true );
+
+  /**
+   * @return the current event-buffer index.
+   */
+  BufferIndex GetEventBufferIndex() const
+  {
+    // inlined as its called often from event thread
+    return mSceneGraphBuffers.GetEventBufferIndex();
+  }
+
+  /**
+   * Called by the event-thread to signal that FlushQueue will be called
+   * e.g. when it has finished event processing.
+   */
+  void EventProcessingStarted();
+
+  /**
+   * Flush the set of messages, which were previously stored with QueueMessage().
+   * Calls to this thread-safe method should be minimized, to avoid thread blocking.
+   *
+   * @return True if there are messages to process.
+   */
+  bool FlushQueue();
+
+public:
+
+  /**
+   * Performs an Update traversal on the scene-graph.
+   * @param[in] elapsedSeconds The elapsed time that should be applied to animations.
+   * @param[in] lastVSyncTimeMilliseconds The last time, in milliseconds, that we had a VSync.
+   * @param[in] nextVSyncTimeMilliseconds The estimated time, in milliseconds, of the next VSync.
+   * @return True if further updates are required e.g. during animations.
+   */
+  unsigned int Update( float elapsedSeconds, unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds );
+
+  /**
+   * Set the background color i.e. the glClear color used at the beginning of each frame.
+   * @param[in] color The new background color.
+   */
+  void SetBackgroundColor(const Vector4& color);
+
+  /**
+   * Set the default surface rect.
+   * @param[in] rect The rect value representing the surface.
+   */
+  void SetDefaultSurfaceRect( const Rect<int>& rect );
+
+  /**
+   * @copydoc Dali::Stage::KeepRendering()
+   */
+  void KeepRendering( float durationSeconds );
+
+  /**
+   * Sets the depths of all layers.
+   * @param layers The layers in depth order.
+   * @param[in] systemLevel True if using the system-level overlay.
+   */
+  void SetLayerDepths( const std::vector< Layer* >& layers, bool systemLevel );
+
+private:
+
+  // Undefined
+  UpdateManager(const UpdateManager&);
+
+  // Undefined
+  UpdateManager& operator=(const UpdateManager& rhs);
+
+  /**
+   * Helper to check whether the update-thread should keep going.
+   * @param[in] elapsedSeconds The time in seconds since the previous update.
+   * @return True if the update-thread should keep going.
+   */
+  unsigned int KeepUpdatingCheck( float elapsedSeconds ) const;
+
+  /**
+   * Helper to calculate new camera setup when root node resizes.
+   * @param[in] updateBuffer The buffer to read the root node size from.
+   */
+  void UpdateProjectionAndViewMatrices(int updateBuffer);
+
+  /**
+   * Post process resources that have been updated by renderer
+   */
+  void PostProcessResources();
+
+  /**
+   * Helper to reset a Node properties.
+   * @param[in] node The node.
+   */
+  void ResetNodeProperty( Node& node );
+
+  /**
+   * Helper to reset all Node properties
+   */
+  void ResetProperties();
+
+  /**
+   * Perform gesture updates.
+   * @param[in]  lastVSyncTime  The last VSync time in milliseconds.
+   * @param[in]  nextVSyncTime  The estimated time of the next VSync in milliseconds.
+   * @return true, if any properties were updated.
+   */
+  bool ProcessGestures( unsigned int lastVSyncTimeMilliseconds, unsigned int nextVSyncTimeMilliseconds );
+
+  /**
+   * Perform animation updates
+   * @param[in] elapsedSeconds time since last frame
+   */
+  void Animate( float elapsedSeconds );
+
+  /**
+   * Perform constraint updates.
+   * @note Applies constraints to nodes first (depth first search order).
+   * Then shader constraints second (construction order)
+   */
+  void ApplyConstraints();
+
+  /**
+   * Perform property notification updates
+   */
+  void ProcessPropertyNotifications();
+
+  /**
+   * Pass shader binaries queued here on to event thread.
+   */
+  void ForwardCompiledShadersToEventThread();
+
+  /**
+   * Update the default camera.
+   * This must be altered to match the root Node for 2D layouting.
+   * @param[in] updateBuffer The buffer to read the root node size from.
+   */
+  void UpdateDefaultCamera( int updateBuffer );
+
+  /**
+   * Update node shaders, opacity, geometry etc.
+   */
+  void UpdateNodes();
+
+private:
+
+  // needs to be direct member so that getter for event buffer can be inlined
+  SceneGraphBuffers mSceneGraphBuffers;
+
+  struct Impl;
+  Impl* mImpl;
+
+};
+
+// Messages for UpdateManager
+
+inline void InstallRootMessage( UpdateManager& manager, Layer& root, bool systemLevel )
+{
+  typedef MessageValue2< UpdateManager, Layer*, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::InstallRoot, &root, systemLevel );
+}
+
+inline void AddNodeMessage( UpdateManager& manager, Node& node )
+{
+  typedef MessageValue1< UpdateManager, OwnerPointer<Node> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddNode, &node );
+}
+
+inline void ConnectNodeMessage( UpdateManager& manager, const Node& constParent, const Node& constChild, int index )
+{
+  // Update thread can edit the object
+  Node& parent = const_cast< Node& >( constParent );
+  Node& child = const_cast< Node& >( constChild );
+
+  typedef MessageValue3< UpdateManager, Node*, Node*, int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::ConnectNode, &parent, &child, index );
+}
+
+inline void DisconnectNodeMessage( UpdateManager& manager, const Node& constNode )
+{
+  // Scene graph thread can modify this object.
+  Node& node = const_cast< Node& >( constNode );
+
+  typedef MessageValue1< UpdateManager, Node* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::DisconnectNode, &node );
+}
+
+inline void DestroyNodeMessage( UpdateManager& manager, const Node& constNode )
+{
+  // Scene graph thread can destroy this object.
+  Node& node = const_cast< Node& >( constNode );
+
+  typedef MessageValue1< UpdateManager, Node* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::DestroyNode, &node );
+}
+
+inline void AttachToNodeMessage( UpdateManager& manager, const Node& constParent, NodeAttachment* attachment )
+{
+  // Scene graph thread can modify this object.
+  Node& parent = const_cast< Node& >( constParent );
+
+  // @todo MESH_REWORK Don't pass by owner pointer after merge with SceneGraph::RenderableAttachment ? (not needed if we split RendererAttachment to 2 objects)
+  typedef MessageValue2< UpdateManager, Node*, NodeAttachmentOwner > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AttachToNode, &parent, attachment );
+}
+
+inline void AttachToSceneGraphMessage( UpdateManager& manager, RendererAttachment* renderer )
+{
+  // @todo MESH_REWORK Pass by owner pointer after merge with SceneGraph::RenderableAttachment
+  typedef MessageValue1< UpdateManager, RendererAttachment* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AttachToSceneGraph, renderer );
+}
+
+inline void AddObjectMessage( UpdateManager& manager, PropertyOwner* object )
+{
+  typedef MessageValue1< UpdateManager, OwnerPointer<PropertyOwner> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddObject, object );
+}
+
+inline void RemoveObjectMessage( UpdateManager& manager, PropertyOwner* object )
+{
+  typedef MessageValue1< UpdateManager, PropertyOwner* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RemoveObject, object );
+}
+
+inline void AddAnimationMessage( UpdateManager& manager, Animation* animation )
+{
+  typedef MessageValue1< UpdateManager, Animation* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddAnimation, animation );
+}
+
+inline void StopAnimationMessage( UpdateManager& manager, const Animation& constAnimation )
+{
+  // The scene-graph thread owns this object so it can safely edit it.
+  Animation& animation = const_cast< Animation& >( constAnimation );
+
+  typedef MessageValue1< UpdateManager, Animation* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::StopAnimation, &animation );
+}
+
+inline void RemoveAnimationMessage( UpdateManager& manager, const Animation& constAnimation )
+{
+  // The scene-graph thread owns this object so it can safely edit it.
+  Animation& animation = const_cast< Animation& >( constAnimation );
+
+  typedef MessageValue1< UpdateManager, Animation* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RemoveAnimation, &animation );
+}
+
+inline void AddPropertyNotificationMessage( UpdateManager& manager, PropertyNotification* propertyNotification )
+{
+  typedef MessageValue1< UpdateManager, PropertyNotification* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddPropertyNotification, propertyNotification );
+}
+
+inline void RemovePropertyNotificationMessage( UpdateManager& manager, const PropertyNotification& constPropertyNotification )
+{
+  // The scene-graph thread owns this object so it can safely edit it.
+  PropertyNotification& propertyNotification = const_cast< PropertyNotification& >( constPropertyNotification );
+
+  typedef MessageValue1< UpdateManager, PropertyNotification* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RemovePropertyNotification, &propertyNotification );
+}
+
+inline void PropertyNotificationSetNotifyModeMessage( UpdateManager& manager,
+                                                      const PropertyNotification* constPropertyNotification,
+                                                      PropertyNotification::NotifyMode notifyMode )
+{
+  // The scene-graph thread owns this object so it can safely edit it.
+  PropertyNotification* propertyNotification = const_cast< PropertyNotification* >( constPropertyNotification );
+
+  typedef MessageValue2< UpdateManager, PropertyNotification*, PropertyNotification::NotifyMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::PropertyNotificationSetNotify, propertyNotification, notifyMode );
+}
+
+// The render thread can safely change the Shader
+inline void AddShaderMessage( UpdateManager& manager, Shader& shader )
+{
+  typedef MessageValue1< UpdateManager, OwnerPointer< Shader > > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddShader, &shader );
+}
+
+// The render thread can safely change the Shader
+inline void RemoveShaderMessage( UpdateManager& manager, Shader& shader )
+{
+  typedef MessageValue1< UpdateManager, Shader* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RemoveShader, &shader );
+}
+
+inline void SetShaderProgramMessage( UpdateManager& manager,
+                                     Shader& shader,
+                                     Internal::ShaderDataPtr shaderData,
+                                     bool modifiesGeometry )
+{
+  typedef MessageValue3< UpdateManager, Shader*, Internal::ShaderDataPtr, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::SetShaderProgram, &shader, shaderData, modifiesGeometry );
+}
+
+inline void SetBackgroundColorMessage( UpdateManager& manager, const Vector4& color )
+{
+  typedef MessageValue1< UpdateManager, Vector4 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::SetBackgroundColor, color );
+}
+
+inline void SetDefaultSurfaceRectMessage( UpdateManager& manager, const Rect<int>& rect  )
+{
+  typedef MessageValue1< UpdateManager, Rect<int> > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::SetDefaultSurfaceRect, rect );
+}
+
+inline void KeepRenderingMessage( UpdateManager& manager, float durationSeconds )
+{
+  typedef MessageValue1< UpdateManager, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::KeepRendering, durationSeconds );
+}
+
+/**
+ * Create a message for setting the depth of a layer
+ * @param[in] manager The update manager
+ * @param[in] layers list of layers
+ * @param[in] systemLevel True if the layers are added via the SystemOverlay API
+ */
+inline void SetLayerDepthsMessage( UpdateManager& manager, const std::vector< Layer* >& layers, bool systemLevel )
+{
+  typedef MessageValue2< UpdateManager, std::vector< Layer* >, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::SetLayerDepths, layers, systemLevel );
+}
+
+inline void AddGestureMessage( UpdateManager& manager, PanGesture* gesture )
+{
+  typedef MessageValue1< UpdateManager, PanGesture* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::AddGesture, gesture );
+}
+
+inline void RemoveGestureMessage( UpdateManager& manager, PanGesture* gesture )
+{
+  typedef MessageValue1< UpdateManager, PanGesture* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &UpdateManager::RemoveGesture, gesture );
+}
+
+template< typename T >
+inline void AddMessage( UpdateManager& manager, ObjectOwnerContainer<T>& owner, T& object )
+{
+  typedef MessageValue1< ObjectOwnerContainer<T>, OwnerPointer< T > > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &owner, &ObjectOwnerContainer<T>::Add, &object );
+}
+
+template< typename T >
+inline void RemoveMessage( UpdateManager& manager, ObjectOwnerContainer<T>& owner, T& object )
+{
+  typedef MessageValue1< ObjectOwnerContainer<T>, T* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = manager.ReserveMessageSlot( sizeof( LocalType ) );
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &owner, &ObjectOwnerContainer<T>::Remove, &object );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_UPDATE_MANAGER_H__
diff --git a/dali/internal/update/node-attachments/node-attachment-declarations.h b/dali/internal/update/node-attachments/node-attachment-declarations.h
new file mode 100644 (file)
index 0000000..fcc66a9
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_DECLARATIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/common/owner-container.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class NodeAttachment;
+typedef OwnerPointer<NodeAttachment> NodeAttachmentOwner;
+
+typedef OwnerContainer< NodeAttachment* >           NodeAttachmentOwnerContainer;
+typedef NodeAttachmentOwnerContainer::Iterator      NodeAttachmentIter;
+typedef NodeAttachmentOwnerContainer::ConstIterator NodeAttachmentConstIter;
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_DECLARATIONS_H__
diff --git a/dali/internal/update/node-attachments/node-attachment.cpp b/dali/internal/update/node-attachments/node-attachment.cpp
new file mode 100644 (file)
index 0000000..659d109
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/node-attachments/node-attachment.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/nodes/node.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+NodeAttachment::NodeAttachment()
+: mParent(NULL)
+{
+}
+
+NodeAttachment::~NodeAttachment()
+{
+}
+
+void NodeAttachment::SetParent( Node& parent )
+{
+  DALI_ASSERT_DEBUG(mParent == NULL);
+
+  mParent = &parent;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/node-attachments/node-attachment.h b/dali/internal/update/node-attachments/node-attachment.h
new file mode 100644 (file)
index 0000000..7803450
--- /dev/null
@@ -0,0 +1,159 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>    // NULL
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Node;
+class RenderableAttachment;
+class SceneController;
+
+/**
+ * NodeAttachment is a base class for objects attached to Nodes in the scene graph.
+ * The position of the object is provided by its parent node.
+ * NodeAttachment data is double-buffered. This allows an update thread to modify node data, without interferring
+ * with another thread reading the values from the previous update traversal.
+ */
+class NodeAttachment
+{
+public:
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodeAttachment();
+
+  /**
+   * Second-phase construction.
+   * This is called by the UpdateManager when the attachment is attached to the scene-graph.
+   * @param[in] sceneController Allows attachments to get camera controllers.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  virtual void Initialize( SceneController& sceneController, BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Called shortly before destruction.
+   * After this method has been called, the SceneController cannot be safely accessed.
+   */
+  virtual void OnDestroy() = 0;
+
+  /**
+   * Called when the parent node is connected to the SceneGraph
+   */
+  virtual void ConnectedToSceneGraph() = 0;
+
+  /**
+   * Called when the parent node is disconnected from the SceneGraph
+   */
+  virtual void DisconnectedFromSceneGraph( ) = 0;
+
+  /**
+   * Set the parent of a NodeAttachment.
+   * @param[in] parent the new parent.
+   */
+  void SetParent( Node& parent );
+
+  /**
+   * Retrieve the parent node of a NodeAttachment.
+   * @return The parent node, or NULL if the NodeAttachment has not been added to the scene-graph.
+   */
+  Node& GetParent()
+  {
+    DALI_ASSERT_DEBUG( mParent != NULL );
+    return *mParent;
+  }
+
+  /**
+   * Retrieve the parent node of a NodeAttachment.
+   * @return The parent node, or NULL if the NodeAttachment has not been added to the scene-graph.
+   */
+  Node& GetParent() const
+  {
+    DALI_ASSERT_DEBUG( mParent != NULL );
+    return *mParent;
+  }
+
+  // RenderableAttachment interface
+
+  /**
+   * Query whether the attachment is renderable i.e. implements the SceneGraph::RenderableAttachment interface.
+   * @return True if the attachment is renderable.
+   */
+  bool IsRenderable()
+  {
+    return (GetRenderable() != NULL);
+  }
+
+  /**
+   * Convert an attachment to a renderable attachment.
+   * @return A pointer to the renderable attachment, or NULL.
+   */
+  virtual RenderableAttachment* GetRenderable() = 0;
+
+  // Update methods
+
+  /**
+   * Called when the attachment or it's owning node is flagged as dirty during scene graph updates.
+   * Allows derived classes to perform extra processing
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] owningNode The attachment's owning node
+   * @param[in] nodeDirtyFlags of the owning node
+   */
+  virtual void Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags ) {}
+
+protected:
+
+  /**
+   * Derived versions of NodeAttachment should be constructed.
+   */
+  NodeAttachment();
+
+private:
+
+  // Undefined
+  NodeAttachment( const NodeAttachment& );
+
+  // Undefined
+  NodeAttachment& operator=( const NodeAttachment& rhs );
+
+protected:
+
+  Node* mParent; ///< Pointer to parent node which owns the attachment.
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_ATTACHMENT_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-camera-attachment.cpp
new file mode 100644 (file)
index 0000000..e62a7d8
--- /dev/null
@@ -0,0 +1,575 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/node-attachments/scene-graph-camera-attachment.h>
+
+// INTERNAL HEADERS
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/integration-api/debug.h>
+
+namespace // unnamed namespace
+{
+const unsigned int UPDATE_COUNT        = 2u;  // Update projection or view matrix this many frames after a change
+const unsigned int COPY_PREVIOUS_MATRIX = 1u; // Copy view or projection matrix from previous frame
+}
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+namespace
+{
+
+void LookAt(Matrix& result, const Vector3& eye, const Vector3& target, const Vector3& up)
+{
+  Vector3 vZ = target - eye;
+  vZ.Normalize();
+
+  Vector3 vX = up.Cross(vZ);
+  vX.Normalize();
+
+  Vector3 vY = vZ.Cross(vX);
+  vY.Normalize();
+
+  result.SetInverseTransformComponents(vX, vY, vZ, eye);
+}
+
+
+void Frustum(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis)
+{
+  float deltaZ = far - near;
+  if ((near <= 0.0f) || (far <= 0.0f) || Equals(right, left) || Equals(bottom, top) || (deltaZ <= 0.0f))
+  {
+    DALI_LOG_ERROR("Invalid parameters passed into Frustum!");
+    DALI_ASSERT_DEBUG("Invalid parameters passed into Frustum!");
+    return;
+  }
+
+  float deltaX = right - left;
+  float deltaY = invertYAxis ? bottom - top : top - bottom;
+
+  result.SetIdentity();
+
+  float* m = result.AsFloat();
+  m[0] = -2.0f * near / deltaX;
+  m[1] = m[2] = m[3] = 0.0f;
+
+  m[5] = -2.0f * near / deltaY;
+  m[4] = m[6] = m[7] = 0.0f;
+
+  m[8] = (right + left) / deltaX;
+  m[9] = (top + bottom) / deltaY;
+  m[10] = (near + far) / deltaZ;
+  m[11] = 1.0f;
+
+  m[14] = -2.0f * near * far / deltaZ;
+  m[12] = m[13] = m[15] = 0.0f;
+}
+
+void Perspective(Matrix& result, float fovy, float aspect, float near, float far, bool invertYAxis, const Vector2& stereoBias )
+{
+  float frustumH = tanf( fovy * 0.5f ) * near;
+  float frustumW = frustumH * aspect;
+  Vector2 bias = stereoBias * 0.5f;
+
+  Frustum(result, -(frustumW + bias.x), frustumW - bias.x, -(frustumH + bias.y), frustumH - bias.y, near, far, invertYAxis);
+}
+
+void Orthographic(Matrix& result, float left, float right, float bottom, float top, float near, float far, bool invertYAxis)
+{
+  if ( Equals(right, left) || Equals(top, bottom) || Equals(far, near) )
+  {
+    DALI_LOG_ERROR( "Cannot create orthographic projection matrix with a zero dimension." );
+    DALI_ASSERT_DEBUG( "Cannot create orthographic projection matrix with a zero dimension." );
+    return;
+  }
+
+  float deltaX = right - left;
+  float deltaY = invertYAxis ? bottom - top : top - bottom;
+  float deltaZ = far - near;
+
+  float *m = result.AsFloat();
+  m[0] = -2.0f / deltaX;
+  m[1] = 0.0f;
+  m[2] = 0.0f;
+  m[3] = 0.0f;
+
+  m[4] = 0.0f;
+  m[5] = -2.0f / deltaY;
+  m[6] = 0.0f;
+  m[7] = 0.0f;
+
+  m[8] = 0.0f;
+  m[9] = 0.0f;
+  m[10] = 2.0f / deltaZ;
+  m[11] = 0.0f;
+  m[12] = -(right + left) / deltaX;
+  m[13] = -(top + bottom) / deltaY;
+  m[14] = -(near + far)   / deltaZ;
+  m[15] = 1.0f;
+}
+
+} // unnamed namespace
+
+const Dali::Camera::Type CameraAttachment::DEFAULT_TYPE( Dali::Camera::FREE_LOOK );
+const Dali::Camera::ProjectionMode CameraAttachment::DEFAULT_MODE( Dali::Camera::PERSPECTIVE_PROJECTION );
+const bool  CameraAttachment::DEFAULT_INVERT_Y_AXIS( false );
+const float CameraAttachment::DEFAULT_FIELD_OF_VIEW( 45.0f*(M_PI/180.0f) );
+const float CameraAttachment::DEFAULT_ASPECT_RATIO( 4.0f/3.0f );
+const float CameraAttachment::DEFAULT_LEFT_CLIPPING_PLANE(-240.0f);
+const float CameraAttachment::DEFAULT_RIGHT_CLIPPING_PLANE(240.0f);
+const float CameraAttachment::DEFAULT_TOP_CLIPPING_PLANE(-400.0f);
+const float CameraAttachment::DEFAULT_BOTTOM_CLIPPING_PLANE(400.0f);
+const float CameraAttachment::DEFAULT_NEAR_CLIPPING_PLANE( 800.0f ); // default height of the screen
+const float CameraAttachment::DEFAULT_FAR_CLIPPING_PLANE( DEFAULT_NEAR_CLIPPING_PLANE + 2.f * DEFAULT_NEAR_CLIPPING_PLANE );
+const Vector2 CameraAttachment::DEFAULT_STEREO_BIAS( 0.0f, 0.0f );
+const Vector3 CameraAttachment::DEFAULT_TARGET_POSITION( 0.0f, 0.0f, 0.0f );
+
+
+CameraAttachment::CameraAttachment()
+: NodeAttachment(),
+  mUpdateViewFlag( UPDATE_COUNT ),
+  mUpdateProjectionFlag( UPDATE_COUNT ),
+  mType( DEFAULT_TYPE ),
+  mProjectionMode( DEFAULT_MODE ),
+  mInvertYAxis( DEFAULT_INVERT_Y_AXIS ),
+  mFieldOfView( DEFAULT_FIELD_OF_VIEW ),
+  mAspectRatio( DEFAULT_ASPECT_RATIO ),
+  mLeftClippingPlane( DEFAULT_LEFT_CLIPPING_PLANE ),
+  mRightClippingPlane( DEFAULT_RIGHT_CLIPPING_PLANE ),
+  mTopClippingPlane( DEFAULT_TOP_CLIPPING_PLANE ),
+  mBottomClippingPlane( DEFAULT_BOTTOM_CLIPPING_PLANE ),
+  mNearClippingPlane( DEFAULT_NEAR_CLIPPING_PLANE ),
+  mFarClippingPlane( DEFAULT_FAR_CLIPPING_PLANE ),
+  mStereoBias( DEFAULT_STEREO_BIAS ),
+  mTargetPosition( DEFAULT_TARGET_POSITION ),
+  mViewMatrix(),
+  mProjectionMatrix(),
+  mInverseViewProjection( Matrix::IDENTITY )
+{
+}
+
+CameraAttachment* CameraAttachment::New()
+{
+  return new CameraAttachment();
+}
+
+void CameraAttachment::Initialize( SceneController& sceneController, BufferIndex updateBufferIndex )
+{
+  // do nothing
+}
+
+void CameraAttachment::OnDestroy()
+{
+  // do nothing
+}
+
+void CameraAttachment::ConnectedToSceneGraph()
+{
+  // do nothing
+}
+
+void CameraAttachment::DisconnectedFromSceneGraph()
+{
+  // do nothing
+}
+
+CameraAttachment::~CameraAttachment()
+{
+}
+
+RenderableAttachment* CameraAttachment::GetRenderable()
+{
+  return NULL;
+}
+
+void CameraAttachment::SetType( Dali::Camera::Type type )
+{
+  mType = type;
+}
+
+void CameraAttachment::SetProjectionMode( Dali::Camera::ProjectionMode mode )
+{
+  mProjectionMode = mode;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetInvertYAxis( bool invertYAxis )
+{
+  mInvertYAxis = invertYAxis;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetFieldOfView( float fieldOfView )
+{
+  mFieldOfView = fieldOfView;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetAspectRatio( float aspectRatio )
+{
+  mAspectRatio = aspectRatio;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetStereoBias( const Vector2& stereoBias )
+{
+  mStereoBias = stereoBias;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetLeftClippingPlane( float leftClippingPlane )
+{
+  mLeftClippingPlane = leftClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetRightClippingPlane( float rightClippingPlane )
+{
+  mRightClippingPlane = rightClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetTopClippingPlane( float topClippingPlane )
+{
+  mTopClippingPlane = topClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetBottomClippingPlane( float bottomClippingPlane )
+{
+  mBottomClippingPlane = bottomClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetNearClippingPlane( float nearClippingPlane )
+{
+  mNearClippingPlane = nearClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetFarClippingPlane( float farClippingPlane )
+{
+  mFarClippingPlane = farClippingPlane;
+  mUpdateProjectionFlag = UPDATE_COUNT;
+}
+
+void CameraAttachment::SetTargetPosition( const Vector3& targetPosition )
+{
+  mTargetPosition = targetPosition;
+  mUpdateViewFlag = UPDATE_COUNT;
+}
+
+const Matrix& CameraAttachment::GetProjectionMatrix( BufferIndex bufferIndex ) const
+{
+  return mProjectionMatrix[ bufferIndex ];
+}
+
+const Matrix& CameraAttachment::GetViewMatrix( BufferIndex bufferIndex ) const
+{
+  return mViewMatrix[ bufferIndex ];
+}
+
+const Matrix& CameraAttachment::GetInverseViewProjectionMatrix( BufferIndex bufferIndex ) const
+{
+  return mInverseViewProjection[ bufferIndex ];
+}
+
+const PropertyInputImpl* CameraAttachment::GetProjectionMatrix() const
+{
+  return &mProjectionMatrix;
+}
+
+const PropertyInputImpl* CameraAttachment::GetViewMatrix() const
+{
+  return &mViewMatrix;
+}
+
+void CameraAttachment::Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags )
+{
+  // if owning node has changes in world position we need to update camera for next 2 frames
+  if( nodeDirtyFlags & TransformFlag )
+  {
+    mUpdateViewFlag = UPDATE_COUNT;
+  }
+  if( nodeDirtyFlags & VisibleFlag )
+  {
+    // If the visibility changes, the projection matrix needs to be re-calculated.
+    // It may happen the first time an actor is rendered it's rendered only once and becomes invisible,
+    // in the following update the node will be skipped leaving the projection matrix (double buffered)
+    // with the Identity.
+    mUpdateProjectionFlag = UPDATE_COUNT;
+  }
+
+  // if either matrix changed, we need to recalculate the inverse matrix for hit testing to work
+  unsigned int viewUpdateCount = UpdateViewMatrix( updateBufferIndex, owningNode );
+  unsigned int projectionUpdateCount = UpdateProjection( updateBufferIndex );
+
+  // if model or view matrix changed we need to either recalculate the inverse VP or copy previous
+  if( viewUpdateCount > COPY_PREVIOUS_MATRIX || projectionUpdateCount > COPY_PREVIOUS_MATRIX )
+  {
+    // either has actually changed so recalculate
+    Matrix::Multiply( mInverseViewProjection[ updateBufferIndex ], mViewMatrix[ updateBufferIndex ], mProjectionMatrix[ updateBufferIndex ] );
+    UpdateFrustum( updateBufferIndex );
+
+    // ignore the error, if the view projection is incorrect (non inversible) then you will have tough times anyways
+    static_cast< void >( mInverseViewProjection[ updateBufferIndex ].Invert() );
+  }
+  else if( viewUpdateCount == COPY_PREVIOUS_MATRIX || projectionUpdateCount == COPY_PREVIOUS_MATRIX )
+  {
+    // neither has actually changed, but we might copied previous frames value so need to
+    // copy the previous inverse and frustum as well
+    mInverseViewProjection[updateBufferIndex] = mInverseViewProjection[updateBufferIndex ? 0 : 1];
+    mFrustum[ updateBufferIndex ] = mFrustum[ updateBufferIndex ? 0 : 1 ];
+  }
+}
+
+bool CameraAttachment::ViewMatrixUpdated()
+{
+  return 0u != mUpdateViewFlag;
+}
+
+unsigned int CameraAttachment::UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode )
+{
+  unsigned int retval( mUpdateViewFlag );
+  if( 0u != mUpdateViewFlag )
+  {
+    if( COPY_PREVIOUS_MATRIX == mUpdateViewFlag )
+    {
+      // The projection matrix was updated in the previous frame; copy it
+      mViewMatrix.CopyPrevious( updateBufferIndex );
+    }
+    else // UPDATE_COUNT == mUpdateViewFlag
+    {
+      switch( mType )
+      {
+        // camera orientation taken from node - i.e. look in abitrary, unconstrained direction
+        case Dali::Camera::FREE_LOOK:
+          {
+          Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
+          viewMatrix.SetInverseTransformComponents( Vector3::ONE, owningNode.GetWorldOrientation( updateBufferIndex ),
+                                                    owningNode.GetWorldPosition( updateBufferIndex ) );
+          mViewMatrix.SetDirty( updateBufferIndex );
+          break;
+        }
+          // camera orientation constrained to look at a target
+        case Dali::Camera::LOOK_AT_TARGET:
+          {
+          Matrix& viewMatrix = mViewMatrix.Get( updateBufferIndex );
+          LookAt( viewMatrix, owningNode.GetWorldPosition( updateBufferIndex ), mTargetPosition,
+                  owningNode.GetWorldOrientation( updateBufferIndex ).Rotate( Vector3::YAXIS ) );
+          mViewMatrix.SetDirty( updateBufferIndex );
+          break;
+        }
+      }
+    }
+    --mUpdateViewFlag;
+  }
+  return retval;
+}
+
+void CameraAttachment::UpdateFrustum( BufferIndex updateBufferIndex, bool normalize )
+{
+
+  // Extract the clip matrix planes
+  Matrix clipMatrix;
+  Matrix::Multiply( clipMatrix, mViewMatrix[ updateBufferIndex ], mProjectionMatrix[ updateBufferIndex ] );
+
+  const float* cm = clipMatrix.AsFloat();
+  FrustumPlanes& planes = mFrustum[ updateBufferIndex ];
+
+  // Left
+  planes.mPlanes[ 0 ].mNormal.x = cm[ 3 ]  + cm[ 0 ]; // column 4 + column 1
+  planes.mPlanes[ 0 ].mNormal.y = cm[ 7 ]  + cm[ 4 ];
+  planes.mPlanes[ 0 ].mNormal.z = cm[ 11 ] + cm[ 8 ];
+  planes.mPlanes[ 0 ].mDistance = cm[ 15 ] + cm[ 12 ];
+
+  // Right
+  planes.mPlanes[ 1 ].mNormal.x = cm[ 3 ]  - cm[ 0 ]; // column 4 - column 1
+  planes.mPlanes[ 1 ].mNormal.y = cm[ 7 ]  - cm[ 4 ];
+  planes.mPlanes[ 1 ].mNormal.z = cm[ 11 ] - cm[ 8 ];
+  planes.mPlanes[ 1 ].mDistance = cm[ 15 ] - cm[ 12 ];
+
+  // Bottom
+  planes.mPlanes[ 2 ].mNormal.x = cm[ 3 ]  + cm[ 1 ]; // column 4 + column 2
+  planes.mPlanes[ 2 ].mNormal.y = cm[ 7 ]  + cm[ 5 ];
+  planes.mPlanes[ 2 ].mNormal.z = cm[ 11 ] + cm[ 9 ];
+  planes.mPlanes[ 2 ].mDistance = cm[ 15 ] + cm[ 13 ];
+
+  // Top
+  planes.mPlanes[ 3 ].mNormal.x = cm[ 3 ]  - cm[ 1 ]; // column 4 - column 2
+  planes.mPlanes[ 3 ].mNormal.y = cm[ 7 ]  - cm[ 5 ];
+  planes.mPlanes[ 3 ].mNormal.z = cm[ 11 ] - cm[ 9 ];
+  planes.mPlanes[ 3 ].mDistance = cm[ 15 ] - cm[ 13 ];
+
+  // Near
+  planes.mPlanes[ 4 ].mNormal.x = cm[ 3 ]  + cm[ 2 ]; // column 4 + column 3
+  planes.mPlanes[ 4 ].mNormal.y = cm[ 7 ]  + cm[ 6 ];
+  planes.mPlanes[ 4 ].mNormal.z = cm[ 11 ] + cm[ 10 ];
+  planes.mPlanes[ 4 ].mDistance = cm[ 15 ] + cm[ 14 ];
+
+  // Far
+  planes.mPlanes[ 5 ].mNormal.x = cm[ 3 ]  - cm[ 2 ]; // column 4 - column 3
+  planes.mPlanes[ 5 ].mNormal.y = cm[ 7 ]  - cm[ 6 ];
+  planes.mPlanes[ 5 ].mNormal.z = cm[ 11 ] - cm[ 10 ];
+  planes.mPlanes[ 5 ].mDistance = cm[ 15 ] - cm[ 14 ];
+
+  if ( normalize )
+  {
+    for ( unsigned int i = 0; i < 6; ++i )
+    {
+      // Normalize planes to ensure correct bounding distance checking
+      Plane& plane = planes.mPlanes[ i ];
+      float l = 1.0f / plane.mNormal.Length();
+      plane.mNormal *= l;
+      plane.mDistance *= l;
+    }
+  }
+  mFrustum[ updateBufferIndex ? 0 : 1 ] = planes;
+}
+
+bool CameraAttachment::CheckSphereInFrustum( BufferIndex bufferIndex, const Vector3& origin, float radius )
+{
+  const FrustumPlanes& planes = mFrustum[ bufferIndex ];
+  for ( uint32_t i = 0; i < 6; ++i )
+  {
+    if ( ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( origin ) ) < -radius )
+    {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool CameraAttachment::CheckAABBInFrustum( BufferIndex bufferIndex, const Vector3& origin, const Vector3& halfExtents )
+{
+  const FrustumPlanes& planes = mFrustum[ bufferIndex ];
+  Vector3 tln = origin + Vector3( -halfExtents );
+  Vector3 trn = origin + Vector3( halfExtents.x, -halfExtents.y, -halfExtents.z );
+  Vector3 bln = origin + Vector3( -halfExtents.x, halfExtents.y, -halfExtents.z );
+  Vector3 brn = origin + Vector3( halfExtents.x, halfExtents.y, -halfExtents.z );
+  Vector3 tlf = origin + Vector3( -halfExtents.x, -halfExtents.y, halfExtents.z );
+  Vector3 trf = origin + Vector3( halfExtents.x, -halfExtents.y, halfExtents.z );
+  Vector3 blf = origin + Vector3( -halfExtents.x, halfExtents.y, halfExtents.z );
+  Vector3 brf = origin + Vector3( halfExtents.x, halfExtents.y, halfExtents.z );
+
+  for ( uint32_t i = 0; i < 6; ++i )
+  {
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( tln ) >= 0 )
+    {
+      continue;
+    }
+
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( trn ) >= 0 )
+    {
+      continue;
+    }
+
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( bln ) >= 0 )
+    {
+      continue;
+    }
+
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( brn ) >= 0 )
+    {
+      continue;
+    }
+
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( tlf ) >= 0 )
+    {
+      continue;
+    }
+
+     if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( trf ) >= 0 )
+    {
+      continue;
+    }
+
+     if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( blf ) >= 0 )
+    {
+      continue;
+    }
+
+    if ( planes.mPlanes[ i ].mDistance + planes.mPlanes[ i ].mNormal.Dot( brf ) >= 0 )
+    {
+      continue;
+    }
+    return false;
+  }
+  return true;
+}
+
+unsigned int CameraAttachment::UpdateProjection( BufferIndex updateBufferIndex )
+{
+  unsigned int retval( mUpdateProjectionFlag );
+  // Early-exit if no update required
+  if ( 0u != mUpdateProjectionFlag )
+  {
+    if ( COPY_PREVIOUS_MATRIX == mUpdateProjectionFlag )
+    {
+      // The projection matrix was updated in the previous frame; copy it
+      mProjectionMatrix.CopyPrevious( updateBufferIndex );
+    }
+    else // UPDATE_COUNT == mUpdateProjectionFlag
+    {
+      switch( mProjectionMode )
+      {
+        case Dali::Camera::PERSPECTIVE_PROJECTION:
+        {
+          Matrix &projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
+          Perspective( projectionMatrix,
+                       mFieldOfView,
+                       mAspectRatio,
+                       mNearClippingPlane,
+                       mFarClippingPlane,
+                       mInvertYAxis,
+                       mStereoBias );
+          break;
+        }
+        case Dali::Camera::ORTHOGRAPHIC_PROJECTION:
+        {
+          Matrix &projectionMatrix = mProjectionMatrix.Get(updateBufferIndex);
+          Orthographic( projectionMatrix,
+                        mLeftClippingPlane,   mRightClippingPlane,
+                        mBottomClippingPlane, mTopClippingPlane,
+                        mNearClippingPlane,   mFarClippingPlane,
+                        mInvertYAxis );
+          break;
+        }
+      }
+
+      mProjectionMatrix.SetDirty(updateBufferIndex);
+    }
+    --mUpdateProjectionFlag;
+  }
+  return retval;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/node-attachments/scene-graph-camera-attachment.h b/dali/internal/update/node-attachments/scene-graph-camera-attachment.h
new file mode 100644 (file)
index 0000000..2dccea4
--- /dev/null
@@ -0,0 +1,482 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_CAMERA_ATTACHMENT_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_CAMERA_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/inherited-property.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< Dali::Camera::Type >
+: public BasicType< Dali::Camera::Type > {};
+template <> struct ParameterType< Dali::Camera::ProjectionMode >
+: public BasicType< Dali::Camera::ProjectionMode > {};
+
+namespace SceneGraph
+{
+
+class RenderableAttachment;
+class SceneController;
+
+/**
+ * An attachment for camera objects and their properties.
+ */
+class CameraAttachment : public NodeAttachment
+{
+public:
+  static const Dali::Camera::Type DEFAULT_TYPE;
+  static const Dali::Camera::ProjectionMode DEFAULT_MODE;
+  static const bool  DEFAULT_INVERT_Y_AXIS;
+  static const float DEFAULT_FIELD_OF_VIEW;
+  static const float DEFAULT_ASPECT_RATIO;
+  static const float DEFAULT_LEFT_CLIPPING_PLANE;
+  static const float DEFAULT_RIGHT_CLIPPING_PLANE;
+  static const float DEFAULT_TOP_CLIPPING_PLANE;
+  static const float DEFAULT_BOTTOM_CLIPPING_PLANE;
+  static const float DEFAULT_NEAR_CLIPPING_PLANE;
+  static const float DEFAULT_FAR_CLIPPING_PLANE;
+  static const Vector2 DEFAULT_STEREO_BIAS;
+  static const Vector3 DEFAULT_TARGET_POSITION;
+
+  /**
+   * Plane equation container for a plane of the view frustum
+   */
+  struct Plane
+  {
+    Vector3 mNormal;
+    float mDistance;
+  };
+
+  /**
+   * @brief Container for six planes in a view frustum
+   */
+  struct FrustumPlanes
+  {
+    Plane mPlanes[ 6 ];
+  };
+
+  /**
+   * Construct a new CameraAttachment.
+   * @return a new camera.
+   */
+  static CameraAttachment* New();
+
+  /**
+   * @copydoc NodeAttachment::Initialize().
+   */
+  virtual void Initialize( SceneController& sceneController, BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc NodeAttachment::OnDestroy().
+   */
+  virtual void OnDestroy();
+
+  /**
+   * @copydoc NodeAttachment::ConnectedToSceneGraph()
+   */
+  virtual void ConnectedToSceneGraph();
+
+  /**
+   * @copydoc NodeAttachment::DisconnectedFromSceneGraph()
+   */
+  virtual void DisconnectedFromSceneGraph();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~CameraAttachment();
+
+  /**
+   * @copydoc NodeAttachment::GetRenderable.
+   * @return Always NULL.
+   */
+  virtual RenderableAttachment* GetRenderable();
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetType
+   */
+  void SetType( Dali::Camera::Type type );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetInvertYAxis
+   */
+  void SetInvertYAxis( bool invertYAxis );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetProjectionMode
+   */
+  void SetProjectionMode( Dali::Camera::ProjectionMode projectionMode );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetFieldOfView
+   */
+  void SetFieldOfView( float fieldOfView );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetAspectRatio
+   */
+  void SetAspectRatio( float aspectRatio );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetStereoBias
+   */
+  void SetStereoBias(const Vector2& stereoBias);
+
+   /**
+   * @copydoc Dali::Internal::CameraAttachment::SetLeftClippingPlane
+   */
+  void SetLeftClippingPlane( float leftClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetRightClippingPlane
+   */
+  void SetRightClippingPlane( float rightClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetTopClippingPlane
+   */
+  void SetTopClippingPlane( float topClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetBottomClippingPlane
+   */
+  void SetBottomClippingPlane( float bottomClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetNearClippingPlane
+   */
+  void SetNearClippingPlane( float nearClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetFarClippingPlane
+   */
+  void SetFarClippingPlane( float farClippingPlane );
+
+  /**
+   * @copydoc Dali::Internal::CameraAttachment::SetTarget
+   */
+  void SetTargetPosition( const Vector3& targetPosition );
+
+  /**
+   * Get Camera Target
+   */
+  Vector3 GetTargetPosition() const;
+
+  /**
+   * Retrieve the view-matrix; this is double buffered for input handling.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The view-matrix.
+   */
+  const Matrix& GetViewMatrix( BufferIndex bufferIndex ) const;
+
+  /**
+   * @brief Check to see if a sphere lies within the view frustum.
+   *
+   * @param bufferIndex The buffer to read from.
+   * @param origin The world position center of the sphere to check.
+   * @param radius The length of the sphere radius in world scale.
+   *
+   * @return false if the sphere lies outside of the frustum.
+   */
+  bool CheckSphereInFrustum( BufferIndex bufferIndex, const Vector3& origin, float radius );
+
+  /**
+   * @brief Check to see if a bounding box lies within the view frustum.
+   *
+   * @param bufferIndex The buffer to read from.
+   * @param origin the world position center of the cubeoid to check.
+   * @param extents The half length of the cubeoid in world co-ordinates in each axis.
+   *
+   * @return false if the cubeoid lies outside of the frustum.
+   */
+  bool CheckAABBInFrustum( BufferIndex bufferIndex, const Vector3& origin, const Vector3& extents );
+
+  /**
+   * Retrieve the projection-matrix; this is double buffered for input handling.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The projection-matrix.
+   */
+  const Matrix& GetProjectionMatrix( BufferIndex bufferIndex ) const;
+
+  /**
+   * Retrieve the inverted view-projection-matrix; this is double buffered for input handling.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The inverse view-projection-matrix.
+   */
+  const Matrix& GetInverseViewProjectionMatrix( BufferIndex bufferIndex ) const;
+
+  /**
+   * Retrieve the projection-matrix property querying interface.
+   * @pre The attachment is on-stage.
+   * @return The projection-matrix property querying interface.
+   */
+  const PropertyInputImpl* GetProjectionMatrix() const;
+
+  /**
+   * Retrieve the view-matrix property querying interface.
+   * @pre The attachment is on-stage.
+   * @return The view-matrix property querying interface.
+   */
+  const PropertyInputImpl* GetViewMatrix() const;
+
+  /**
+   * @copydoc NodeAttachment::Update
+   */
+  virtual void Update( BufferIndex updateBufferIndex, const Node& owningNode, int nodeDirtyFlags );
+
+  /**
+   * @return true if the view matrix of camera is updated this or the previous frame
+   */
+  bool ViewMatrixUpdated();
+
+protected:
+
+  /**
+   * Protected constructor, see New().
+   */
+  CameraAttachment();
+
+private:
+
+  // Undefined
+  CameraAttachment(const CameraAttachment&);
+
+  // Undefined
+  CameraAttachment& operator=(const CameraAttachment& rhs);
+
+  /**
+   * Recalculates the view matrix.
+   * @param[in] bufferIndex The current update buffer index.
+   * @param[in] owningNode to use for calculations.
+   * @return count how many frames ago the matrix was changed.
+   */
+  unsigned int UpdateViewMatrix( BufferIndex updateBufferIndex, const Node& owningNode );
+
+  /**
+   * Recalculates the projection matrix.
+   * @param[in] bufferIndex The current update buffer index.
+   * @return count how many frames ago the matrix was changed.
+   */
+  unsigned int UpdateProjection( BufferIndex updateBufferIndex );
+
+private:
+
+  /**
+   * @brief Extracts the frustum planes.
+   *
+   * @param[in] bufferIndex The current update buffer index.
+   * @param[in] normalize will normalize plane equation coefficients by default.
+   */
+  void UpdateFrustum( BufferIndex updateBufferIndex, bool normalize = true );
+
+
+  unsigned int                  mUpdateViewFlag;       ///< This is non-zero if the view matrix requires an update
+  unsigned int                  mUpdateProjectionFlag; ///< This is non-zero if the projection matrix requires an update
+
+public:  // PROPERTIES
+  Dali::Camera::Type            mType;                 // Non-animatable
+  Dali::Camera::ProjectionMode  mProjectionMode;       // Non-animatable
+  bool                          mInvertYAxis;          // Non-animatable
+
+  float                         mFieldOfView;
+  float                         mAspectRatio;
+  float                         mLeftClippingPlane;
+  float                         mRightClippingPlane;
+  float                         mTopClippingPlane;
+  float                         mBottomClippingPlane;
+  float                         mNearClippingPlane;
+  float                         mFarClippingPlane;
+  Vector2                       mStereoBias;
+  Vector3                       mTargetPosition;
+
+  InheritedMatrix mViewMatrix;           ///< The view-matrix; this is double buffered for input handling.
+  InheritedMatrix mProjectionMatrix;     ///< The projection-matrix; this is double buffered for input handling.
+
+  DoubleBuffered< FrustumPlanes > mFrustum;               ///< Clipping frustum; double buffered for input handling
+  DoubleBuffered< Matrix >        mInverseViewProjection; ///< Inverted viewprojection; double buffered for input handling
+
+};
+
+// Messages for CameraAttachment
+
+inline void SetTypeMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, Dali::Camera::Type parameter )
+{
+  typedef MessageValue1< CameraAttachment, Dali::Camera::Type > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetType, parameter );
+}
+
+inline void SetProjectionModeMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, Dali::Camera::ProjectionMode parameter )
+{
+  typedef MessageValue1< CameraAttachment, Dali::Camera::ProjectionMode > LocalProjectionMode;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalProjectionMode ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalProjectionMode( &attachment, &CameraAttachment::SetProjectionMode, parameter );
+}
+
+
+inline void SetFieldOfViewMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetFieldOfView, parameter );
+}
+
+inline void SetAspectRatioMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetAspectRatio, parameter );
+}
+
+inline void SetStereoBiasMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, const Vector2& parameter )
+{
+  typedef MessageValue1< CameraAttachment, Vector2 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetStereoBias, parameter );
+}
+
+inline void SetLeftClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetLeftClippingPlane, parameter );
+}
+
+inline void SetRightClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetRightClippingPlane, parameter );
+}
+
+inline void SetTopClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetTopClippingPlane, parameter );
+}
+
+inline void SetBottomClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetBottomClippingPlane, parameter );
+}
+
+inline void SetNearClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetNearClippingPlane, parameter );
+}
+
+inline void SetFarClippingPlaneMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, float parameter )
+{
+  typedef MessageValue1< CameraAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetFarClippingPlane, parameter );
+}
+
+inline void SetTargetPositionMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, const Vector3& parameter )
+{
+  typedef MessageValue1< CameraAttachment, Vector3 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetTargetPosition, parameter );
+}
+
+
+inline void SetInvertYAxisMessage( EventThreadServices& eventThreadServices, const CameraAttachment& attachment, bool parameter )
+{
+  typedef MessageValue1< CameraAttachment, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &CameraAttachment::SetInvertYAxis, parameter );
+}
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_CAMERA_ATTACHMENT_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h b/dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h
new file mode 100644 (file)
index 0000000..ef950ed
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __DALI_SCENE_GRAPH_IMAGE_ATTACHMENT_DEBUG_H__
+#define __DALI_SCENE_GRAPH_IMAGE_ATTACHMENT_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");
+
+#define ATTACHMENT_LOG(level)                                                 \
+  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
+#define ATTACHMENT_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)
+
+#else
+
+#define ATTACHMENT_LOG(level)
+#define ATTACHMENT_LOG_FMT(level, format, args...)
+
+#endif
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_SCENE_GRAPH_IMAGE_ATTACHMENT_DEBUG_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-image-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-image-attachment.cpp
new file mode 100644 (file)
index 0000000..59cb27d
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/common/internal-constants.h>
+
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+#include <dali/internal/update/nodes/node.h>
+
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/vertex.h>
+#include <dali/internal/render/common/performance-monitor.h>
+#include <dali/internal/render/renderers/scene-graph-image-renderer.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-declarations.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+#include <dali/internal/update/node-attachments/scene-graph-image-attachment-debug.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< SceneGraph::ImageRenderer::MeshType >
+: public BasicType< SceneGraph::ImageRenderer::MeshType > {};
+
+namespace SceneGraph
+{
+
+ImageAttachment* ImageAttachment::New( unsigned int textureId )
+{
+  return new ImageAttachment( textureId );
+}
+
+ImageAttachment::ImageAttachment( unsigned int textureId )
+: RenderableAttachment( false ), // no scaling
+  mImageRenderer( NULL ),
+  mTextureId( textureId ),
+  mRefreshMeshData( true ),
+  mIsPixelAreaSet( false ),
+  mPreviousRefreshHints( 0 ),
+  mStyle( Dali::ImageActor::STYLE_QUAD ),
+  mCullFaceMode( CullNone )
+{
+}
+
+void ImageAttachment::Initialize2( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( NULL != mSceneController );
+
+  // Create main renderer, passing ownership to the render-thread
+  mImageRenderer = ImageRenderer::New( *mParent );
+
+  mSceneController->GetRenderMessageDispatcher().AddRenderer( *mImageRenderer );
+
+  ATTACHMENT_LOG_FMT(Debug::General, " renderer: %p\n", mImageRenderer);
+
+  if( mTextureId != 0 )
+  {
+    typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetTextureId, mTextureId );
+  }
+
+  // After derived classes have (potentially) created their renderer
+  Renderer& renderer = GetRenderer();
+  renderer.SetCullFace( mCullFaceMode );
+
+  // set the default shader here as well
+  renderer.SetShader( mShader );
+}
+
+void ImageAttachment::OnDestroy2()
+{
+  DALI_ASSERT_DEBUG( NULL != mSceneController );
+
+  // Request deletion in the next Render
+  mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mImageRenderer );
+  mImageRenderer = NULL;
+}
+
+void ImageAttachment::ConnectedToSceneGraph()
+{
+  // Do nothing
+}
+
+void ImageAttachment::DisconnectedFromSceneGraph()
+{
+  // Do nothing
+}
+
+ImageAttachment::~ImageAttachment()
+{
+}
+
+Renderer& ImageAttachment::GetRenderer()
+{
+  return *mImageRenderer;
+}
+
+const Renderer& ImageAttachment::GetRenderer() const
+{
+  return *mImageRenderer;
+}
+
+void ImageAttachment::SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId )
+{
+  DALI_ASSERT_DEBUG(mSceneController);
+  ATTACHMENT_LOG_FMT(Debug::General, " textureid: %d)\n", textureId);
+
+  mTextureId = textureId;
+
+  // Loading is essentially finished if we don't have a resource ID
+  mFinishedResourceAcquisition = ( 0 == mTextureId );
+
+  if( mImageRenderer )
+  {
+    typedef MessageValue1< ImageRenderer, ResourceId > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetTextureId, mTextureId );
+  }
+}
+
+void ImageAttachment::SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea )
+{
+  // update the pixel area information
+  mIsPixelAreaSet = true;
+
+  {
+    typedef MessageValue1< ImageRenderer, ImageRenderer::PixelArea > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetPixelArea, pixelArea );
+  }
+
+  // we rely on attachment to not call us unless it actually did change
+  mRefreshMeshData = true;
+}
+
+void ImageAttachment::ClearPixelArea()
+{
+  mIsPixelAreaSet = false;
+  mRefreshMeshData = true;
+}
+
+void ImageAttachment::SetStyle( Dali::ImageActor::Style style )
+{
+  if (mStyle != style)
+  {
+    mStyle = style;
+    mRefreshMeshData = true;
+  }
+}
+
+void ImageAttachment::SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels )
+{
+  // update the 9 patch border information
+
+  typedef MessageValue2< ImageRenderer, Vector4, bool > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( mImageRenderer, &ImageRenderer::SetNinePatchBorder, border, inPixels );
+
+  if (mStyle != Dali::ImageActor::STYLE_QUAD)
+  {
+    mRefreshMeshData = true;
+  }
+}
+
+void ImageAttachment::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
+{
+  // Blending options are forwarded to renderer in render-thread
+  typedef MessageValue1< Renderer, unsigned int > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendingOptions, options );
+}
+
+void ImageAttachment::SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color )
+{
+  // Blend color is forwarded to renderer in render-thread
+  typedef MessageValue1< Renderer, Vector4 > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &GetRenderer(), &Renderer::SetBlendColor, color );
+}
+
+void ImageAttachment::SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode )
+{
+  DALI_ASSERT_DEBUG(mSceneController);
+  DALI_ASSERT_DEBUG(mode >= CullNone && mode <= CullFrontAndBack);
+
+  mCullFaceMode = mode;
+
+  typedef MessageValue1< Renderer, CullFaceMode > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &GetRenderer(), &Renderer::SetCullFace, mode );
+}
+
+void ImageAttachment::SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield )
+{
+  DALI_ASSERT_DEBUG(mSceneController);
+
+  typedef MessageValue1< Renderer, unsigned int > DerivedType;
+
+  // Reserve some memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+  // Construct message in the render queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &GetRenderer(), &Renderer::SetSampler, samplerBitfield );
+}
+
+void ImageAttachment::ApplyShader( BufferIndex updateBufferIndex, Shader* shader )
+{
+  mShader = shader;
+
+  // send the message to renderer
+  SendShaderChangeMessage( updateBufferIndex );
+
+  // tell derived class to do something
+  ShaderChanged( updateBufferIndex );
+}
+
+void ImageAttachment::RemoveShader( BufferIndex updateBufferIndex )
+{
+  // return to default shader
+  mShader = NULL;
+
+  // send the message to renderer
+  SendShaderChangeMessage( updateBufferIndex );
+
+  // tell derived class to do something
+  ShaderChanged( updateBufferIndex );
+}
+
+
+void ImageAttachment::ShaderChanged( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( mSceneController );
+
+  int hints = 0; // default shader hints are 0
+  if( mShader )
+  {
+    hints = mShader->GetGeometryHints();
+  }
+  if ( hints != mPreviousRefreshHints )
+  {
+    mPreviousRefreshHints = hints;
+    // (may) need to change geometry
+    mRefreshMeshData = true;
+  }
+}
+
+void ImageAttachment::SizeChanged( BufferIndex updateBufferIndex )
+{
+  // avoid regenerating geometry if the size did not actually change (visibility change can accumulate a false SizeChanged)
+  const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
+  if( fabsf( actorSize.width  - mGeometrySize.width  ) > Math::MACHINE_EPSILON_1 ||
+      fabsf( actorSize.height - mGeometrySize.height ) > Math::MACHINE_EPSILON_1 )
+  {
+    mRefreshMeshData = true;
+  }
+}
+
+bool ImageAttachment::DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
+{
+  DALI_LOG_TRACE_METHOD_FMT(gImageAttachmentLogFilter, "this:%p", this);
+  bool ready = false;
+
+  if( 0 != mTextureId )
+  {
+    // The metadata is used by IsFullyOpaque(), below.
+    mBitmapMetadata = resourceManager.GetBitmapMetadata( mTextureId );
+
+    CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
+    CompleteStatusManager::CompleteState status = completeStatusManager.GetStatus( mTextureId );
+
+    switch( status )
+    {
+      case CompleteStatusManager::NOT_READY:
+      {
+        ready = false;
+
+        if( mBitmapMetadata.GetIsFramebuffer() )
+        {
+          ready = true;
+        }
+        mFinishedResourceAcquisition = false;
+        FollowTracker( mTextureId );
+      }
+      break;
+
+      case CompleteStatusManager::COMPLETE:
+      {
+        ready = true;
+        mFinishedResourceAcquisition = true;
+      }
+      break;
+
+      case CompleteStatusManager::NEVER:
+      {
+        ready = false;
+        mFinishedResourceAcquisition = true;
+      }
+      break;
+    }
+  }
+  else
+  {
+    // Loading is essentially finished if we don't have a resource ID
+    mFinishedResourceAcquisition = true;
+  }
+
+  ATTACHMENT_LOG_FMT(Debug::General, " ObjName:%s finished:%s ready:%s \n",
+                     DALI_LOG_GET_OBJECT_C_STR(mParent),
+                     mFinishedResourceAcquisition?"T":"F", ready?"T":"F");
+
+  return ready;
+}
+
+void ImageAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( mSceneController && mImageRenderer );
+
+  ATTACHMENT_LOG_FMT(Debug::General, "ObjName:%s textureId:%d\n",
+                     DALI_LOG_GET_OBJECT_C_STR(mParent),
+                     mTextureId);
+
+  // Check whether we need to refresh the vertex buffer.
+  if ( mRefreshMeshData )
+  {
+    const Vector3& actorSize = GetParent().GetSize( updateBufferIndex );
+    mGeometrySize.x = actorSize.x;
+    mGeometrySize.y = actorSize.y;
+
+    ImageRenderer::MeshType meshType = ImageRenderer::GRID_QUAD;
+
+    if ( !PreviousHintEnabled( Dali::ShaderEffect::HINT_GRID ) )
+    {
+      if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
+      {
+        meshType = ImageRenderer::NINE_PATCH;
+      }
+      else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
+      {
+        meshType = ImageRenderer::NINE_PATCH_NO_CENTER;
+      }
+      else
+      {
+        meshType = ImageRenderer::QUAD;
+      }
+    }
+    else
+    {
+      if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH )
+      {
+        meshType = ImageRenderer::GRID_NINE_PATCH;
+      }
+      else if ( mStyle == Dali::ImageActor::STYLE_NINE_PATCH_NO_CENTER )
+      {
+        meshType = ImageRenderer::GRID_NINE_PATCH_NO_CENTER;
+      }
+      else
+      {
+        meshType = ImageRenderer::GRID_QUAD;
+      }
+    }
+
+    // Recalculate the mesh data in the next render
+    {
+      typedef MessageValue3< ImageRenderer, ImageRenderer::MeshType, Vector2, bool > DerivedType;
+
+      // Reserve some memory inside the render queue
+      unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+      // Construct message in the render queue memory; note that delete should not be called on the return value
+      new (slot) DerivedType( mImageRenderer, &ImageRenderer::CalculateMeshData, meshType, mGeometrySize, mIsPixelAreaSet );
+    }
+
+    mRefreshMeshData = false;
+  }
+}
+
+void RenderableAttachment::SetBlendingMode( BlendingMode::Type mode )
+{
+  mBlendingMode = mode;
+}
+
+BlendingMode::Type RenderableAttachment::GetBlendingMode() const
+{
+  return mBlendingMode;
+}
+
+bool ImageAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
+{
+  bool fullyOpaque = true;
+
+  switch( mBlendingMode )
+  {
+    case BlendingMode::OFF:
+    {
+      fullyOpaque = true;
+      break;
+    }
+    case BlendingMode::ON:
+    {
+      // Blending always.
+      fullyOpaque = false;
+      break;
+    }
+    case BlendingMode::AUTO:
+    {
+      /**
+       * Fully opaque when...
+       *   1) not using the alpha channel from the image data
+       *   2) the inherited color is not transparent nor semi-transparent
+       *   3) the shader doesn't require blending
+       */
+      fullyOpaque = mBitmapMetadata.IsFullyOpaque();
+
+      if ( fullyOpaque && mParent )
+      {
+        fullyOpaque = ( mParent->GetWorldColor(updateBufferIndex).a >= FULLY_OPAQUE );
+
+        if ( fullyOpaque && mShader != NULL )
+        {
+          fullyOpaque = !PreviousHintEnabled( Dali::ShaderEffect::HINT_BLENDING );
+        }
+      }
+    }
+  }
+  return fullyOpaque;
+}
+
+void ImageAttachment::SendShaderChangeMessage( BufferIndex updateBufferIndex )
+{
+  typedef MessageValue1< Renderer, Shader* > DerivedType;
+  // Reserve memory inside the render queue
+  unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+  // Construct message in the mRenderer queue memory; note that delete should not be called on the return value
+  new (slot) DerivedType( &GetRenderer(), &Renderer::SetShader, mShader );
+}
+
+
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/node-attachments/scene-graph-image-attachment.h b/dali/internal/update/node-attachments/scene-graph-image-attachment.h
new file mode 100644 (file)
index 0000000..1523d10
--- /dev/null
@@ -0,0 +1,403 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_IMAGE_ATTACHMENT_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_IMAGE_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/update/resources/bitmap-metadata.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< Dali::ImageActor::Style >
+: public BasicType< Dali::ImageActor::Style > {};
+
+namespace SceneGraph
+{
+class ImageRenderer;
+class Shader;
+class RenderQueue;
+
+/**
+ * An attachment for rendering images in various ways.
+ */
+class ImageAttachment : public RenderableAttachment
+{
+public:
+
+  typedef Dali::ImageActor::Style     Style;
+  typedef Dali::ImageActor::PixelArea PixelArea;
+
+  /**
+   * Create a new ImageAttachment.
+   * @param [in] textureId The resource ID of a texture.
+   * @return The newly allocated ImageAttachment.
+   */
+  static ImageAttachment* New( unsigned int textureId );
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~ImageAttachment();
+
+  /**
+   * @copydoc RenderableAttachment::GetRenderer().
+   */
+  virtual Renderer& GetRenderer();
+
+  /**
+   * @copydoc RenderableAttachment::GetRenderer().
+   */
+  virtual const Renderer& GetRenderer() const;
+
+  /**
+   * Set the ID used to retrieve a texture from ResourceManager.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] textureId The texture ID.
+   */
+  void SetTextureId( BufferIndex updateBufferIndex, unsigned int textureId );
+
+  /**
+   * Set the area of the texture to display.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param [in] pixelArea The area to display, in pixels relative to the top-left (0,0) of the image.
+   */
+  void SetPixelArea( BufferIndex updateBufferIndex, const PixelArea& pixelArea );
+
+  /**
+   * Query whether a pixel area has been set.
+   * @return True if a pixel area has been set.
+   */
+  bool IsPixelAreaSet() const
+  {
+    return mIsPixelAreaSet;
+  }
+
+  /**
+   * Remove any pixel areas specified with SetPixelArea; the entire image will be displayed.
+   * @pre image must be initialized.
+   */
+  void ClearPixelArea();
+
+  /**
+   * Set how the attachment is rendered; the default is STYLE_QUAD.
+   * @param [in] style The new style.
+   */
+  void SetStyle( Style style );
+
+  /**
+   * Retrieve how the attachment is rendered.
+   * @return The style.
+   */
+  Style GetStyle()
+  {
+    return mStyle;
+  }
+
+  /**
+   * Set the border; this is applied with STYLE_NINE_PATCH.
+   * @param [in] updateBufferIndex to use.
+   * @param [in] border The new border setting.
+   * @param [in] inPixels if the border is in pixels.
+   */
+  void SetBorder( BufferIndex updateBufferIndex, const Vector4& border, bool inPixels );
+
+  /**
+   * Set the blending options. This should only be called from the update-thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] options A bitmask of blending options.
+   */
+  void SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options );
+
+  /**
+   * Set the blend-color. This should only be called from the update-thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] color The new blend-color.
+   */
+  void SetBlendColor( BufferIndex updateBufferIndex, const Vector4& color );
+
+  /**
+   * Set the face-culling mode.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] mode The face-culling mode.
+   */
+  void SetCullFace( BufferIndex updateBufferIndex, CullFaceMode mode );
+
+  /**
+   * Set the sampler used to render the texture for this renderable.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] samplerBitfield The image sampler packed options to set.
+   */
+  void SetSampler( BufferIndex updateBufferIndex, unsigned int samplerBitfield );
+
+  /**
+   * Apply a shader on the renderable
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] shader to apply.
+   */
+  void ApplyShader( BufferIndex updateBufferIndex, Shader* shader );
+
+  /**
+   * Remove the shader from the renderable
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void RemoveShader( BufferIndex updateBufferIndex );
+
+  /**
+   * Called to notify that the shader might have been changed
+   * The implementation should recalculate geometry and scale based on the
+   * hints from the new shader
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return Return true if the geometry changed.
+   */
+  virtual void ShaderChanged( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::SizeChanged()
+   */
+  virtual void SizeChanged( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::DoPrepareRender()
+   */
+  virtual void DoPrepareRender( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::IsFullyOpaque()
+   */
+  virtual bool IsFullyOpaque( BufferIndex updateBufferIndex );
+
+protected:
+
+  /**
+   * Protected constructor
+   */
+  ImageAttachment( unsigned int textureId );
+
+private:
+  /**
+   * Sends the shader to the renderer
+   * @param updateBufferIndex for the message buffer
+   */
+  void SendShaderChangeMessage( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::Initialize2().
+   */
+  virtual void Initialize2( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::OnDestroy2().
+   */
+  virtual void OnDestroy2();
+
+  /**
+   * @copydoc NodeAttachment::ConnectedToSceneGraph()
+   */
+  virtual void ConnectedToSceneGraph();
+
+  /**
+   * @copydoc NodeAttachment::DisconnectedFromSceneGraph()
+   */
+  virtual void DisconnectedFromSceneGraph();
+
+  /**
+   * @copydoc RenderableAttachment::DoPrepareResources()
+   */
+  virtual bool DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager );
+
+  // Helper to check whether a geometry hint was set
+  bool PreviousHintEnabled( Dali::ShaderEffect::GeometryHints hint ) const
+  {
+    return mPreviousRefreshHints & hint;
+  }
+
+  // Undefined
+  ImageAttachment(const ImageAttachment&);
+
+  // Undefined
+  ImageAttachment& operator=(const ImageAttachment& rhs);
+
+private: // Data
+
+  ImageRenderer* mImageRenderer; ///< Raw-pointers to renderer that is owned by RenderManager
+  unsigned int mTextureId;        ///< The resource ID for a texture
+
+  // bitfields to fit in single byte
+  bool mRefreshMeshData      : 1; ///< Whether the vertex/index buffers needs regenerating
+  bool mIsPixelAreaSet       : 1; ///< Whether pixel area is set, cached for image actor to be able to ask for it
+  int  mPreviousRefreshHints : 4; ///< The shader geometry hints, when the vertex buffer was last refreshed, 4 bits is enough as there's 4 flags
+  Style mStyle               : 2; ///< rendering style, 2 bits is enough as only 2 values in the enum
+  CullFaceMode mCullFaceMode : 3; ///< Cullface mode, 3 bits is enough for 4 values
+
+  BitmapMetadata  mBitmapMetadata;///< The bitmap metadata
+  Vector2 mGeometrySize;          ///< The size of the currently used geometry
+
+};
+
+// Messages for ImageAttachment
+
+inline void SetTextureIdMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, unsigned int id )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetTextureId, id );
+}
+
+inline void SetPixelAreaMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, const Dali::ImageActor::PixelArea& area )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, Dali::ImageActor::PixelArea > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetPixelArea, area );
+}
+
+inline void ClearPixelAreaMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment )
+{
+  typedef Message< ImageAttachment > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::ClearPixelArea );
+}
+
+inline void SetStyleMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, Dali::ImageActor::Style style )
+{
+  typedef MessageValue1< ImageAttachment, Dali::ImageActor::Style > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetStyle, style );
+}
+
+inline void SetNinePatchBorderMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, const Vector4& border, bool inPixels )
+{
+  typedef MessageDoubleBuffered2< ImageAttachment, Vector4, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetBorder, border, inPixels );
+}
+
+inline void SetSortModifierMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, float modifier )
+{
+  typedef MessageValue1< ImageAttachment, float > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetSortModifier, modifier );
+}
+
+inline void SetCullFaceMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, CullFaceMode mode )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, CullFaceMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetCullFace, mode );
+}
+
+inline void SetBlendingOptionsMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, unsigned int options )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  new (slot) LocalType( &attachment, &ImageAttachment::SetBlendingOptions, options );
+}
+
+inline void SetBlendColorMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, const Vector4& color )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, Vector4 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  new (slot) LocalType( &attachment, &ImageAttachment::SetBlendColor, color );
+}
+
+inline void SetSamplerMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, unsigned int samplerBitfield )
+{
+  typedef MessageDoubleBuffered1< ImageAttachment, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::SetSampler, samplerBitfield );
+}
+
+inline void ApplyShaderMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment, const Shader& constShader )
+{
+  // Update thread can edit the object
+  Shader& shader = const_cast< Shader& >( constShader );
+
+  typedef MessageDoubleBuffered1< ImageAttachment, Shader* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::ApplyShader, &shader );
+}
+
+inline void RemoveShaderMessage( EventThreadServices& eventThreadServices, const ImageAttachment& attachment )
+{
+  typedef MessageDoubleBuffered0< ImageAttachment > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &ImageAttachment::RemoveShader );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_IMAGE_ATTACHMENT_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-renderable-attachment-declarations.h b/dali/internal/update/node-attachments/scene-graph-renderable-attachment-declarations.h
new file mode 100644 (file)
index 0000000..0da47fa
--- /dev/null
@@ -0,0 +1,44 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_DECLARATIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class RenderableAttachment;
+
+typedef std::vector<RenderableAttachment*>      RenderableAttachmentContainer;
+typedef RenderableAttachmentContainer::iterator RenderableAttachmentIter;
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-renderable-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-renderable-attachment.cpp
new file mode 100644 (file)
index 0000000..a27e960
--- /dev/null
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/internal/update/manager/prepare-render-instructions.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+#include <dali/internal/update/resources/resource-tracker.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/scene-graph-renderer.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+#include <dali/internal/common/image-sampler.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderableAttachment::RenderableAttachment( bool usesGeometryScaling )
+: mSceneController(NULL), //@todo MESH_REWORK Pass in where required rather than store
+  mShader( NULL ),
+  mTrackedResources(),
+  mSortModifier( 0.0f ),
+  mBlendingMode( Dali::ImageActor::DEFAULT_BLENDING_MODE ),
+  mUsesGeometryScaling( usesGeometryScaling ),
+  mScaleForSizeDirty( true ),
+  mUseBlend( false ),
+  mHasSizeAndColorFlag( false ),
+  mResourcesReady( false ),
+  mFinishedResourceAcquisition( false ),
+  mHasUntrackedResources( false )
+{
+}
+
+RenderableAttachment::~RenderableAttachment()
+{
+}
+
+void RenderableAttachment::Initialize( SceneController& sceneController, BufferIndex updateBufferIndex )
+{
+  mSceneController = &sceneController;
+
+  // Chain to derived attachments
+  Initialize2( updateBufferIndex );
+}
+
+void RenderableAttachment::OnDestroy()
+{
+  // Chain to derived attachments
+  OnDestroy2();
+
+  // SceneController is no longer valid
+  mSceneController = NULL;
+}
+
+void RenderableAttachment::SetRecalculateScaleForSize()
+{
+  mScaleForSizeDirty = true;
+}
+
+void RenderableAttachment::GetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
+{
+  DoGetScaleForSize( nodeSize, scaling );
+  mScaleForSizeDirty = false;
+}
+
+bool RenderableAttachment::ResolveVisibility( BufferIndex updateBufferIndex )
+{
+  mHasSizeAndColorFlag = false;
+  const Vector4& color = mParent->GetWorldColor( updateBufferIndex );
+  if( color.a > FULLY_TRANSPARENT )               // not fully transparent
+  {
+    const float MAX_NODE_SIZE = float(1u<<30);
+    const Vector3& size = mParent->GetSize( updateBufferIndex );
+    if( ( size.width > Math::MACHINE_EPSILON_1000 ) &&  // width is greater than a very small number
+        ( size.height > Math::MACHINE_EPSILON_1000 ) )  // height is greater than a very small number
+    {
+      if( ( size.width < MAX_NODE_SIZE ) &&             // width is smaller than the maximum allowed size
+          ( size.height < MAX_NODE_SIZE ) )             // height is smaller than the maximum allowed size
+      {
+        mHasSizeAndColorFlag = true;
+      }
+      else
+      {
+        DALI_LOG_ERROR("Actor size should not be bigger than %f.\n", MAX_NODE_SIZE );
+        DALI_LOG_ACTOR_TREE( mParent );
+      }
+    }
+  }
+  return mHasSizeAndColorFlag;
+}
+
+void RenderableAttachment::DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling )
+{
+  scaling = Vector3::ONE;
+}
+
+void RenderableAttachment::PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager )
+{
+  mHasUntrackedResources = false; // Only need to know this if the resources are not yet complete
+  mTrackedResources.Clear(); // Resource trackers are only needed if not yet completea
+
+  if( mShader )
+  {
+    Integration::ResourceId id = mShader->GetEffectTextureResourceId();
+
+    if( id != 0 )
+    {
+      CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
+
+      if(CompleteStatusManager::COMPLETE != completeStatusManager.GetStatus( id ))
+      {
+        FollowTracker(id);
+        mFinishedResourceAcquisition = false;
+        mResourcesReady = false;
+
+        // If shader has effect texture and it's not complete and tracked, ensure
+        // we call DoPrepareResources, as the effect texture may become ready in
+        // the ProcessRenderTasks step.  Otherwise, may early out.
+        if( mHasUntrackedResources )
+        {
+          return;
+        }
+      }
+    }
+  }
+
+  mResourcesReady = DoPrepareResources( updateBufferIndex, resourceManager );
+}
+
+void RenderableAttachment::FollowTracker( Integration::ResourceId id )
+{
+  CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
+
+  if( completeStatusManager.FindResourceTracker(id) != NULL )
+  {
+    bool found = false;
+    std::size_t numTrackedResources = mTrackedResources.Count();
+    for( size_t i=0; i < numTrackedResources; ++i )
+    {
+      if(mTrackedResources[i] == id)
+      {
+        found = true;
+        break;
+      }
+    }
+    if( ! found )
+    {
+      mTrackedResources.PushBack( id );
+    }
+  }
+  else
+  {
+    mHasUntrackedResources = true;
+  }
+}
+
+
+void RenderableAttachment::GetReadyAndComplete(bool& ready, bool& complete) const
+{
+  ready = mResourcesReady;
+  complete = false;
+
+  CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
+
+  std::size_t numTrackedResources = mTrackedResources.Count();
+  if( mHasUntrackedResources || numTrackedResources == 0 )
+  {
+    complete = mFinishedResourceAcquisition;
+  }
+  else
+  {
+    // If there are tracked resources and no untracked resources, test the trackers
+    bool trackersComplete = true;
+    for( size_t i=0; i < numTrackedResources; ++i )
+    {
+      ResourceId id = mTrackedResources[i];
+      ResourceTracker* tracker = completeStatusManager.FindResourceTracker(id);
+      if( tracker  && ! tracker->IsComplete() )
+      {
+        trackersComplete = false;
+        break;
+      }
+    }
+
+    complete = mFinishedResourceAcquisition || trackersComplete;
+  }
+}
+
+void RenderableAttachment::PrepareRender( BufferIndex updateBufferIndex )
+{
+  // call the derived class first as it might change its state regarding blending
+  DoPrepareRender( updateBufferIndex );
+
+  // @todo MESH_REWORK Remove remainder of method after removing ImageAttachment
+
+  bool blend = !IsFullyOpaque( updateBufferIndex );
+
+  if ( mUseBlend != blend )
+  {
+    mUseBlend = blend;
+
+    // Enable/disable blending in the next render
+    typedef MessageValue1< Renderer, bool > DerivedType;
+
+    // Reserve some memory inside the render queue
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+    // Construct message in the render queue memory; note that delete should not be called on the return value
+    new (slot) DerivedType( &GetRenderer(), &Renderer::SetUseBlend, blend );
+  }
+}
+
+RenderableAttachment* RenderableAttachment::GetRenderable()
+{
+  return this;
+}
+
+void RenderableAttachment::SetSortModifier(float modifier)
+{
+  // Setting sort modifier makes the node dirty, i.e. we cannot reuse previous frames render items
+  if( mParent )
+  {
+    // only do this if we are on-stage
+    mParent->SetDirtyFlag( SortModifierFlag );
+  }
+  mSortModifier = modifier;
+}
+
+void RenderableAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
+{
+  sortAttributes.shader = mShader;
+  sortAttributes.material = NULL;
+  sortAttributes.geometry = NULL;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/node-attachments/scene-graph-renderable-attachment.h b/dali/internal/update/node-attachments/scene-graph-renderable-attachment.h
new file mode 100644 (file)
index 0000000..0f01208
--- /dev/null
@@ -0,0 +1,311 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/blending-options.h>
+#include <dali/internal/common/internal-constants.h>
+#include <dali/internal/common/type-abstraction-enums.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/render/renderers/scene-graph-renderer-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class ResourceManager;
+class ResourceTracker;
+
+namespace SceneGraph
+{
+class Renderer;
+class Shader;
+class SortAttributes;
+struct RendererWithSortAttributes;
+
+/**
+ * RenderableAttachments are responsible for preparing textures, meshes, matrices etc. during the Update.
+ * These resources are then passed to a renderer, for use in the next Render.
+ */
+class RenderableAttachment : public NodeAttachment
+{
+protected:
+  /**
+   * Protected constructor; only derived classes can be instantiated.
+   * @param usesGeometryScaling should be false if the derived class does not need geometry scaling
+   */
+  RenderableAttachment( bool usesGeometryScaling );
+
+  /**
+   * Virtual destructor, no deletion through this interface
+   */
+  virtual ~RenderableAttachment();
+
+private: // From NodeAttachment
+
+  /**
+   * @copydoc NodeAttachment::Initialize().
+   */
+  virtual void Initialize( SceneController& sceneController, BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc NodeAttachment::OnDestroy().
+   */
+  virtual void OnDestroy();
+
+  /**
+   * @copydoc NodeAttachment::GetRenderable()
+   */
+  virtual RenderableAttachment* GetRenderable();
+
+public: // Connection API for derived classes
+  /**
+   * Chained from RenderableAttachment::Initialize()
+   */
+  virtual void Initialize2( BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Chained from RenderableAttachment::OnDestroy()
+   */
+  virtual void OnDestroy2() = 0;
+
+
+public: // API
+
+  /**
+   * @See Dali::RenderableActor::SetBlendMode().
+   */
+  void SetBlendingMode( BlendingMode::Type mode );
+
+  /**
+   * @copydoc Dali::RenderableActor::GetBlendMode().
+   */
+  BlendingMode::Type GetBlendingMode() const;
+
+  /**
+   * Flag to check if any geometry scaling is needed, inlined as called from update algorithm often
+   * @return true if the derived renderable uses geometry scaling
+   */
+  bool UsesGeometryScaling() const
+  {
+    return mUsesGeometryScaling;
+  }
+
+  /**
+   * Triggers scale for size update. GetScaleForSize will be called in this frame
+   */
+  void SetRecalculateScaleForSize();
+
+  /**
+   * Returns the scaling dirty flag, inlined as called from update algorithm often
+   * @return if scale for size is dirty, i.e. scaling has changed
+   */
+  bool IsScaleForSizeDirty() const
+  {
+    return mScaleForSizeDirty;
+  }
+
+  /**
+   * Retrieve scale-for-size for given node size
+   * Clears the scale for size flag
+   * @param[in] nodeSize to scale to
+   * @param[out] scaling factors
+   */
+  void GetScaleForSize( const Vector3& nodeSize, Vector3& scaling );
+
+
+public: // For use during in the update algorithm only
+
+  /**
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return visible tells if this renderer can be potentially seen
+   */
+  bool ResolveVisibility( BufferIndex updateBufferIndex );
+
+  /**
+   * if this renderable actor has visible size and color
+   * @return true if you can potentially see this actor
+   */
+  bool HasVisibleSizeAndColor() const
+  {
+    return mHasSizeAndColorFlag;
+  }
+
+  /**
+   * Prepare the object resources.
+   * This must be called by the UpdateManager before calling PrepareRender, for each frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] resourceManager The resource manager.
+   */
+  void PrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager );
+
+  /**
+   * If the resource is being tracked, then follow it. ( Further ready tests will use this
+   * list ) Otherwise, if it's not complete, set mHasUntrackedResources.
+   * @param[in] The resource id
+   */
+  void FollowTracker( Integration::ResourceId id );
+
+  /**
+   * Check whether the attachment has been marked as ready to render
+   * @param[out] ready TRUE if the attachment has resources to render
+   * @param[out] complete TRUE if the attachment's resources are complete
+   * (e.g. image has finished loading, framebuffer is ready to render, native image
+   * framebuffer has been rendered)
+   */
+  void GetReadyAndComplete(bool& ready, bool& complete) const;
+
+  /**
+   * Prepare the object for rendering.
+   * This is called by the UpdateManager when an object is due to be rendered in the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void PrepareRender( BufferIndex updateBufferIndex );
+
+public: // API for derived classes
+
+  /**
+   * Retrieve a Renderer used by this attachment; implemented in derived classes.
+   * @note The first Renderer is the main renderer for the attachment, and
+   * should always exist during the lifetime of the RenderableAttachment.
+   * @return A Renderer.
+   */
+  virtual Renderer& GetRenderer() = 0;
+
+  /**
+   * Retrieve a Renderer used by this attachment.
+   * @note The first Renderer is the main renderer for the attachment, and
+   * should always exist during the lifetime of the RenderableAttachment.
+   * Other renderers are for effects such as shadows and reflections.
+   * @return A Renderer.
+   */
+  virtual const Renderer& GetRenderer() const = 0;
+
+  /**
+   * Prepare the object resources.
+   * This must be called by the UpdateManager before calling PrepareRender, for each frame.
+   * @param[in] updateBufferIndex The current buffer index.
+   * @param[in] resourceManager The resource manager.
+   * @return True if resources are ready, false will prevent PrepareRender being called for this attachment.
+   */
+  virtual bool DoPrepareResources( BufferIndex updateBufferIndex, ResourceManager& resourceManager ) = 0;
+
+  /**
+   * @copydoc RenderableAttachment::PrepareRender()
+   */
+  virtual void DoPrepareRender( BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Query whether the attachment is fully opaque.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return True if fully opaque.
+   */
+  virtual bool IsFullyOpaque( BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Called to notify that the size has been changed
+   * The implementation may tell the renderer to recalculate scale
+   * based on the new size
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  virtual void SizeChanged( BufferIndex updateBufferIndex ) = 0;
+
+  /**
+   * Retrieve the scale-for-size for given node size. Default implementation returns Vector3::ZERO
+   * @param[in] nodeSize to scale to
+   * @param[out] scaling factors
+   */
+  virtual void DoGetScaleForSize( const Vector3& nodeSize, Vector3& scaling );
+
+  /**
+   * Set the sort-modifier for the attachment.
+   * @param[in] modifier The depth-sort modifier.
+   */
+  void SetSortModifier(float modifier);
+
+  /**
+   * Get the depth index for the attachment
+   * @param[in] bufferIndex The current update buffer index.
+   */
+  virtual int GetDepthIndex()
+  {
+    return static_cast<int>( mSortModifier );
+  }
+
+  /**
+   * Write the attachment's sort attributes to the passed in reference
+   * @todo MESH_REWORK Consider removing this after merge with scene-graph-renderer-attachment,
+   * and allowing PrepareRenderInstruction to read directly from this object
+   *
+   * @param[in] bufferIndex The current update buffer index.
+   * @param[out] sortAttributes
+   */
+  virtual void SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes );
+
+private:
+
+  // Undefined
+  RenderableAttachment( const RenderableAttachment& );
+
+  // Undefined
+  RenderableAttachment& operator=( const RenderableAttachment& rhs );
+
+protected:
+  SceneController* mSceneController;   ///< Used for initializing renderers whilst attached
+  Shader*          mShader;            ///< A pointer to the shader
+
+  Dali::Vector< Integration::ResourceId > mTrackedResources; ///< Filled during PrepareResources if there are uncomplete, tracked resources.
+
+  float mSortModifier;
+
+  BlendingMode::Type mBlendingMode:2;  ///< Whether blending is used to render the renderable attachment. 2 bits is enough for 3 values
+
+  bool mUsesGeometryScaling:1;         ///< True if the derived renderer uses scaling.
+  bool mScaleForSizeDirty:1;           ///< True if mScaleForSize has changed in the current frame.
+  bool mUseBlend:1;                    ///< True if the attachment & renderer should be considered opaque for sorting and blending.
+  bool mHasSizeAndColorFlag:1;         ///< Set during the update algorithm to tell whether this renderer can potentially be seen
+  bool mResourcesReady:1;              ///< Set during the Update algorithm; true if the attachment has resources ready for the current frame.
+  bool mFinishedResourceAcquisition:1; ///< Set during DoPrepareResources; true if ready & all resource acquisition has finished (successfully or otherwise)
+  bool mHasUntrackedResources:1;       ///< Set during PrepareResources, true if have tried to follow untracked resources
+};
+
+// Messages for RenderableAttachment
+
+inline void SetBlendingModeMessage( EventThreadServices& eventThreadServices, const RenderableAttachment& attachment, BlendingMode::Type mode )
+{
+  typedef MessageValue1< RenderableAttachment, BlendingMode::Type > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  new (slot) LocalType( &attachment, &RenderableAttachment::SetBlendingMode, mode );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDERABLE_ATTACHMENT_H__
diff --git a/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp b/dali/internal/update/node-attachments/scene-graph-renderer-attachment.cpp
new file mode 100644 (file)
index 0000000..eac06ef
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "scene-graph-renderer-attachment.h"
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/update/manager/prepare-render-instructions.h>
+#include <dali/internal/update/rendering/scene-graph-geometry.h>
+#include <dali/internal/update/rendering/scene-graph-material.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/renderers/render-renderer.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gImageAttachmentLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_IMAGE_ATTACHMENT");
+
+#define ATTACHMENT_LOG(level)                                                 \
+  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p\n", __FUNCTION__, this)
+#define ATTACHMENT_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gImageAttachmentLogFilter, level, "SceneGraph::ImageAttachment::%s: this:%p " format, __FUNCTION__, this, ## args)
+
+#else
+
+#define ATTACHMENT_LOG(level)
+#define ATTACHMENT_LOG_FMT(level, format, args...)
+
+#endif
+
+
+namespace // unnamed namespace
+{
+const int REGENERATE_UNIFORM_MAP = 2;
+const int COPY_UNIFORM_MAP       = 1;
+}
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+RendererAttachment* RendererAttachment::New()
+{
+  return new RendererAttachment();
+}
+
+
+RendererAttachment::RendererAttachment()
+: RenderableAttachment( false ),
+  mRenderer(NULL),
+  mMaterial(NULL),
+  mGeometry(NULL),
+  mRegenerateUniformMap(REGENERATE_UNIFORM_MAP),
+  mResendDataProviders(false),
+  mResendGeometry(false),
+  mDepthIndex(0)
+{
+  mUniformMapChanged[0]=false;
+  mUniformMapChanged[1]=false;
+
+  // Observe our own PropertyOwner's uniform map
+  AddUniformMapObserver( *this );
+}
+
+
+RendererAttachment::~RendererAttachment()
+{
+  if (mMaterial)
+  {
+    mMaterial->RemoveConnectionObserver(*this);
+    mMaterial=NULL;
+  }
+  if (mGeometry)
+  {
+    mGeometry->RemoveConnectionObserver(*this);
+    mGeometry=NULL;
+  }
+}
+
+void RendererAttachment::Initialize2( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( mSceneController );
+}
+
+void RendererAttachment::OnDestroy2()
+{
+}
+
+void RendererAttachment::ConnectedToSceneGraph()
+{
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+  mParent->AddUniformMapObserver( *this ); // Watch actor's uniform maps
+
+  DALI_ASSERT_DEBUG( mParent != NULL );
+
+  RenderDataProvider* dataProvider = NewRenderDataProvider();
+
+  RenderGeometry* renderGeometry = mGeometry->GetRenderGeometry(mSceneController);
+  mRenderer = NewRenderer::New( *mParent, dataProvider, renderGeometry );
+  mSceneController->GetRenderMessageDispatcher().AddRenderer( *mRenderer );
+}
+
+void RendererAttachment::DisconnectedFromSceneGraph()
+{
+  mRegenerateUniformMap = 0;
+  mParent->RemoveUniformMapObserver( *this );
+
+  mGeometry->OnRendererDisconnect();
+
+  DALI_ASSERT_DEBUG( mSceneController );
+  mSceneController->GetRenderMessageDispatcher().RemoveRenderer( *mRenderer );
+  mRenderer = NULL;
+}
+
+void RendererAttachment::SetMaterial( BufferIndex updateBufferIndex, Material* material)
+{
+  DALI_ASSERT_DEBUG( material != NULL && "Material pointer is NULL" );
+
+  mMaterial = material;
+  mMaterial->AddConnectionObserver( *this );
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+
+  mResendDataProviders = true;
+}
+
+Material& RendererAttachment::GetMaterial()
+{
+  return *mMaterial;
+}
+
+void RendererAttachment::SetGeometry( BufferIndex updateBufferIndex, Geometry* geometry)
+{
+  DALI_ASSERT_DEBUG( geometry != NULL && "Geometry pointer is NULL");
+  if( mGeometry)
+  {
+    mGeometry->RemoveConnectionObserver(*this);
+    mGeometry->OnRendererDisconnect();
+  }
+
+  mGeometry = geometry;
+  mGeometry->AddConnectionObserver( *this ); // Observe geometry connections / uniform mapping changes
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+
+  if( mRenderer )
+  {
+    mResendGeometry = true;
+  }
+}
+
+Geometry& RendererAttachment::GetGeometry()
+{
+  return *mGeometry;
+}
+
+void RendererAttachment::SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes )
+{
+  sortAttributes.shader = mMaterial->GetShader();
+  sortAttributes.material = mMaterial;
+  sortAttributes.geometry = mGeometry;
+}
+
+void RendererAttachment::SetDepthIndex( int depthIndex )
+{
+  mDepthIndex = depthIndex;
+
+  if( mParent )
+  {
+    // only do this if we are on-stage. Ensures the render lists are re-sorted
+    mParent->SetDirtyFlag( SortModifierFlag );
+  }
+}
+
+Renderer& RendererAttachment::GetRenderer()
+{
+  return *mRenderer;
+}
+
+const Renderer& RendererAttachment::GetRenderer() const
+{
+  return *mRenderer;
+}
+
+// Called by ProcessRenderTasks after DoPrepareRender
+bool RendererAttachment::IsFullyOpaque( BufferIndex updateBufferIndex )
+{
+  bool opaque = false;
+
+  if( mMaterial != NULL )
+  {
+    Material::BlendPolicy blendPolicy = mMaterial->GetBlendPolicy();
+    switch( blendPolicy )
+    {
+      case Material::OPAQUE:
+      {
+        opaque = true;
+        break;
+      }
+      case Material::TRANSPARENT:
+      {
+        opaque = false;
+        break;
+      }
+      case Material::USE_ACTOR_COLOR:
+      {
+        if( mParent )
+        {
+          opaque = mParent->GetWorldColor( updateBufferIndex ).a >= FULLY_OPAQUE;
+        }
+        break;
+      }
+    }
+  }
+
+  return opaque;
+}
+
+void RendererAttachment::SizeChanged( BufferIndex updateBufferIndex )
+{
+  // Do nothing.
+}
+
+bool RendererAttachment::DoPrepareResources(
+  BufferIndex updateBufferIndex,
+  ResourceManager& resourceManager )
+{
+  DALI_ASSERT_DEBUG( mSceneController );
+
+  CompleteStatusManager& completeStatusManager = mSceneController->GetCompleteStatusManager();
+  bool ready = false;
+  mFinishedResourceAcquisition = false;
+
+  // Can only be considered ready when all the scene graph objects are connected to the renderer
+  if( ( mGeometry ) &&
+      ( mGeometry->GetVertexBuffers().Count() > 0 ) &&
+      ( mMaterial ) &&
+      ( mMaterial->GetShader() != NULL ) )
+  {
+    unsigned int completeCount = 0;
+    unsigned int neverCount = 0;
+    unsigned int frameBufferCount = 0;
+
+    Vector<Sampler*>& samplers = mMaterial->GetSamplers();
+    for( Vector<Sampler*>::ConstIterator iter = samplers.Begin();
+         iter != samplers.End(); ++iter )
+    {
+      Sampler* sampler = *iter;
+
+      ResourceId textureId = sampler->GetTextureId( updateBufferIndex );
+      BitmapMetadata metaData = resourceManager.GetBitmapMetadata( textureId );
+
+      sampler->SetFullyOpaque( metaData.IsFullyOpaque() );
+
+      switch( completeStatusManager.GetStatus( textureId ) )
+      {
+        case CompleteStatusManager::NOT_READY:
+        {
+          if( metaData.GetIsFramebuffer() )
+          {
+            frameBufferCount++;
+          }
+          FollowTracker( textureId ); // @todo MESH_REWORK Trackers per sampler rather than per actor?
+        }
+        break;
+
+        case CompleteStatusManager::COMPLETE:
+        {
+          completeCount++;
+        }
+        break;
+
+        case CompleteStatusManager::NEVER:
+        {
+          neverCount++;
+        }
+        break;
+      }
+    }
+
+    // We are ready if all samplers are complete, or those that aren't are framebuffers
+    // We are complete if all samplers are either complete or will never complete
+
+    ready = ( completeCount + frameBufferCount >= samplers.Count() ) ;
+    mFinishedResourceAcquisition = ( completeCount + neverCount >= samplers.Count() );
+  }
+
+  return ready;
+}
+
+
+// Uniform maps are checked in the following priority order:
+//   Renderer (this object)
+//   Actor
+//   Material
+//   Samplers
+//   Shader
+//   Geometry
+//   VertexBuffers
+void RendererAttachment::DoPrepareRender( BufferIndex updateBufferIndex )
+{
+  // @todo MESH_REWORK - call DoPrepareRender on all scene objects? in caller class?
+  mMaterial->PrepareRender( updateBufferIndex );
+
+  if( mRegenerateUniformMap > 0)
+  {
+    if( mRegenerateUniformMap == REGENERATE_UNIFORM_MAP)
+    {
+      DALI_ASSERT_DEBUG( mGeometry != NULL && "No geometry available in DoPrepareRender()" );
+      DALI_ASSERT_DEBUG( mMaterial != NULL && "No geometry available in DoPrepareRender()" );
+
+      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
+      localMap.Resize(0);
+
+      const UniformMap& rendererUniformMap = PropertyOwner::GetUniformMap();
+      AddMappings( localMap, rendererUniformMap );
+
+      const UniformMap& actorUniformMap = mParent->GetUniformMap();
+      AddMappings( localMap, actorUniformMap );
+
+      AddMappings( localMap, mMaterial->GetUniformMap() );
+      Vector<Sampler*>& samplers = mMaterial->GetSamplers();
+      for( Vector<Sampler*>::ConstIterator iter = samplers.Begin(), end = samplers.End();
+           iter != end ;
+           ++iter )
+      {
+        const SceneGraph::Sampler* sampler = (*iter);
+        AddMappings( localMap, sampler->GetUniformMap() );
+      }
+
+      AddMappings( localMap, mMaterial->GetShader()->GetUniformMap() );
+
+      AddMappings( localMap, mGeometry->GetUniformMap() );
+
+      Vector<PropertyBuffer*>& vertexBuffers = mGeometry->GetVertexBuffers();
+      for( Vector<PropertyBuffer*>::ConstIterator iter = vertexBuffers.Begin(), end = vertexBuffers.End() ;
+           iter != end ;
+           ++iter )
+      {
+        const SceneGraph::PropertyBuffer* vertexBuffer = *iter;
+        AddMappings( localMap, vertexBuffer->GetUniformMap() );
+      }
+
+      PropertyBuffer* indexBuffer = mGeometry->GetIndexBuffer();
+      if( indexBuffer )
+      {
+        AddMappings( localMap, indexBuffer->GetUniformMap() );
+      }
+
+      mUniformMapChanged[updateBufferIndex] = true;
+    }
+    else if( mRegenerateUniformMap == COPY_UNIFORM_MAP )
+    {
+      // Copy old map into current map
+      CollectedUniformMap& localMap = mCollectedUniformMap[ updateBufferIndex ];
+      CollectedUniformMap& oldMap = mCollectedUniformMap[ 1-updateBufferIndex ];
+
+      localMap.Resize( oldMap.Count() );
+
+      unsigned int index=0;
+      for( CollectedUniformMap::Iterator iter = oldMap.Begin(), end = oldMap.End() ; iter != end ; ++iter, ++index )
+      {
+        localMap[index] = *iter;
+      }
+
+      mUniformMapChanged[updateBufferIndex] = true;
+    }
+
+    mRegenerateUniformMap--;
+  }
+
+  if( mResendDataProviders )
+  {
+    RenderDataProvider* dataProvider = NewRenderDataProvider();
+
+    // Tell renderer about a new provider
+    // @todo MESH_REWORK Should we instead create a new renderer when these change?
+
+    typedef MessageValue1< NewRenderer, OwnerPointer<RenderDataProvider> > DerivedType;
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+    new (slot) DerivedType( mRenderer, &NewRenderer::SetRenderDataProvider, dataProvider );
+    mResendDataProviders = false;
+  }
+
+  if( mResendGeometry )
+  {
+    // The first call to GetRenderGeometry() creates the geometry and sends it in a message
+    RenderGeometry* geometry = mGeometry->GetRenderGeometry( mSceneController );
+
+    typedef MessageValue1< NewRenderer, RenderGeometry* > DerivedType;
+    unsigned int* slot = mSceneController->GetRenderQueue().ReserveMessageSlot( updateBufferIndex, sizeof( DerivedType ) );
+
+    new (slot) DerivedType( mRenderer, &NewRenderer::SetGeometry, geometry );
+    mResendGeometry = false;
+  }
+}
+
+void RendererAttachment::ConnectionsChanged( PropertyOwner& object )
+{
+  // One of our child objects has changed it's connections. Ensure the uniform
+  // map gets regenerated during PrepareRender
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+
+  // Ensure the child object pointers get re-sent to the renderer
+  mResendDataProviders = true;
+}
+
+void RendererAttachment::ConnectedUniformMapChanged()
+{
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+}
+
+void RendererAttachment::UniformMappingsChanged( const UniformMap& mappings )
+{
+  // The mappings are either from PropertyOwner base class, or the Actor
+  mRegenerateUniformMap = REGENERATE_UNIFORM_MAP;
+}
+
+bool RendererAttachment::GetUniformMapChanged( BufferIndex bufferIndex ) const
+{
+  return mUniformMapChanged[bufferIndex];
+}
+
+const CollectedUniformMap& RendererAttachment::GetUniformMap( BufferIndex bufferIndex ) const
+{
+  return mCollectedUniformMap[ bufferIndex ];
+}
+
+void RendererAttachment::AddMappings( CollectedUniformMap& localMap, const UniformMap& uniformMap )
+{
+  // Iterate thru uniformMap.
+  //   Any maps that aren't in localMap should be added in a single step
+  CollectedUniformMap newUniformMappings;
+
+  for( unsigned int i=0, count=uniformMap.Count(); i<count; ++i )
+  {
+    UniformPropertyMapping::Hash nameHash = uniformMap[i].uniformNameHash;
+    bool found = false;
+
+    for( CollectedUniformMap::Iterator iter = localMap.Begin() ; iter != localMap.End() ; ++iter )
+    {
+      const UniformPropertyMapping* map = (*iter);
+      if( map->uniformNameHash == nameHash )
+      {
+        if( map->uniformName == uniformMap[i].uniformName )
+        {
+          found = true;
+          break;
+        }
+      }
+    }
+    if( !found )
+    {
+      // it's a new mapping. Add raw ptr to temporary list
+      newUniformMappings.PushBack( &uniformMap[i] );
+    }
+  }
+
+  if( newUniformMappings.Count() > 0 )
+  {
+    localMap.Reserve( localMap.Count() + newUniformMappings.Count() );
+
+    for( CollectedUniformMap::Iterator iter = newUniformMappings.Begin(),
+           end = newUniformMappings.End() ;
+         iter != end ;
+         ++iter )
+    {
+      const UniformPropertyMapping* map = (*iter);
+      localMap.PushBack( map );
+    }
+    //@todo MESH_REWORK Use memcpy to copy ptrs from one array to the other
+  }
+}
+
+RenderDataProvider* RendererAttachment::NewRenderDataProvider()
+{
+  RenderDataProvider* dataProvider = new RenderDataProvider();
+
+  dataProvider->mMaterialDataProvider = mMaterial;
+  dataProvider->mUniformMapDataProvider = this;
+  dataProvider->mShader = mMaterial->GetShader();
+
+  Vector<Sampler*>& samplers = mMaterial->GetSamplers();
+  dataProvider->mSamplers.Reserve( samplers.Count() );
+  for( Vector<Sampler*>::Iterator iter = samplers.Begin() ;
+       iter != samplers.End();
+       ++iter )
+  {
+    dataProvider->mSamplers.PushBack(*iter); // Convert from derived type to base type
+  }
+  return dataProvider;
+}
+
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/update/node-attachments/scene-graph-renderer-attachment.h b/dali/internal/update/node-attachments/scene-graph-renderer-attachment.h
new file mode 100644 (file)
index 0000000..b7c4e7a
--- /dev/null
@@ -0,0 +1,283 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_RENDERER_ATTACHMENT_H
+#define DALI_INTERNAL_SCENE_GRAPH_RENDERER_ATTACHMENT_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/scene-graph-connection-change-propagator.h>
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/update/controllers/scene-controller.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Material;
+class Geometry;
+class NewRenderer;
+struct RendererWithSortAttributes;
+
+/**
+ * The renderer attachment is the SceneGraph equivalent of Dali::Renderer. It is used to create an instance of a geometry and material for rendering, and is attached to an actor.
+ *
+ * It observes it's children (Material and Geometry) for connection change and for uniform map change, and observer's it's actor parent for uniform map change - this allows it to re-generate the uniform maps used by its RenderThread equivalent class.
+ *
+ * Lifetime and ownership
+ * It is created when a Dali::Renderer is created, and sent to UpdateManager. At this point
+ * Initialize is called on the object, but ownership is NOT taken by UpdateManager.
+
+ * When a Dali::Renderer is added to an actor, then this object becomes the node attachment
+ * for that actor, and the node takes ownership. It will create the Render::NewRenderer object
+ * in the Update thread on reciept of the connection message.
+
+ * When it's not attached to an actor, it is still possible to send messages to this
+ * object, to, e.g., set the material, or a property.
+ *
+ * @todo MESH_REWORK On merge with RenderableAttachment, change owner of all attachments to UpdateManager.
+ */
+class RendererAttachment : public RenderableAttachment,
+                           public PropertyOwner,
+                           public UniformMapDataProvider,
+                           public UniformMap::Observer,
+                           public ConnectionChangePropagator::Observer
+{
+public:
+  /**
+   * Create a new renderer attachment.
+   * @return The newly allocated RendererAttachment
+   */
+  static RendererAttachment* New();
+
+  /**
+   * Constructor
+   */
+  RendererAttachment();
+
+  /**
+   * Destructor
+   */
+  virtual ~RendererAttachment();
+
+  /**
+   * @copydoc RenderableAttachment::Initialize2().
+   */
+  virtual void Initialize2( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::OnDestroy2().
+   */
+  virtual void OnDestroy2();
+
+  /**
+   * @copydoc NodeAttachment::ConnectedToSceneGraph()
+   */
+  virtual void ConnectedToSceneGraph();
+
+  /**
+   * @copydoc NodeAttachment::DisconnectedFromSceneGraph()
+   */
+  virtual void DisconnectedFromSceneGraph();
+
+  /**
+   * Set the material for the renderer
+   * @param[in] bufferIndex The current frame's buffer index
+   * @param[in] material The material this renderer will use
+   */
+  void SetMaterial( BufferIndex bufferIndex, Material* material);
+
+  /**
+   * Get the material of this renderer
+   * @return the material this renderer uses
+   */
+  Material& GetMaterial();
+
+  /**
+   * Set the geometry for the renderer
+   * @param[in] bufferIndex The current frame's buffer index
+   * @param[in] geometry The geometry this renderer will use
+   */
+  void SetGeometry( BufferIndex bufferIndex, Geometry* geometry);
+
+  /**
+   * Get the geometry of this renderer
+   * @return the geometry this renderer uses
+   */
+  Geometry& GetGeometry();
+
+  /**
+   * Set the depth index
+   * @param[in] depthIndex the new depth index to use
+   */
+  void SetDepthIndex( int depthIndex );
+
+protected: // From NodeAttachment
+  /**
+   * @brief Get the depth index
+   * @return The depth index
+   */
+  virtual int GetDepthIndex()
+  {
+    return mDepthIndex;
+  }
+
+  /**
+   * Write the attachment's sort attributes to the passed in reference.
+   * @param[in] bufferIndex The buffer index
+   * @param[out] sortAttributes
+   */
+  virtual void SetSortAttributes( BufferIndex bufferIndex, RendererWithSortAttributes& sortAttributes );
+
+protected: // From RenderableAttachment
+  /**
+   * @copydoc RenderableAttachment::GetRenderer().
+   */
+  virtual Renderer& GetRenderer();
+
+  /**
+   * @copydoc RenderableAttachment::GetRenderer().
+   */
+  virtual const Renderer& GetRenderer() const;
+
+  /**
+   * @copydoc RenderableAttachment::DoPrepareResources()
+   */
+  virtual bool DoPrepareResources( BufferIndex updateBufferIndex,
+                                   ResourceManager& resourceManager );
+
+  /**
+   * @copydoc RenderableAttachment::DoPrepareRender()
+   */
+  virtual void DoPrepareRender( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::IsFullyOpaque()
+   */
+  virtual bool IsFullyOpaque( BufferIndex updateBufferIndex );
+
+  /**
+   * @copydoc RenderableAttachment::SizeChanged()
+   */
+  virtual void SizeChanged( BufferIndex updateBufferIndex );
+
+protected: // From ConnectionObserver
+  /**
+   * @copydoc ConnectionObservers::Observer::ConnectionsChanged
+   */
+  virtual void ConnectionsChanged(PropertyOwner& object);
+
+  /**
+   * @copydoc ConnectionObservers::Observer::ConnectedUniformMapChanged
+   */
+  virtual void ConnectedUniformMapChanged();
+
+protected: // From UniformMap::Observer
+  /**
+   * @copydoc UniformMap::Observer::UniformMappingsChanged
+   */
+  virtual void UniformMappingsChanged( const UniformMap& mappings );
+
+protected: // From UniformMapDataProvider
+  /**
+   * @copydoc UniformMapDataProvider::GetUniformMapChanged
+   */
+  virtual bool GetUniformMapChanged( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc UniformMapDataProvider::GetUniformMap
+   */
+  virtual const CollectedUniformMap& GetUniformMap( BufferIndex bufferIndex ) const;
+
+private:
+  /**
+   * Add any new mappings from map into the current map.
+   * This doesn't override any existing mappings.
+   * @param[in] localMap The map of collected uniforms.
+   * @param[in] map The map to import into the local map
+   */
+  void AddMappings( CollectedUniformMap& localMap, const UniformMap& map );
+
+  /**
+   * Create a new render data provider
+   * @return the new (initialized) data provider
+   */
+  RenderDataProvider* NewRenderDataProvider();
+
+private:
+  NewRenderer* mRenderer; ///< Raw pointer to the new renderer (that's owned by RenderManager)
+
+  Material* mMaterial; ///< The material this renderer uses. (Not owned)
+  Geometry* mGeometry; ///< The geometry this renderer uses. (Not owned)
+
+  CollectedUniformMap mCollectedUniformMap[2];
+  int mRegenerateUniformMap;      ///< 2 if the map should be regenerated, 1 if it should be copied.
+  bool mUniformMapChanged[2];     ///< Records if the uniform map has been altered this frame
+  bool mResendDataProviders : 1;  ///< True if the data providers should be resent to the renderer
+  bool mResendGeometry      : 1;  ///< True if geometry should be resent to the renderer
+
+public: // Properties
+
+  int mDepthIndex; ///< Used only in PrepareRenderInstructions
+};
+
+// Messages for RendererAttachment
+
+inline void SetMaterialMessage( EventThreadServices& eventThreadServices, const RendererAttachment& attachment, const Material& material )
+{
+  typedef MessageDoubleBuffered1< RendererAttachment, Material* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &RendererAttachment::SetMaterial, const_cast<Material*>(&material) );
+}
+
+inline void SetGeometryMessage( EventThreadServices& eventThreadServices, const RendererAttachment& attachment, const Geometry& geometry )
+{
+  typedef MessageDoubleBuffered1< RendererAttachment, Geometry* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &RendererAttachment::SetGeometry, const_cast<Geometry*>(&geometry) );
+}
+
+inline void SetDepthIndexMessage( EventThreadServices& eventThreadServices, const RendererAttachment& attachment, int depthIndex )
+{
+  typedef MessageValue1< RendererAttachment, int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &attachment, &RendererAttachment::SetDepthIndex, depthIndex );
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+
+#endif //  DALI_INTERNAL_SCENE_GRAPH_RENDERER_ATTACHMENT_H
diff --git a/dali/internal/update/nodes/node-declarations.h b/dali/internal/update/nodes/node-declarations.h
new file mode 100644 (file)
index 0000000..458b5c8
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_DECLARATIONS_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/internal/common/owner-pointer.h>
+#include <dali/internal/common/owner-container.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+class Node;
+
+typedef OwnerContainer< Node* > NodeOwnerContainer;
+
+typedef Dali::Vector< Node* > NodeContainer;
+typedef NodeContainer::Iterator NodeIter;
+typedef NodeContainer::ConstIterator NodeConstIter;
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_DECLARATIONS_H__
diff --git a/dali/internal/update/nodes/node-messages.cpp b/dali/internal/update/nodes/node-messages.cpp
new file mode 100644 (file)
index 0000000..d3fdf6f
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/nodes/node-messages.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+// Messages for Node
+
+NodePropertyMessageBase::NodePropertyMessageBase(UpdateManager& updateManager)
+: mUpdateManager(updateManager)
+{
+}
+
+NodePropertyMessageBase::~NodePropertyMessageBase()
+{
+}
+
+void NodePropertyMessageBase::NotifyUpdateManager( Node* node )
+{
+  mUpdateManager.SetNodeActive( node );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/nodes/node-messages.h b/dali/internal/update/nodes/node-messages.h
new file mode 100644 (file)
index 0000000..d49abfa
--- /dev/null
@@ -0,0 +1,250 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_MESSAGES_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_MESSAGES_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/manager/update-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+// Messages for Node
+
+class NodePropertyMessageBase : public MessageBase
+{
+public:
+
+  /**
+   * Create a message.
+   */
+  NodePropertyMessageBase(UpdateManager& updateManager);
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodePropertyMessageBase();
+
+protected:
+
+  /**
+   * Inform UpdateManager that the Node is now active
+   */
+  void NotifyUpdateManager( Node* node );
+
+private:
+
+  // Undefined
+  NodePropertyMessageBase(const NodePropertyMessageBase&);
+  NodePropertyMessageBase& operator=(const NodePropertyMessageBase& rhs);
+
+protected:
+
+  UpdateManager& mUpdateManager;
+};
+
+/**
+ * Templated message which bakes a Node property.
+ */
+template< typename P >
+class NodePropertyMessage : public NodePropertyMessageBase
+{
+public:
+
+  typedef void(AnimatableProperty<P>::*MemberFunction)( BufferIndex, typename ParameterType< P >::PassingType );
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const Node* node,
+                    const AnimatableProperty<P>* property,
+                    MemberFunction member,
+                    typename ParameterType< P >::PassingType value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( NodePropertyMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) NodePropertyMessage( eventThreadServices.GetUpdateManager(), node, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodePropertyMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+
+    if( ! mNode->IsActive() )
+    {
+      // Inform UpdateManager that the Node is now active
+      NotifyUpdateManager( mNode );
+    }
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] updateManager The update-manager.
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the property.
+   */
+  NodePropertyMessage( UpdateManager& updateManager,
+                       const Node* node,
+                       const AnimatableProperty<P>* property,
+                       MemberFunction member,
+                       typename ParameterType< P >::PassingType value )
+  : NodePropertyMessageBase( updateManager ),
+    mNode( const_cast< Node* >( node ) ),
+    mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+
+  Node* mNode;
+  AnimatableProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  typename ParameterType< P >::HolderType mParam;
+};
+
+/**
+ * Templated message which bakes a Node property.
+ */
+template< typename P >
+class NodePropertyComponentMessage : public NodePropertyMessageBase
+{
+public:
+
+  typedef void(AnimatableProperty<P>::*MemberFunction)( BufferIndex, float );
+
+  /**
+   * Send a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] eventThreadServices The object used to send messages to the scene graph
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+   */
+  static void Send( EventThreadServices& eventThreadServices,
+                    const Node* node,
+                    const AnimatableProperty<P>* property,
+                    MemberFunction member,
+                    float value )
+  {
+    // Reserve some memory inside the message queue
+    unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( NodePropertyComponentMessage ) );
+
+    // Construct message in the message queue memory; note that delete should not be called on the return value
+    new (slot) NodePropertyComponentMessage( eventThreadServices.GetUpdateManager(), node, property, member, value );
+  }
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~NodePropertyComponentMessage()
+  {
+  }
+
+  /**
+   * @copydoc MessageBase::Process
+   */
+  virtual void Process( BufferIndex updateBufferIndex )
+  {
+    (mProperty->*mMemberFunction)( updateBufferIndex, mParam );
+
+    if( ! mNode->IsActive() )
+    {
+      // Inform UpdateManager that the Node is now active
+      NotifyUpdateManager( mNode );
+    }
+  }
+
+private:
+
+  /**
+   * Create a message.
+   * @note The node is expected to be const in the thread which sends this message.
+   * However it can be modified when Process() is called in a different thread.
+   * @param[in] updateManager The update-manager.
+   * @param[in] node The node.
+   * @param[in] property The property to bake.
+   * @param[in] member The member function of the object.
+   * @param[in] value The new value of the X,Y,Z or W component.
+  */
+  NodePropertyComponentMessage( UpdateManager& updateManager,
+                                const Node* node,
+                                const AnimatableProperty<P>* property,
+                                MemberFunction member,
+                                float value )
+  : NodePropertyMessageBase( updateManager ),
+    mNode( const_cast< Node* >( node ) ),
+    mProperty( const_cast< AnimatableProperty<P>* >( property ) ),
+    mMemberFunction( member ),
+    mParam( value )
+  {
+  }
+
+private:
+
+  Node* mNode;
+  AnimatableProperty<P>* mProperty;
+  MemberFunction mMemberFunction;
+  float mParam;
+};
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_MESSAGES_H__
diff --git a/dali/internal/update/nodes/node.cpp b/dali/internal/update/nodes/node.cpp
new file mode 100644 (file)
index 0000000..db5798f
--- /dev/null
@@ -0,0 +1,293 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/nodes/node.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/node-attachments/node-attachment.h>
+#include <dali/internal/update/common/discard-queue.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/constants.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+const PositionInheritanceMode Node::DEFAULT_POSITION_INHERITANCE_MODE( INHERIT_PARENT_POSITION );
+const ColorMode Node::DEFAULT_COLOR_MODE( USE_OWN_MULTIPLY_PARENT_ALPHA );
+
+Node* Node::New()
+{
+  return new Node();
+}
+
+Node::Node()
+: mParentOrigin( ParentOrigin::DEFAULT ),
+  mAnchorPoint( AnchorPoint::DEFAULT ),
+  mSize(),     // zero initialized by default
+  mPosition(), // zero initialized by default
+  mOrientation(), // initialized to identity by default
+  mScale( Vector3::ONE ),
+  mVisible( true ),
+  mColor( Color::WHITE ),
+  mWorldPosition(), // zero initialized by default
+  mWorldOrientation(), // initialized to identity by default
+  mWorldScale( Vector3::ONE ),
+  mWorldMatrix(),
+  mWorldColor( Color::WHITE ),
+  mParent( NULL ),
+  mExclusiveRenderTask( NULL ),
+  mAttachment( NULL ),
+  mChildren(),
+  mDepth(0u),
+  mDirtyFlags(AllFlags),
+  mIsRoot( false ),
+  mInheritOrientation( true ),
+  mInheritScale( true ),
+  mInhibitLocalTransform( false ),
+  mIsActive( true ),
+  mDrawMode( DrawMode::NORMAL ),
+  mPositionInheritanceMode( DEFAULT_POSITION_INHERITANCE_MODE ),
+  mColorMode( DEFAULT_COLOR_MODE )
+{
+}
+
+Node::~Node()
+{
+}
+
+void Node::OnDestroy()
+{
+  // Node attachments should be notified about the disconnection.
+  if ( mAttachment )
+  {
+    mAttachment->OnDestroy();
+  }
+
+  // Animators, Constraints etc. should be disconnected from the child's properties.
+  PropertyOwner::Destroy();
+}
+
+void Node::Attach( NodeAttachment& object )
+{
+  DALI_ASSERT_DEBUG(!mAttachment);
+
+  object.SetParent(*this);
+
+  mAttachment = &object;
+  SetAllDirtyFlags();
+
+  if( mIsActive )
+  {
+    mAttachment->ConnectedToSceneGraph();
+  }
+}
+
+void Node::SetRoot(bool isRoot)
+{
+  DALI_ASSERT_DEBUG(!isRoot || mParent == NULL); // Root nodes cannot have a parent
+
+  mIsRoot = isRoot;
+}
+
+void Node::ConnectChild( Node* childNode, int index )
+{
+  DALI_ASSERT_ALWAYS( this != childNode );
+  DALI_ASSERT_ALWAYS( IsRoot() || NULL != mParent ); // Parent should be connected first
+  DALI_ASSERT_ALWAYS( !childNode->IsRoot() && NULL == childNode->GetParent() ); // Child should be disconnected
+
+  childNode->SetParent( *this );
+
+  // Everything should be reinherited when reconnected to scene-graph
+  childNode->SetAllDirtyFlags();
+
+  if (index == -1)
+  {
+    mChildren.PushBack( childNode );
+  }
+  else
+  {
+    mChildren.Insert(mChildren.Begin()+index, childNode);
+  }
+
+  // Inform property observers of new connection
+  childNode->ConnectToSceneGraph();
+
+  // Inform child node attachment that the node has been added to the stage
+  if( childNode->mAttachment )
+  {
+    childNode->mAttachment->ConnectedToSceneGraph();
+  }
+}
+
+void Node::DisconnectChild( BufferIndex updateBufferIndex, Node& childNode, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
+{
+  DALI_ASSERT_ALWAYS( this != &childNode );
+  DALI_ASSERT_ALWAYS( childNode.GetParent() == this );
+
+  // Find the childNode and remove it
+  Node* found( NULL );
+
+  const NodeIter endIter = mChildren.End();
+  for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
+  {
+    Node* current = *iter;
+    if ( current == &childNode )
+    {
+      found = current;
+      mChildren.Erase( iter ); // order matters here
+      break; // iter is no longer valid
+    }
+  }
+  DALI_ASSERT_ALWAYS( NULL != found );
+
+  found->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
+}
+
+int Node::GetDirtyFlags() const
+{
+  // get initial dirty flags, they are reset ResetDefaultProperties, but setters may have made the node dirty already
+  int flags = mDirtyFlags;
+  const bool sizeFlag = mSize.IsClean();
+
+  if ( !(flags & TransformFlag) )
+  {
+    // Check whether the transform related properties have changed
+    if( !sizeFlag            ||
+        !mPosition.IsClean() ||
+        !mOrientation.IsClean() ||
+        !mScale.IsClean()    ||
+        mParentOrigin.InputChanged() || // parent origin and anchor point rarely change
+        mAnchorPoint.InputChanged() )
+    {
+      flags |= TransformFlag;
+    }
+  }
+
+  // Check whether the visible property has changed
+  if ( !mVisible.IsClean() )
+  {
+    flags |= VisibleFlag;
+  }
+
+  // Check whether the color property has changed
+  if ( !mColor.IsClean() )
+  {
+    flags |= ColorFlag;
+  }
+
+  // Check whether the size property has changed
+  if ( !sizeFlag )
+  {
+    flags |= SizeFlag;
+   }
+
+  return flags;
+}
+
+void Node::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  // clear dirty flags in parent origin & anchor point
+  mParentOrigin.Clear();
+  mAnchorPoint.Clear();
+  // Reset default properties
+  mSize.ResetToBaseValue( updateBufferIndex );
+  mPosition.ResetToBaseValue( updateBufferIndex );
+  mOrientation.ResetToBaseValue( updateBufferIndex );
+  mScale.ResetToBaseValue( updateBufferIndex );
+  mVisible.ResetToBaseValue( updateBufferIndex );
+  mColor.ResetToBaseValue( updateBufferIndex );
+
+  mDirtyFlags = NothingFlag;
+}
+
+bool Node::IsFullyVisible( BufferIndex updateBufferIndex ) const
+{
+  if( !IsVisible( updateBufferIndex ) )
+  {
+    return false;
+  }
+
+  Node* parent = mParent;
+
+  while( NULL != parent )
+  {
+    if( !parent->IsVisible( updateBufferIndex ) )
+    {
+      return false;
+    }
+
+    parent = parent->GetParent();
+  }
+
+  return true;
+}
+
+void Node::SetParent(Node& parentNode)
+{
+  DALI_ASSERT_ALWAYS(this != &parentNode);
+  DALI_ASSERT_ALWAYS(!mIsRoot);
+  DALI_ASSERT_ALWAYS(mParent == NULL);
+
+  mParent = &parentNode;
+  mDepth = mParent->GetDepth() + 1u;
+}
+
+void Node::RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes )
+{
+  DALI_ASSERT_ALWAYS(!mIsRoot);
+  DALI_ASSERT_ALWAYS(mParent != NULL);
+
+  const NodeIter endIter = mChildren.End();
+  for ( NodeIter iter = mChildren.Begin(); iter != endIter; ++iter )
+  {
+    (*iter)->RecursiveDisconnectFromSceneGraph( updateBufferIndex, connectedNodes, disconnectedNodes );
+  }
+
+  // Animators, Constraints etc. should be disconnected from the child's properties.
+  PropertyOwner::DisconnectFromSceneGraph( updateBufferIndex );
+
+  // Remove back-pointer to parent
+  mParent = NULL;
+  mDepth = 0u;
+
+  // Remove all child pointers
+  mChildren.Clear();
+
+  // Inform child node attachment that the node has been removed from the stage
+  if( mAttachment )
+  {
+    mAttachment->DisconnectedFromSceneGraph();
+  }
+
+  // Move into disconnectedNodes
+  std::set<Node*>::size_type removed = connectedNodes.erase( this );
+  DALI_ASSERT_ALWAYS( removed );
+  disconnectedNodes.insert( this );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/nodes/node.h b/dali/internal/update/nodes/node.h
new file mode 100644 (file)
index 0000000..7c4242b
--- /dev/null
@@ -0,0 +1,1122 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_NODE_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_NODE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/actors/draw-mode.h>
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/property-vector3.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+#include <dali/internal/update/common/inherited-property.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/update/nodes/node-declarations.h>
+#include <dali/internal/update/node-attachments/node-attachment-declarations.h>
+#include <dali/internal/render/data-providers/node-data-provider.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+// value types used by messages
+template <> struct ParameterType< ColorMode > : public BasicType< ColorMode > {};
+template <> struct ParameterType< PositionInheritanceMode > : public BasicType< PositionInheritanceMode > {};
+
+namespace SceneGraph
+{
+
+class DiscardQueue;
+class Layer;
+class NodeAttachment;
+class RenderTask;
+class UpdateManager;
+
+/**
+ * Flag whether property has changed, during the Update phase.
+ */
+enum NodePropertyFlags
+{
+  NothingFlag          = 0x000,
+  TransformFlag        = 0x001,
+  VisibleFlag          = 0x002,
+  ColorFlag            = 0x004,
+  SizeFlag             = 0x008,
+  OverlayFlag          = 0x010,
+  SortModifierFlag     = 0x020,
+  ChildDeletedFlag     = 0x040
+};
+
+static const int AllFlags = ( ChildDeletedFlag << 1 ) - 1; // all the flags
+
+/**
+ * Size is not inherited.
+ * VisibleFlag is inherited so that attachments can be synchronized with nodes after they become visible
+ */
+static const int InheritedDirtyFlags = TransformFlag | VisibleFlag | ColorFlag | OverlayFlag;
+
+// Flags which require the scene renderable lists to be updated
+static const int RenderableUpdateFlags = TransformFlag | SortModifierFlag | ChildDeletedFlag;
+
+/**
+ * Node is the base class for all nodes in the Scene Graph.
+ *
+ * Each node provides a transformation which applies to the node and
+ * its children.  Node data is double-buffered. This allows an update
+ * thread to modify node data, without interferring with another
+ * thread reading the values from the previous update traversal.
+ */
+class Node : public PropertyOwner, public NodeDataProvider
+{
+public:
+
+  // Defaults
+  static const PositionInheritanceMode DEFAULT_POSITION_INHERITANCE_MODE;
+  static const ColorMode DEFAULT_COLOR_MODE;
+
+  // Creation methods
+
+  /**
+   * Construct a new Node.
+   */
+  static Node* New();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Node();
+
+  /**
+   * When a Node is marked "active" it has been disconnected, but its properties have been modified.
+   * @note An inactive Node will be skipped during the UpdateManager ResetProperties stage.
+   * @param[in] isActive True if the Node is active.
+   */
+  void SetActive( bool isActive )
+  {
+    mIsActive = isActive;
+  }
+
+  /**
+   * Query whether the Node is active.
+   * @return True if the Node is active.
+   */
+  bool IsActive() const
+  {
+    return mIsActive;
+  }
+
+  /**
+   * Called during UpdateManager::DestroyNode shortly before Node is destroyed.
+   */
+  void OnDestroy();
+
+  // Layer interface
+
+  /**
+   * Query whether the node is a layer.
+   * @return True if the node is a layer.
+   */
+  bool IsLayer()
+  {
+    return (GetLayer() != NULL);
+  }
+
+  /**
+   * Convert a node to a layer.
+   * @return A pointer to the layer, or NULL.
+   */
+  virtual Layer* GetLayer()
+  {
+    return NULL;
+  }
+
+  // Attachments
+
+  /**
+   * Attach an object to this Node; This should only be done by UpdateManager::AttachToNode.
+   * @pre The Node does not already have an attachment.
+   * @param[in] attachment The object to attach.
+   */
+  void Attach( NodeAttachment& attachment );
+
+  /**
+   * Query the node if it has an attachment.
+   * @return True if it has an attachment.
+   */
+  bool HasAttachment() const
+  {
+    return mAttachment;
+  }
+
+  /**
+   * Retreive the object attached to this node.
+   * @return The attachment.
+   */
+  NodeAttachment& GetAttachment() const
+  {
+    return *mAttachment;
+  }
+
+  // Containment methods
+
+  /**
+   * Query whether a node is the root node. Root nodes cannot have a parent node.
+   * A node becomes a root node, when it is installed by UpdateManager.
+   * @return True if the node is a root node.
+   */
+  bool IsRoot() const
+  {
+    return mIsRoot;
+  }
+
+  /**
+   * Set whether a node is the root node. Root nodes cannot have a parent node.
+   * This method should only be called by UpdateManager.
+   * @pre When isRoot is true, the node must not have a parent.
+   * @param[in] isRoot Whether the node is now a root node.
+   */
+  void SetRoot(bool isRoot);
+
+  /**
+   * Retrieve the parent of a Node.
+   * @return The parent node, or NULL if the Node has not been added to the scene-graph.
+   */
+  Node* GetParent()
+  {
+    return mParent;
+  }
+
+  /**
+   * Retrieve the parent of a Node.
+   * @return The parent node, or NULL if the Node has not been added to the scene-graph.
+   */
+  const Node* GetParent() const
+  {
+    return mParent;
+  }
+
+  /**
+   * Connect a node to the scene-graph.
+   * @pre A node cannot be added to itself.
+   * @pre The parent node is connected to the scene-graph.
+   * @pre The childNode does not already have a parent.
+   * @pre The childNode is not a root node.
+   * @param[in] childNode The child to add.
+   * @param[in] index to insert at, if not supplied or -1 it will be appended
+   *
+   */
+  void ConnectChild( Node* childNode, int index = -1);
+
+  /**
+   * Disconnect a child (& its children) from the scene-graph.
+   * @pre childNode is a child of this Node.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] childNode The node to disconnect.
+   * @param[in] connectedNodes Disconnected Node attachments should be removed from here.
+   * @param[in] disconnectedNodes Disconnected Node attachments should be added here.
+   */
+  void DisconnectChild( BufferIndex updateBufferIndex, Node& childNode, std::set<Node*>& connectedNodes,  std::set<Node*>& disconnectedNodes );
+
+  /**
+   * Retrieve the children a Node.
+   * @return The container of children.
+   */
+  const NodeContainer& GetChildren() const
+  {
+    return mChildren;
+  }
+
+  /**
+   * Retrieve the children a Node.
+   * @return The container of children.
+   */
+  NodeContainer& GetChildren()
+  {
+    return mChildren;
+  }
+
+  // Update methods
+
+  /**
+   * Flag that one of the node values has changed in the current frame.
+   * @param[in] flag The flag to set.
+   */
+  void SetDirtyFlag(NodePropertyFlags flag)
+  {
+    mDirtyFlags |= flag;
+  }
+
+  /**
+   * Flag that all of the node values are dirty.
+   */
+  void SetAllDirtyFlags()
+  {
+    mDirtyFlags = AllFlags;
+  }
+
+  /**
+   * Query whether a node is dirty.
+   * @return The dirty flags
+   */
+  int GetDirtyFlags() const;
+
+  /**
+   * Query whether a node is clean.
+   * @return True if the node is clean.
+   */
+  bool IsClean() const
+  {
+    return ( NothingFlag == GetDirtyFlags() );
+  }
+
+  /**
+   * Retrieve the parent-origin of the node.
+   * @return The parent-origin.
+   */
+  const Vector3& GetParentOrigin() const
+  {
+    return mParentOrigin.mValue;
+  }
+
+  /**
+   * Sets both the local & base parent-origins of the node.
+   * @param[in] origin The new local & base parent-origins.
+   */
+  void SetParentOrigin(const Vector3& origin)
+  {
+    mParentOrigin.mValue = origin;
+    mParentOrigin.OnSet();
+  }
+
+  /**
+   * Retrieve the anchor-point of the node.
+   * @return The anchor-point.
+   */
+  const Vector3& GetAnchorPoint() const
+  {
+    return mAnchorPoint.mValue;
+  }
+
+  /**
+   * Sets both the local & base anchor-points of the node.
+   * @param[in] anchor The new local & base anchor-points.
+   */
+  void SetAnchorPoint(const Vector3& anchor)
+  {
+    mAnchorPoint.mValue = anchor;
+    mAnchorPoint.OnSet();
+  }
+
+  /**
+   * Retrieve the local position of the node, relative to its parent.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The local position.
+   */
+  const Vector3& GetPosition(BufferIndex bufferIndex) const
+  {
+    return mPosition[bufferIndex];
+  }
+
+  /**
+   * Sets both the local & base positions of the node.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] position The new local & base position.
+   */
+  void BakePosition(BufferIndex updateBufferIndex, const Vector3& position)
+  {
+    mPosition.Bake( updateBufferIndex, position );
+  }
+
+  /**
+   * Sets the world of the node derived from the position of all its parents.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] position The world position.
+   */
+  void SetWorldPosition( BufferIndex updateBufferIndex, const Vector3& position )
+  {
+    mWorldPosition.Set( updateBufferIndex, position );
+  }
+
+  /**
+   * Sets the position of the node derived from the position of all its parents.
+   * This method should only be called when the parent's world position is up-to-date.
+   * With a non-central anchor-point, the local orientation and scale affects the world position.
+   * Therefore the world orientation & scale must be updated before the world position.
+   * @pre The node has a parent.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void InheritWorldPosition(BufferIndex updateBufferIndex)
+  {
+    DALI_ASSERT_DEBUG(mParent != NULL);
+
+    switch( mPositionInheritanceMode )
+    {
+      case INHERIT_PARENT_POSITION  : ///@see Dali::PositionInheritanceMode for how these modes are expected to work
+      {
+        Vector3 finalPosition(-0.5f, -0.5f, -0.5f);
+
+        finalPosition += mParentOrigin.mValue;
+        finalPosition *= mParent->GetSize(updateBufferIndex);
+        finalPosition += mPosition[updateBufferIndex];
+        finalPosition *= mParent->GetWorldScale(updateBufferIndex);
+        const Quaternion& parentWorldOrientation = mParent->GetWorldOrientation(updateBufferIndex);
+        if(!parentWorldOrientation.IsIdentity())
+        {
+          finalPosition *= parentWorldOrientation;
+        }
+
+        // check if a node needs to be offsetted locally (only applies when AnchorPoint is not central)
+        // dont use operator== as that does a slower comparison (and involves function calls)
+        Vector3 localOffset(0.5f, 0.5f, 0.5f);    // AnchorPoint::CENTER
+        localOffset -= mAnchorPoint.mValue;
+
+        if( ( fabsf( localOffset.x ) >= Math::MACHINE_EPSILON_0 ) ||
+            ( fabsf( localOffset.y ) >= Math::MACHINE_EPSILON_0 ) ||
+            ( fabsf( localOffset.z ) >= Math::MACHINE_EPSILON_0 ) )
+        {
+          localOffset *= mSize[updateBufferIndex];
+
+          Vector3 scale = mWorldScale[updateBufferIndex];
+
+          // Pick up sign of local scale
+          if (mScale[updateBufferIndex].x < 0.0f)
+          {
+            scale.x = -scale.x;
+          }
+          if (mScale[updateBufferIndex].y < 0.0f)
+          {
+            scale.y = -scale.y;
+          }
+          if (mScale[updateBufferIndex].z < 0.0f)
+          {
+            scale.z = -scale.z;
+          }
+
+          // If the anchor-point is not central, then position is affected by the local orientation & scale
+          localOffset *= scale;
+          const Quaternion& localWorldOrientation = mWorldOrientation[updateBufferIndex];
+          if(!localWorldOrientation.IsIdentity())
+          {
+            localOffset *= localWorldOrientation;
+          }
+          finalPosition += localOffset;
+        }
+
+        finalPosition += mParent->GetWorldPosition(updateBufferIndex);
+        mWorldPosition.Set( updateBufferIndex, finalPosition );
+        break;
+      }
+      case USE_PARENT_POSITION_PLUS_LOCAL_POSITION :
+      {
+        // copy parents position plus local transform
+        mWorldPosition.Set( updateBufferIndex, mParent->GetWorldPosition(updateBufferIndex) + mPosition[updateBufferIndex] );
+        break;
+      }
+      case USE_PARENT_POSITION :
+      {
+        // copy parents position
+        mWorldPosition.Set( updateBufferIndex, mParent->GetWorldPosition(updateBufferIndex) );
+        break;
+      }
+      case DONT_INHERIT_POSITION :
+      {
+        // use local position as world position
+        mWorldPosition.Set( updateBufferIndex, mPosition[updateBufferIndex] );
+        break;
+      }
+    }
+  }
+
+  /**
+   * Copies the previous inherited position, if this changed in the previous frame.
+   * This method should be called instead of InheritWorldPosition i.e. if the inherited position
+   * does not need to be recalculated in the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousWorldPosition( BufferIndex updateBufferIndex )
+  {
+    mWorldPosition.CopyPrevious( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve the position of the node derived from the position of all its parents.
+   * @return The world position.
+   */
+  const Vector3& GetWorldPosition( BufferIndex bufferIndex ) const
+  {
+    return mWorldPosition[bufferIndex];
+  }
+
+  /**
+   * Set the position inheritance mode.
+   * @see Dali::Actor::PositionInheritanceMode
+   * @param[in] mode The new position inheritance mode.
+   */
+  void SetPositionInheritanceMode( PositionInheritanceMode mode )
+  {
+    mPositionInheritanceMode = mode;
+
+    SetDirtyFlag(TransformFlag);
+  }
+
+  /**
+   * @return The position inheritance mode.
+   */
+  PositionInheritanceMode GetPositionInheritanceMode() const
+  {
+    return mPositionInheritanceMode;
+  }
+
+  /**
+   * Retrieve the local orientation of the node, relative to its parent.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The local orientation.
+   */
+  const Quaternion& GetOrientation(BufferIndex bufferIndex) const
+  {
+    return mOrientation[bufferIndex];
+  }
+
+  /**
+   * Sets both the local & base orientations of the node.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] orientation The new local & base orientation.
+   */
+  void BakeOrientation(BufferIndex updateBufferIndex, const Quaternion& orientation)
+  {
+    mOrientation.Bake( updateBufferIndex, orientation );
+  }
+
+  /**
+   * Sets the orientation of the node derived from the rotation of all its parents.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] orientation The world orientation.
+   */
+  void SetWorldOrientation( BufferIndex updateBufferIndex, const Quaternion& orientation )
+  {
+    mWorldOrientation.Set( updateBufferIndex, orientation );
+  }
+
+  /**
+   * Sets the orientation of the node derived from the rotation of all its parents.
+   * This method should only be called when the parents world orientation is up-to-date.
+   * @pre The node has a parent.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void InheritWorldOrientation( BufferIndex updateBufferIndex )
+  {
+    DALI_ASSERT_DEBUG(mParent != NULL);
+
+    const Quaternion& localOrientation = mOrientation[updateBufferIndex];
+
+    if(localOrientation.IsIdentity())
+    {
+      mWorldOrientation.Set( updateBufferIndex, mParent->GetWorldOrientation(updateBufferIndex) );
+    }
+    else
+    {
+      Quaternion finalOrientation( mParent->GetWorldOrientation(updateBufferIndex) );
+      finalOrientation *= localOrientation;
+      mWorldOrientation.Set( updateBufferIndex, finalOrientation );
+    }
+  }
+
+  /**
+   * Copies the previous inherited orientation, if this changed in the previous frame.
+   * This method should be called instead of InheritWorldOrientation i.e. if the inherited orientation
+   * does not need to be recalculated in the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousWorldOrientation( BufferIndex updateBufferIndex )
+  {
+    mWorldOrientation.CopyPrevious( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve the orientation of the node derived from the rotation of all its parents.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The world rotation.
+   */
+  const Quaternion& GetWorldOrientation( BufferIndex bufferIndex ) const
+  {
+    return mWorldOrientation[bufferIndex];
+  }
+
+  /**
+   * Set whether the Node inherits orientation.
+   * @param[in] inherit True if the parent orientation is inherited.
+   */
+  void SetInheritOrientation(bool inherit)
+  {
+    if (inherit != mInheritOrientation)
+    {
+      mInheritOrientation = inherit;
+
+      SetDirtyFlag(TransformFlag);
+    }
+  }
+
+  /**
+   * Query whether the node inherits orientation from its parent.
+   * @return True if the parent orientation is inherited.
+   */
+  bool IsOrientationInherited() const
+  {
+    return mInheritOrientation;
+  }
+
+  /**
+   * Retrieve the local scale of the node, relative to its parent.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The local scale.
+   */
+  const Vector3& GetScale(BufferIndex bufferIndex) const
+  {
+    return mScale[bufferIndex];
+  }
+
+  /**
+   * Sets the scale of the node derived from the scale of all its parents and a pre-scale
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] scale The world scale.
+   */
+  void SetWorldScale(BufferIndex updateBufferIndex, const Vector3& scale)
+  {
+    mWorldScale.Set( updateBufferIndex, scale );
+  }
+
+  /**
+   * Sets the scale of the node derived from the scale of all its parents and a pre-scale.
+   * This method should only be called when the parents world scale is up-to-date.
+   * @pre The node has a parent.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void InheritWorldScale(BufferIndex updateBufferIndex)
+  {
+    DALI_ASSERT_DEBUG(mParent != NULL);
+
+    mWorldScale.Set( updateBufferIndex, mParent->GetWorldScale(updateBufferIndex) * mScale[updateBufferIndex] );
+  }
+
+  /**
+   * Copies the previous inherited scale, if this changed in the previous frame.
+   * This method should be called instead of InheritWorldScale i.e. if the inherited scale
+   * does not need to be recalculated in the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousWorldScale( BufferIndex updateBufferIndex )
+  {
+    mWorldScale.CopyPrevious( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve the scale of the node derived from the scale of all its parents.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The world scale.
+   */
+  const Vector3& GetWorldScale( BufferIndex bufferIndex ) const
+  {
+    return mWorldScale[bufferIndex];
+  }
+
+  /**
+   * Set whether the Node inherits scale.
+   * @param inherit True if the Node inherits scale.
+   */
+  void SetInheritScale( bool inherit )
+  {
+    if( inherit != mInheritScale )
+    {
+      mInheritScale = inherit;
+
+      SetDirtyFlag( TransformFlag );
+    }
+  }
+
+  /**
+   * Query whether the Node inherits scale.
+   * @return if scale is inherited
+   */
+  bool IsScaleInherited() const
+  {
+    return mInheritScale;
+  }
+
+  /**
+   * Copies the previously used size, if this changed in the previous frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousSize( BufferIndex updateBufferIndex )
+  {
+    SetSize( updateBufferIndex, GetSize( 1u - updateBufferIndex ) );
+  }
+
+  /**
+   * Retrieve the visibility of the node.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return True if the node is visible.
+   */
+  bool IsVisible(BufferIndex bufferIndex) const
+  {
+    return mVisible[bufferIndex];
+  }
+
+  /**
+   * Retrieves whether a node is fully visible.
+   * A node is fully visible if is visible and all its ancestors are visible.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return True if the node is fully visible.
+   */
+  bool IsFullyVisible( BufferIndex updateBufferIndex ) const;
+
+  /**
+   * Retrieve the opacity of the node.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The opacity.
+   */
+  float GetOpacity(BufferIndex bufferIndex) const
+  {
+    return mColor[bufferIndex].a;
+  }
+
+  /**
+   * Retrieve the color of the node.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The color.
+   */
+  const Vector4& GetColor(BufferIndex bufferIndex) const
+  {
+    return mColor[bufferIndex];
+  }
+
+  /**
+   * Sets the color of the node derived from the color of all its parents.
+   * @param[in] color The world color.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void SetWorldColor(const Vector4& color, BufferIndex updateBufferIndex)
+  {
+    mWorldColor.Set( updateBufferIndex, color );
+  }
+
+  /**
+   * Sets the color of the node derived from the color of all its parents.
+   * This method should only be called when the parents world color is up-to-date.
+   * @pre The node has a parent.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void InheritWorldColor( BufferIndex updateBufferIndex )
+  {
+    DALI_ASSERT_DEBUG(mParent != NULL);
+
+    // default first
+    if( mColorMode == USE_OWN_MULTIPLY_PARENT_ALPHA )
+    {
+      const Vector4& ownColor = mColor[updateBufferIndex];
+      mWorldColor.Set( updateBufferIndex, ownColor.r, ownColor.g, ownColor.b, ownColor.a * mParent->GetWorldColor(updateBufferIndex).a );
+    }
+    else if( mColorMode == USE_OWN_MULTIPLY_PARENT_COLOR )
+    {
+      mWorldColor.Set( updateBufferIndex, mParent->GetWorldColor(updateBufferIndex) * mColor[updateBufferIndex] );
+    }
+    else if( mColorMode == USE_PARENT_COLOR )
+    {
+      mWorldColor.Set( updateBufferIndex, mParent->GetWorldColor(updateBufferIndex) );
+    }
+    else // USE_OWN_COLOR
+    {
+      mWorldColor.Set( updateBufferIndex, mColor[updateBufferIndex] );
+    }
+  }
+
+  /**
+   * Copies the previous inherited scale, if this changed in the previous frame.
+   * This method should be called instead of InheritWorldScale i.e. if the inherited scale
+   * does not need to be recalculated in the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousWorldColor( BufferIndex updateBufferIndex )
+  {
+    mWorldColor.CopyPrevious( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve the color of the node, possibly derived from the color
+   * of all its parents, depending on the value of mColorMode.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The world color.
+   */
+  const Vector4& GetWorldColor(BufferIndex bufferIndex) const
+  {
+    return mWorldColor[bufferIndex];
+  }
+
+  /**
+   * Set the color mode. This specifies whether the Node uses its own color,
+   * or inherits its parent color.
+   * @param[in] colorMode The new color mode.
+   */
+  void SetColorMode(ColorMode colorMode)
+  {
+    mColorMode = colorMode;
+
+    SetDirtyFlag(ColorFlag);
+  }
+
+  /**
+   * Retrieve the color mode.
+   * @return The color mode.
+   */
+  ColorMode GetColorMode() const
+  {
+    return mColorMode;
+  }
+
+  /**
+   * Sets the size of the node.
+   * @param[in] bufferIndex The buffer to write to.
+   * @param[in] size The size to write.
+   */
+  void SetSize( BufferIndex bufferIndex, const Vector3& size )
+  {
+    mSize[bufferIndex] = size;
+  }
+
+  /**
+   * Retrieve the size of the node.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The size.
+   */
+  const Vector3& GetSize(BufferIndex bufferIndex) const
+  {
+    return mSize[bufferIndex];
+  }
+
+  /**
+   * Set the world-matrix of a node, with scale + rotation + translation.
+   * Scale and rotation are centered at the origin.
+   * Translation is applied independently of the scale or rotatation axis.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] scale The scale.
+   * @param[in] rotation The rotation.
+   * @param[in] translation The translation.
+   */
+  void SetWorldMatrix( BufferIndex updateBufferIndex, const Vector3& scale, const Quaternion& rotation, const Vector3& translation )
+  {
+    mWorldMatrix.Get( updateBufferIndex ).SetTransformComponents( scale, rotation, translation );
+    mWorldMatrix.SetDirty( updateBufferIndex );
+  }
+
+  /**
+   * Retrieve the cached world-matrix of a node.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The world-matrix.
+   */
+  const Matrix& GetWorldMatrix( BufferIndex bufferIndex ) const
+  {
+    return mWorldMatrix[ bufferIndex ];
+  }
+
+  /**
+   * Copy previous frames world matrix
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void CopyPreviousWorldMatrix( BufferIndex updateBufferIndex )
+  {
+    mWorldMatrix.CopyPrevious( updateBufferIndex );
+  }
+
+  /**
+   * Mark the node as exclusive to a single RenderTask.
+   * @param[in] renderTask The render-task, or NULL if the Node is not exclusive to a single RenderTask.
+   */
+  void SetExclusiveRenderTask( RenderTask* renderTask )
+  {
+    mExclusiveRenderTask = renderTask;
+  }
+
+  /**
+   * Query whether the node is exclusive to a single RenderTask.
+   * @return The render-task, or NULL if the Node is not exclusive to a single RenderTask.
+   */
+  RenderTask* GetExclusiveRenderTask() const
+  {
+    return mExclusiveRenderTask;
+  }
+
+  /**
+   * Set how the Node and its children should be drawn; see Dali::Actor::SetDrawMode() for more details.
+   * @param[in] drawMode The new draw-mode to use.
+   */
+  void SetDrawMode( const DrawMode::Type& drawMode )
+  {
+    mDrawMode = drawMode;
+  }
+
+  /**
+   * Returns whether node is an overlay or not.
+   * @return True if node is an overlay, false otherwise.
+   */
+  DrawMode::Type GetDrawMode() const
+  {
+    return mDrawMode;
+  }
+
+  /**
+   * Equality operator, checks for identity, not values.
+   *
+   */
+  bool operator==( const Node* rhs ) const
+  {
+    if ( this == rhs )
+    {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Set the inhibit local transform flag.@n
+   * Setting this flag will stop the node's local transform (position, scale and orientation)
+   * being applied on top of its parents transformation.
+   * @param[in] flag When true, local transformation is inhibited when calculating the world matrix.
+   */
+  void SetInhibitLocalTransform( bool flag )
+  {
+    SetDirtyFlag( TransformFlag );
+    mInhibitLocalTransform = flag;
+  }
+
+  /**
+   * Get the inhibit local transform flag.@n
+   * See @ref SetInhibitLocalTransform
+   * @result A flag, when true, local transformation is inhibited when calculating the world matrix.
+   */
+  bool GetInhibitLocalTransform() const
+  {
+    return mInhibitLocalTransform;
+  }
+
+  unsigned short GetDepth() const
+  {
+    return mDepth;
+  }
+
+protected:
+
+  /**
+   * Set the parent of a Node.
+   * @param[in] parentNode the new parent.
+   */
+  void SetParent(Node& parentNode);
+
+  /**
+   * Protected constructor; See also Node::New()
+   */
+  Node();
+
+private: // from NodeDataProvider
+
+  /**
+   * @copydoc NodeDataProvider::GetModelMatrix
+   */
+  virtual const Matrix& GetModelMatrix( unsigned int bufferId )
+  {
+    return GetWorldMatrix( bufferId );
+  }
+
+  /**
+   * @copydoc NodeDataProvider::GetRenderColor
+   */
+  virtual const Vector4& GetRenderColor( unsigned int bufferId )
+  {
+    return GetWorldColor( bufferId );
+  }
+
+  virtual const Vector3& GetRenderSize( unsigned int bufferId )
+  {
+    return GetSize( bufferId );
+  }
+
+
+private:
+
+  // Undefined
+  Node(const Node&);
+
+  // Undefined
+  Node& operator=(const Node& rhs);
+
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+  /**
+   * Recursive helper to disconnect a Node and its children.
+   * Disconnected Nodes have no parent or children.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] connectedNodes Disconnected Node attachments should be removed from here.
+   * @param[in] disconnectedNodes Disconnected Node attachments should be added here.
+   */
+  void RecursiveDisconnectFromSceneGraph( BufferIndex updateBufferIndex, std::set<Node*>& connectedNodes, std::set<Node*>& disconnectedNodes );
+
+public: // Default properties
+
+  PropertyVector3                mParentOrigin;  ///< Local transform; the position is relative to this. Sets the TransformFlag dirty when changed
+  PropertyVector3                mAnchorPoint;   ///< Local transform; local center of rotation. Sets the TransformFlag dirty when changed
+
+  AnimatableProperty<Vector3>    mSize;          ///< Size is provided for layouting
+  AnimatableProperty<Vector3>    mPosition;      ///< Local transform; distance between parent-origin & anchor-point
+  AnimatableProperty<Quaternion> mOrientation;   ///< Local transform; rotation relative to parent node
+  AnimatableProperty<Vector3>    mScale;         ///< Local transform; scale relative to parent node
+  AnimatableProperty<bool>       mVisible;       ///< Visibility can be inherited from the Node hierachy
+  AnimatableProperty<Vector4>    mColor;         ///< Color can be inherited from the Node hierarchy
+
+  // Inherited properties; read-only from public API
+
+  InheritedVector3    mWorldPosition;     ///< Full inherited position
+  InheritedQuaternion mWorldOrientation;  ///< Full inherited orientation
+  InheritedVector3    mWorldScale;        ///< Full inherited scale
+  InheritedMatrix     mWorldMatrix;       ///< Full inherited world matrix
+  InheritedColor      mWorldColor;        ///< Full inherited color
+
+protected:
+
+  Node*               mParent;                       ///< Pointer to parent node (a child is owned by its parent)
+  RenderTask*         mExclusiveRenderTask;          ///< Nodes can be marked as exclusive to a single RenderTask
+
+  NodeAttachmentOwner mAttachment;                   ///< Optional owned attachment
+  NodeContainer       mChildren;                     ///< Container of children; not owned
+
+
+  // flags, compressed to bitfield
+  unsigned short mDepth: 12;                        ///< Depth in the hierarchy
+  int  mDirtyFlags:8;                               ///< A composite set of flags for each of the Node properties
+
+  bool mIsRoot:1;                                    ///< True if the node cannot have a parent
+  bool mInheritOrientation:1;                        ///< Whether the parent's orientation should be inherited.
+  bool mInheritScale:1;                              ///< Whether the parent's scale should be inherited.
+  bool mInhibitLocalTransform:1;                     ///< whether local transform should be applied.
+  bool mIsActive:1;                                  ///< When a Node is marked "active" it has been disconnected, and its properties have not been modified
+
+  DrawMode::Type          mDrawMode:2;               ///< How the Node and its children should be drawn
+  PositionInheritanceMode mPositionInheritanceMode:2;///< Determines how position is inherited, 2 bits is enough
+  ColorMode               mColorMode:2;              ///< Determines whether mWorldColor is inherited, 2 bits is enough
+
+  // Changes scope, should be at end of class
+  DALI_LOG_OBJECT_STRING_DECLARATION;
+};
+
+// Messages for Node
+
+inline void SetInheritOrientationMessage( EventThreadServices& eventThreadServices, const Node& node, bool inherit )
+{
+  typedef MessageValue1< Node, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetInheritOrientation, inherit );
+}
+
+
+
+inline void SetParentOriginMessage( EventThreadServices& eventThreadServices, const Node& node, const Vector3& origin )
+{
+  typedef MessageValue1< Node, Vector3 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetParentOrigin, origin );
+}
+
+inline void SetAnchorPointMessage( EventThreadServices& eventThreadServices, const Node& node, const Vector3& anchor )
+{
+  typedef MessageValue1< Node, Vector3 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetAnchorPoint, anchor );
+}
+
+inline void SetPositionInheritanceModeMessage( EventThreadServices& eventThreadServices, const Node& node, PositionInheritanceMode mode )
+{
+  typedef MessageValue1< Node, PositionInheritanceMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetPositionInheritanceMode, mode );
+}
+
+inline void SetInheritScaleMessage( EventThreadServices& eventThreadServices, const Node& node, bool inherit )
+{
+  typedef MessageValue1< Node, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetInheritScale, inherit );
+}
+
+inline void SetColorModeMessage( EventThreadServices& eventThreadServices, const Node& node, ColorMode colorMode )
+{
+  typedef MessageValue1< Node, ColorMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetColorMode, colorMode );
+}
+
+inline void SetDrawModeMessage( EventThreadServices& eventThreadServices, const Node& node, DrawMode::Type drawMode )
+{
+  typedef MessageValue1< Node, DrawMode::Type > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &node, &Node::SetDrawMode, drawMode );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_NODE_H_
diff --git a/dali/internal/update/nodes/scene-graph-layer.cpp b/dali/internal/update/nodes/scene-graph-layer.cpp
new file mode 100644 (file)
index 0000000..8cf8155
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/nodes/scene-graph-layer.h>
+#include <dali/internal/event/actors/layer-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+SceneGraph::Layer* Layer::New()
+{
+  return new Layer();
+}
+
+Layer::Layer()
+: mSortFunction( Internal::Layer::ZValue ),
+  mClippingBox( 0,0,0,0 ),
+  mLastCamera( NULL ),
+  mBehavior( Dali::Layer::LAYER_2D ),
+  mIsClipping( false ),
+  mDepthTestDisabled( false ),
+  mIsDefaultSortFunction( true )
+{
+  // layer starts off dirty
+  mAllChildTransformsClean[ 0 ] = false;
+  mAllChildTransformsClean[ 1 ] = false;
+}
+
+Layer::~Layer()
+{
+}
+
+void Layer::SetSortFunction( Dali::Layer::SortFunctionType function )
+{
+  if( mSortFunction != function )
+  {
+    // is a custom sort function used
+    if( function != Internal::Layer::ZValue )
+    {
+      mIsDefaultSortFunction = false;
+    }
+    else
+    {
+      mIsDefaultSortFunction = true;
+    }
+
+    // changing the sort function makes the layer dirty
+    mAllChildTransformsClean[ 0 ] = false;
+    mAllChildTransformsClean[ 1 ] = false;
+    mSortFunction = function;
+  }
+}
+
+void Layer::SetClipping(bool enabled)
+{
+  mIsClipping = enabled;
+}
+
+void Layer::SetClippingBox(const Dali::ClippingBox& box)
+{
+  mClippingBox.Set(box.x, box.y, box.width, box.height);
+}
+
+void Layer::SetBehavior( Dali::Layer::Behavior behavior )
+{
+  mBehavior = behavior;
+}
+
+void Layer::SetDepthTestDisabled( bool disable )
+{
+  mDepthTestDisabled = disable;
+}
+
+bool Layer::IsDepthTestDisabled() const
+{
+  return ( mBehavior == Dali::Layer::LAYER_2D ) || mDepthTestDisabled;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/nodes/scene-graph-layer.h b/dali/internal/update/nodes/scene-graph-layer.h
new file mode 100644 (file)
index 0000000..90789e4
--- /dev/null
@@ -0,0 +1,316 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/update/node-attachments/scene-graph-renderable-attachment-declarations.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+class RenderableAttachment;
+
+// value types used by messages
+template <> struct ParameterType< Dali::Layer::SortFunctionType >
+: public BasicType< Dali::Layer::SortFunctionType > {};
+template <> struct ParameterType< Dali::Layer::Behavior >
+: public BasicType< Dali::Layer::Behavior > {};
+
+namespace SceneGraph
+{
+
+/**
+ * Layers have a "depth" relative to all other layers in the scene-graph.
+ * Non-layer child nodes (and their attachments) are considered part of the layer.
+ *
+ * Layers are rendered separately, and the depth buffer is cleared before each layer is rendered.
+ * Objects in higher layers, are rendered after (in front of) objects in lower layers.
+ */
+class Layer : public Node
+{
+public:
+
+  typedef Dali::Layer::SortFunctionType SortFunctionType;
+
+  // Creation methods
+
+  /**
+   * Construct a new Layer.
+   * @return A smart-pointer to a newly allocated Node
+   */
+  static SceneGraph::Layer* New();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~Layer();
+
+  /**
+   * From Node, to convert a node to a layer.
+   * @return The layer.
+   */
+  virtual Layer* GetLayer()
+  {
+    return this;
+  }
+
+  /**
+   * Sets the sort-function of a layer.
+   * @param [in] function The new sort-function.
+   */
+  void SetSortFunction( Dali::Layer::SortFunctionType function );
+
+  /**
+   * Retrieve the function used to sort semi-transparent geometry in this layer.
+   * @return The sort function.
+   */
+  Dali::Layer::SortFunctionType GetSortFunction() const
+  {
+    return mSortFunction;
+  }
+
+  /**
+   * Sets whether clipping is enabled for a layer.
+   * @param [in] enabled True if clipping is enabled.
+   */
+  void SetClipping( bool enabled );
+
+  /**
+   * Query whether clipping is enabled for a layer.
+   * @return True if clipping is enabled.
+   */
+  bool IsClipping() const
+  {
+    return mIsClipping;
+  }
+
+  /**
+   * Sets the clipping box of a layer, in window coordinates.
+   * The contents of the layer will not be visible outside this box, when clipping is
+   * enabled. The default clipping box is empty (0,0,0,0).
+   * @param [in] box The clipping box
+   */
+  void SetClippingBox( const ClippingBox& box );
+
+  /**
+   * Retrieves the clipping box of a layer, in window coordinates.
+   * @return The clipping box
+   */
+  const ClippingBox& GetClippingBox() const
+  {
+    return mClippingBox;
+  }
+
+  /**
+   * Sets the behavior of the layer
+   * @param [in] behavior The behavior of the layer
+   */
+  void SetBehavior( Dali::Layer::Behavior behavior );
+
+  /**
+   * Retrieves the behavior of the layer.
+   * @return The behavior
+   */
+  Dali::Layer::Behavior GetBehavior() const
+  {
+    return mBehavior;
+  }
+
+  /**
+   * @copydoc Dali::Layer::SetDepthTestDisabled()
+   */
+  void SetDepthTestDisabled( bool disable );
+
+  /**
+   * @copydoc Dali::Layer::IsDepthTestDisabled()
+   */
+  bool IsDepthTestDisabled() const;
+
+  /**
+   * Enables the reuse of the model view matrices of all renderers for this layer
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param value to set
+   */
+  void SetReuseRenderers( BufferIndex updateBufferIndex, bool value )
+  {
+    mAllChildTransformsClean[ updateBufferIndex ] = value;
+  }
+
+  /**
+   * Checks if it is ok to reuse renderers. Renderers can be reused if ModelView transform for all the renderers
+   * has not changed from previous use.
+   * @param[in] camera A pointer to the camera that we want to use to render the list.
+   * @return True if all children transforms have been clean for two consecutive frames and the camera we are going
+   * to use is the same than the one used before ( Otherwise View transform will be different )
+   *
+   */
+  bool CanReuseRenderers(Node* camera)
+  {
+    bool bReturn( mAllChildTransformsClean[ 0 ] && mAllChildTransformsClean[ 1 ] && camera == mLastCamera );
+    mLastCamera = camera;
+
+    return bReturn;
+  }
+
+  /**
+   * @return True if default sort function is used
+   */
+  bool UsesDefaultSortFunction()
+  {
+    return mIsDefaultSortFunction;
+  }
+
+private:
+
+  /**
+   * Private constructor.
+   * See also Layer::New()
+   */
+  Layer();
+
+  // Undefined
+  Layer(const Layer&);
+
+  // Undefined
+  Layer& operator=(const Layer& rhs);
+
+public: // For update-algorithms
+
+  RenderableAttachmentContainer stencilRenderables;
+  RenderableAttachmentContainer colorRenderables;
+  RenderableAttachmentContainer overlayRenderables;
+
+private:
+
+  SortFunctionType mSortFunction; ///< Used to sort semi-transparent geometry
+
+  ClippingBox mClippingBox;           ///< The clipping box, in window coordinates
+  Node* mLastCamera;                  ///< Pointer to the last camera that has rendered the layer
+
+  Dali::Layer::Behavior mBehavior;    ///< The behavior of the layer
+
+  bool mAllChildTransformsClean[ 2 ]; ///< True if all child nodes transforms are clean,
+                                      /// double buffered as we need two clean frames before we can reuse N-1 for N+1
+                                      /// this allows us to cache render items when layer is "static"
+  bool mIsClipping:1;                 ///< True when clipping is enabled
+  bool mDepthTestDisabled:1;          ///< Whether depth test is disabled.
+  bool mIsDefaultSortFunction:1;      ///< whether the default depth sort function is used
+
+};
+
+// Messages for Layer
+
+/**
+ * Create a message to set the sort-function of a layer
+ * @param[in] layer The layer
+ * @param[in] function The new sort-function.
+ */
+inline void SetSortFunctionMessage( EventThreadServices& eventThreadServices, const Layer& layer, Dali::Layer::SortFunctionType function )
+{
+  typedef MessageValue1< Layer, Dali::Layer::SortFunctionType > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &layer, &Layer::SetSortFunction, function );
+}
+
+/**
+ * Create a message for enabling/disabling layer clipping
+ * @param[in] layer The layer
+ * @param[in] enabled True if clipping is enabled
+ */
+inline void SetClippingMessage( EventThreadServices& eventThreadServices, const Layer& layer, bool enabled )
+{
+  typedef MessageValue1< Layer, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &layer, &Layer::SetClipping, enabled );
+}
+
+/**
+ * Create a message to set the clipping box of a layer
+ * @param[in] layer The layer
+ * @param[in] clippingbox The clipping box
+ */
+inline void SetClippingBoxMessage( EventThreadServices& eventThreadServices, const Layer& layer, const Dali::ClippingBox& clippingbox )
+{
+  typedef MessageValue1< Layer, Dali::ClippingBox > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &layer, &Layer::SetClippingBox, clippingbox );
+}
+
+/**
+ * Create a message to set the behavior of a layer
+ * @param[in] layer The layer
+ * @param[in] behavior The behavior
+ */
+inline void SetBehaviorMessage( EventThreadServices& eventThreadServices,
+                                const Layer& layer,
+                                Dali::Layer::Behavior behavior )
+{
+  typedef MessageValue1< Layer, Dali::Layer::Behavior > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &layer, &Layer::SetBehavior, behavior );
+}
+
+/**
+ * Create a message for disabling/enabling depth test.
+ *
+ * @see Dali::Layer::SetDepthTestDisabled().
+ *
+ * @param[in] layer The layer
+ * @param[in] disable \e true disables depth test. \e false sets the default behavior.
+ */
+inline void SetDepthTestDisabledMessage( EventThreadServices& eventThreadServices, const Layer& layer, bool disable )
+{
+  typedef MessageValue1< Layer, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &layer, &Layer::SetDepthTestDisabled, disable );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_LAYER_H__
diff --git a/dali/internal/update/queue/update-message-queue.cpp b/dali/internal/update/queue/update-message-queue.cpp
new file mode 100644 (file)
index 0000000..ada76a6
--- /dev/null
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/queue/update-message-queue.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/devel-api/common/mutex.h>
+#include <dali/integration-api/render-controller.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/message-buffer.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+using std::vector;
+
+using Dali::Integration::RenderController;
+using Dali::Internal::SceneGraph::SceneGraphBuffers;
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace // unnamed namespace
+{
+
+// A message to set Actor::SIZE is 72 bytes on 32bit device
+// A buffer of size 32768 would store (32768 - 4) / (72 + 4) = 431 of those messages
+static const std::size_t INITIAL_BUFFER_SIZE =  32768;
+static const std::size_t MAX_BUFFER_CAPACITY = 73728; // Avoid keeping buffers which exceed this
+static const std::size_t MAX_FREE_BUFFER_COUNT = 3; // Allow this number of buffers to be recycled
+
+// A queue of message buffers
+typedef vector< MessageBuffer* > MessageBufferQueue;
+typedef MessageBufferQueue::iterator MessageBufferIter;
+
+typedef Dali::Mutex MessageQueueMutex;
+
+} // unnamed namespace
+
+namespace Update
+{
+
+/**
+ * Private MessageQueue data
+ */
+struct MessageQueue::Impl
+{
+  Impl( RenderController& controller, const SceneGraphBuffers& buffers )
+  : renderController(controller),
+    sceneGraphBuffers(buffers),
+    processingEvents(false),
+    queueWasEmpty(true),
+    sceneUpdateFlag( false ),
+    sceneUpdate( 0 ),
+    currentMessageBuffer(NULL)
+  {
+  }
+
+  ~Impl()
+  {
+    // Delete the current buffer
+    delete currentMessageBuffer;
+
+    // Delete the unprocessed buffers
+    const MessageBufferIter processQueueEndIter = processQueue.end();
+    for ( MessageBufferIter iter = processQueue.begin(); iter != processQueueEndIter; ++iter )
+    {
+      MessageBuffer* unprocessedBuffer = *iter;
+      DeleteBufferContents( unprocessedBuffer );
+      delete unprocessedBuffer;
+    }
+
+    // Delete the recycled buffers
+    const MessageBufferIter recycleQueueEndIter = recycleQueue.end();
+    for ( MessageBufferIter iter = recycleQueue.begin(); iter != recycleQueueEndIter; ++iter )
+    {
+      MessageBuffer* recycledBuffer = *iter;
+      DeleteBufferContents( recycledBuffer );
+      delete recycledBuffer;
+    }
+
+    const MessageBufferIter freeQueueEndIter = freeQueue.end();
+    for ( MessageBufferIter iter = freeQueue.begin(); iter != freeQueueEndIter; ++iter )
+    {
+      MessageBuffer* freeBuffer = *iter;
+      DeleteBufferContents( freeBuffer );
+      delete freeBuffer;
+    }
+  }
+
+  void DeleteBufferContents( MessageBuffer* buffer )
+  {
+    for( MessageBuffer::Iterator iter = buffer->Begin(); iter.IsValid(); iter.Next() )
+    {
+      MessageBase* message = reinterpret_cast< MessageBase* >( iter.Get() );
+
+      // Call virtual destructor explictly; since delete will not be called after placement new
+      message->~MessageBase();
+    }
+  }
+
+  RenderController&        renderController;     ///< render controller
+  const SceneGraphBuffers& sceneGraphBuffers;    ///< Used to keep track of which buffers are being written or read.
+
+  bool                     processingEvents;     ///< Whether messages queued will be flushed by core
+  bool                     queueWasEmpty;        ///< Flag whether the queue was empty during the Update()
+  bool                     sceneUpdateFlag;      ///< true when there is a new message that requires a scene-graph node tree update
+  int                      sceneUpdate;          ///< Non zero when there is a message in the queue requiring a scene-graph node tree update
+
+  MessageQueueMutex        queueMutex;           ///< queueMutex must be locked whilst accessing processQueue or recycleQueue
+  MessageBufferQueue       processQueue;         ///< to process in the next update
+  MessageBufferQueue       recycleQueue;         ///< to recycle MessageBuffers after the messages have been processed
+
+  MessageBuffer*           currentMessageBuffer; ///< can be used without locking
+  MessageBufferQueue       freeQueue;            ///< buffers from the recycleQueue; can be used without locking
+};
+
+MessageQueue::MessageQueue( Integration::RenderController& controller, const SceneGraph::SceneGraphBuffers& buffers )
+: mImpl(NULL)
+{
+  mImpl = new Impl( controller, buffers );
+}
+
+MessageQueue::~MessageQueue()
+{
+  delete mImpl;
+}
+
+void MessageQueue::EventProcessingStarted()
+{
+  mImpl->processingEvents = true;
+}
+
+unsigned int* MessageQueue::ReserveMessageSlot( unsigned int requestedSize, bool updateScene )
+{
+  DALI_ASSERT_DEBUG( 0 != requestedSize );
+
+  if( updateScene )
+  {
+    mImpl->sceneUpdateFlag = true;
+  }
+
+  if ( !mImpl->currentMessageBuffer )
+  {
+    const MessageBufferIter endIter = mImpl->freeQueue.end();
+
+    // Find the largest recycled buffer from freeQueue
+    MessageBufferIter nextBuffer = endIter;
+    for ( MessageBufferIter iter = mImpl->freeQueue.begin(); iter != endIter; ++iter )
+    {
+      if ( endIter == nextBuffer ||
+           (*nextBuffer)->GetCapacity() < (*iter)->GetCapacity() )
+      {
+        nextBuffer = iter;
+      }
+    }
+
+    if ( endIter != nextBuffer )
+    {
+      // Reuse a recycled buffer from freeQueue
+      mImpl->currentMessageBuffer = *nextBuffer;
+      mImpl->freeQueue.erase( nextBuffer );
+    }
+    else
+    {
+      mImpl->currentMessageBuffer = new MessageBuffer( INITIAL_BUFFER_SIZE );
+    }
+  }
+
+  // If we are inside Core::ProcessEvents(), core will automatically flush the queue.
+  // If we are outside, then we have to request a call to Core::ProcessEvents() on idle.
+  if ( false == mImpl->processingEvents )
+  {
+    mImpl->renderController.RequestProcessEventsOnIdle();
+  }
+
+  return mImpl->currentMessageBuffer->ReserveMessageSlot( requestedSize );
+}
+
+bool MessageQueue::FlushQueue()
+{
+  const bool messagesToProcess = ( NULL != mImpl->currentMessageBuffer );
+
+  // If there're messages to flush
+  if ( messagesToProcess )
+  {
+    // queueMutex must be locked whilst accessing processQueue or recycleQueue
+    MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+    mImpl->processQueue.push_back( mImpl->currentMessageBuffer );
+    mImpl->currentMessageBuffer = NULL;
+
+    // Grab any recycled MessageBuffers
+    while ( !mImpl->recycleQueue.empty() )
+    {
+      MessageBuffer* recycled = mImpl->recycleQueue.back();
+      mImpl->recycleQueue.pop_back();
+
+      // Guard against excessive message buffer growth
+      if ( MAX_FREE_BUFFER_COUNT < mImpl->freeQueue.size() ||
+           MAX_BUFFER_CAPACITY   < recycled->GetCapacity() )
+      {
+        delete recycled;
+      }
+      else
+      {
+        mImpl->freeQueue.push_back( recycled );
+      }
+    }
+
+    if( mImpl->sceneUpdateFlag )
+    {
+      mImpl->sceneUpdate |= 2;
+      mImpl->sceneUpdateFlag = false;
+    }
+  }
+
+  mImpl->processingEvents = false;
+
+  return messagesToProcess;
+}
+
+void MessageQueue::ProcessMessages()
+{
+  PERF_MONITOR_START(PerformanceMonitor::PROCESS_MESSAGES);
+
+  // queueMutex must be locked whilst accessing queue
+  MessageQueueMutex::ScopedLock lock( mImpl->queueMutex );
+
+  const MessageBufferIter processQueueEndIter = mImpl->processQueue.end();
+  for ( MessageBufferIter iter = mImpl->processQueue.begin(); iter != processQueueEndIter ; ++iter )
+  {
+    MessageBuffer* buffer = *iter;
+
+    for( MessageBuffer::Iterator iter = buffer->Begin(); iter.IsValid(); iter.Next() )
+    {
+      MessageBase* message = reinterpret_cast< MessageBase* >( iter.Get() );
+
+      message->Process( mImpl->sceneGraphBuffers.GetUpdateBufferIndex() );
+
+      // Call virtual destructor explictly; since delete will not be called after placement new
+      message->~MessageBase();
+    }
+    buffer->Reset();
+
+    // Pass back for use in the event-thread
+    mImpl->recycleQueue.push_back( buffer );
+  }
+
+  mImpl->sceneUpdate >>= 1;
+
+  mImpl->queueWasEmpty = mImpl->processQueue.empty(); // Flag whether we processed anything
+
+  mImpl->processQueue.clear();
+
+  PERF_MONITOR_END(PerformanceMonitor::PROCESS_MESSAGES);
+}
+
+bool MessageQueue::WasEmpty() const
+{
+  return mImpl->queueWasEmpty;
+}
+
+bool MessageQueue::IsSceneUpdateRequired() const
+{
+  return mImpl->sceneUpdate;
+}
+
+} // namespace Update
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/queue/update-message-queue.h b/dali/internal/update/queue/update-message-queue.h
new file mode 100644 (file)
index 0000000..954ae32
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __DALI_INTERNAL_UPDATE_MESSAGE_QUEUE_H__
+#define __DALI_INTERNAL_UPDATE_MESSAGE_QUEUE_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class RenderController;
+}
+
+namespace Internal
+{
+class MessageBase;
+
+namespace SceneGraph
+{
+class SceneGraphBuffers;
+}
+
+
+namespace Update
+{
+
+/**
+ * Used by UpdateManager to receive messages from the event-thread.
+ */
+class MessageQueue
+{
+public:
+
+  /**
+   * Create a new UpdateMessageQueue.
+   * @param[in] renderController After messages are flushed, we request a render from the RenderController.
+   * @param[in] sceneGraphBuffers Used to keep track of which buffers are being written or read.
+   */
+  MessageQueue( Integration::RenderController& renderController,
+                const SceneGraph::SceneGraphBuffers& sceneGraphBuffers );
+
+  /**
+   * Destructor
+   */
+  ~MessageQueue();
+
+  /**
+   * Inform the queue that event processing has started
+   */
+  void EventProcessingStarted();
+
+  /**
+   * Reserve space for a message
+   * @param[in] size the message size with respect to the size of type 'char'
+   * @param[in] updateScene If set to true, denotes that the message will cause the scene graph node tree to require an update
+   * @return A pointer to the first char allocated for the message
+   */
+  unsigned int* ReserveMessageSlot( unsigned int size, bool updateScene );
+
+  /**
+   * Flushes the message queue
+   * @return true if there are messages to process
+   */
+  bool FlushQueue();
+
+  // Exclusive to UpdateManager
+
+  /**
+   * Called once per update; process the previously flushed messages.
+   */
+  void ProcessMessages();
+
+  /**
+   * Query whether the queue was empty this frame.
+   */
+  bool WasEmpty() const;
+
+  /**
+   * Query whether the queue contains at least one message that requires that the scene-graph
+   * node tree be updated.
+   * @return A flag, true if the scene graph needs an update
+   */
+  bool IsSceneUpdateRequired() const;
+
+private:
+
+  /**
+   * Helper to call Process and destructor on each queued message
+   * @param[in] minorQueue The queue to process.
+   */
+  void ProcessMinorQueue( char* minorQueue );
+
+private:
+
+  // Not copyable:
+  MessageQueue ( const MessageQueue& rhs );
+  MessageQueue& operator=( const MessageQueue& rhs );
+
+private:
+
+  struct Impl;
+  Impl* mImpl;
+};
+
+} // namespace Update
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_UPDATE_MESSAGE_QUEUE_H__
diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-debug.h b/dali/internal/update/render-tasks/scene-graph-render-task-debug.h
new file mode 100644 (file)
index 0000000..adcaf05
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_DEBUG_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gRenderTaskLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_SCENE_GRAPH_RENDER_TASK");
+
+#define STATE_STRING(state)                                     \
+  (state==RENDER_CONTINUOUSLY?"RenderContinuously":              \
+    (state==RENDER_ONCE_WAITING_FOR_RESOURCES?"RenderOnceWaiting":  \
+    (state==RENDERED_ONCE?"RenderedOnce":                        \
+    (state==RENDERED_ONCE_AND_NOTIFIED?"RenderedOnceAndNotified":  \
+     "Unknown"))))
+
+#define TASK_LOG(level)                                              \
+  DALI_LOG_INFO(gRenderTaskLogFilter, level, "SceneGraph::RenderTask::%s: this:%p\n", __FUNCTION__, this)
+#define TASK_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gRenderTaskLogFilter, level, "SceneGraph::RenderTask::%s: this:%p " format, __FUNCTION__, this, ## args)
+
+#else
+
+#define TASK_LOG(level)
+#define TASK_LOG_FMT(level, format, args...)
+
+#endif
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_DEBUG_H__
diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp b/dali/internal/update/render-tasks/scene-graph-render-task-list.cpp
new file mode 100644 (file)
index 0000000..618c01e
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/render-tasks/scene-graph-render-task-list.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderTaskList::RenderTaskList(CompleteStatusManager& completeStatusManager)
+: mNotificationObject( NULL ),
+  mCompleteStatusManager( completeStatusManager )
+{
+}
+
+RenderTaskList::~RenderTaskList()
+{
+}
+
+void RenderTaskList::AddTask( RenderTask* newTask )
+{
+  DALI_ASSERT_DEBUG( newTask != NULL && "SceneGraph RenderTask is null");
+
+  // mRenderTasks container takes ownership
+  mRenderTasks.PushBack( newTask );
+  newTask->SetCompleteStatusManager( &mCompleteStatusManager );
+}
+
+void RenderTaskList::RemoveTask( RenderTask* task )
+{
+  RenderTaskContainer::ConstIterator end = mRenderTasks.End();
+  for ( RenderTaskContainer::Iterator iter = mRenderTasks.Begin(); iter != end; ++iter )
+  {
+    if ( *iter == task )
+    {
+      // Destroy the task
+      mRenderTasks.Erase( iter );
+
+      break; // we're finished
+    }
+  }
+}
+
+RenderTaskList::RenderTaskContainer& RenderTaskList::GetTasks()
+{
+  return mRenderTasks;
+}
+
+const RenderTaskList::RenderTaskContainer& RenderTaskList::GetTasks() const
+{
+  return mRenderTasks;
+}
+
+void RenderTaskList::SetCompleteNotificationInterface( CompleteNotificationInterface* object )
+{
+
+  mNotificationObject = object;
+}
+
+CompleteNotificationInterface* RenderTaskList::GetCompleteNotificationInterface()
+{
+
+  return mNotificationObject;
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/render-tasks/scene-graph-render-task-list.h b/dali/internal/update/render-tasks/scene-graph-render-task-list.h
new file mode 100644 (file)
index 0000000..ad40d2d
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_LIST_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_LIST_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/owner-container.h>
+#include <dali/internal/event/common/event-thread-services.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class CompleteStatusManager;
+class CompleteNotificationInterface;
+
+namespace SceneGraph
+{
+
+class RenderTask;
+
+/**
+ * An ordered list of render-tasks.
+ */
+class RenderTaskList
+{
+public:
+
+  typedef OwnerContainer< RenderTask* > RenderTaskContainer;
+
+  /**
+   * Constructor
+   */
+  RenderTaskList( CompleteStatusManager& completeStatusManager );
+
+  /**
+   * Destructor
+   */
+  ~RenderTaskList();
+
+  /**
+   * Add a new RenderTask to the list.
+   * @param[in] newTask The RenderTaskList takes ownership of this task.
+   */
+  void AddTask( RenderTask* newTask );
+
+  /**
+   * Remove a RenderTask from the list.
+   * @param[in] task The RenderTaskList will destroy this task.
+   */
+  void RemoveTask( RenderTask* task );
+
+  /**
+   * Retrieve the container of RenderTasks.
+   * @return The container.
+   */
+  RenderTaskContainer& GetTasks();
+
+  /**
+   * Retrieve the container of RenderTasks.
+   * @return The container.
+   */
+  const RenderTaskContainer& GetTasks() const;
+
+  /**
+   * Set the notification method to package in the NotifyFinishedMessage
+   * @param object to store in notification managers queue
+   */
+  void SetCompleteNotificationInterface( CompleteNotificationInterface* object );
+
+  /**
+   * Get the Notification interface for when 1+ render tasks have finished
+   */
+  CompleteNotificationInterface* GetCompleteNotificationInterface();
+
+private:
+
+  // Undefined
+  RenderTaskList(const RenderTaskList&);
+
+  // Undefined
+  RenderTaskList& operator=(const RenderTaskList&);
+
+private:
+
+  CompleteNotificationInterface* mNotificationObject; ///< object to pass in to the complete notification
+  RenderTaskContainer mRenderTasks; ///< A container of owned RenderTasks
+  CompleteStatusManager& mCompleteStatusManager; ///< The complete status tracker (render tasks need this)
+
+};
+
+// Messages for RenderTaskList
+
+inline void AddTaskMessage( EventThreadServices& eventThreadServices, RenderTaskList& list, RenderTask& task )
+{
+  typedef MessageValue1< RenderTaskList, RenderTask* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &list, &RenderTaskList::AddTask, &task );
+}
+
+inline void RemoveTaskMessage( EventThreadServices& eventThreadServices, RenderTaskList& list, const RenderTask& constTask )
+{
+  // Scene graph thread can destroy this object.
+  RenderTask& task = const_cast< RenderTask& >( constTask );
+
+  typedef MessageValue1< RenderTaskList, RenderTask* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &list, &RenderTaskList::RemoveTask, &task );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_LIST_H__
diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.cpp b/dali/internal/update/render-tasks/scene-graph-render-task.cpp
new file mode 100644 (file)
index 0000000..379cb39
--- /dev/null
@@ -0,0 +1,534 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/render-tasks/scene-graph-render-task.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/matrix.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/complete-status-manager.h>
+#include <dali/internal/update/nodes/node.h>
+#include <dali/internal/render/common/render-instruction.h>
+
+#include <dali/internal/update/render-tasks/scene-graph-render-task-debug.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+namespace SceneGraph
+{
+
+RenderTask* RenderTask::New()
+{
+  return new RenderTask();
+}
+
+RenderTask::~RenderTask()
+{
+  // Remove exclusive flag from source node
+  if( mExclusive )
+  {
+    if( mSourceNode && (this == mSourceNode->GetExclusiveRenderTask() ) )
+    {
+      mSourceNode->SetExclusiveRenderTask( NULL );
+    }
+  }
+  if( mFrameBufferResourceId )
+  {
+    mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
+  }
+}
+
+void RenderTask::SetSourceNode( Node* node )
+{
+  // Remove exclusive flag from the old node, if necessary
+  if ( mSourceNode &&
+       this == mSourceNode->GetExclusiveRenderTask() )
+  {
+    mSourceNode->SetExclusiveRenderTask( NULL );
+  }
+
+  mSourceNode = node;
+
+  if ( mSourceNode && mExclusive )
+  {
+    mSourceNode->SetExclusiveRenderTask( this );
+  }
+}
+
+Node* RenderTask::GetSourceNode() const
+{
+  return mSourceNode;
+}
+
+void RenderTask::SetExclusive( bool exclusive )
+{
+  mExclusive = exclusive;
+
+  if ( mSourceNode )
+  {
+    if ( mExclusive )
+    {
+      mSourceNode->SetExclusiveRenderTask( this );
+    }
+    else if ( this == mSourceNode->GetExclusiveRenderTask() )
+    {
+      mSourceNode->SetExclusiveRenderTask( NULL );
+    }
+  }
+}
+
+bool RenderTask::IsExclusive() const
+{
+  return mExclusive;
+}
+
+void RenderTask::SetCameraNode( Node* cameraNode )
+{
+  // if camera changed
+  if( cameraNode != mCameraNode )
+  {
+    if( cameraNode )
+    {
+      // get attachment. when camera node is changed we will get a message from event thread object
+      // so no need to observe the node here
+      mCameraAttachment = dynamic_cast< CameraAttachment* >( &cameraNode->GetAttachment() );
+      DALI_ASSERT_DEBUG( mCameraAttachment && "Camera without attachment" );
+    }
+    mCameraNode = cameraNode;
+  }
+}
+
+void RenderTask::SetFrameBufferId( unsigned int resourceId )
+{
+  if ( mFrameBufferResourceId != resourceId )
+  {
+    DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
+    if( mCompleteStatusManager )
+    {
+      if( resourceId && mState == RENDER_ONCE_WAITING_FOR_RESOURCES )
+      {
+        mCompleteStatusManager->TrackResource( resourceId );
+      }
+
+      if( mFrameBufferResourceId )
+      {
+        mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
+      }
+    }
+
+    mFrameBufferResourceId = resourceId;
+  }
+}
+
+unsigned int RenderTask::GetFrameBufferId() const
+{
+  return mFrameBufferResourceId;
+}
+
+bool RenderTask::QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const
+{
+  if( ! GetViewportEnabled( bufferIndex ) )
+  {
+    return false;
+  }
+
+  viewport.x = mViewportPosition[bufferIndex].x;
+  viewport.y = mViewportPosition[bufferIndex].y;
+  viewport.width = mViewportSize[bufferIndex].width;
+  viewport.height = mViewportSize[bufferIndex].height;
+
+  return true;
+}
+
+void RenderTask::SetClearColor( BufferIndex updateBufferIndex, const Vector4& value )
+{
+  mClearColor.Set( updateBufferIndex, value );
+}
+
+const Vector4& RenderTask::GetClearColor( BufferIndex bufferIndex ) const
+{
+  return mClearColor[bufferIndex];
+}
+
+void RenderTask::BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value )
+{
+  mClearColor.Bake( updateBufferIndex, value );
+}
+
+void RenderTask::SetClearEnabled( bool enabled )
+{
+  mClearEnabled = enabled;
+}
+
+bool RenderTask::GetClearEnabled() const
+{
+  return mClearEnabled;
+}
+
+void RenderTask::SetCullMode( bool mode )
+{
+  mCullMode = mode;
+}
+
+bool RenderTask::GetCullMode() const
+{
+  return mCullMode;
+}
+
+void RenderTask::SetRefreshRate( unsigned int refreshRate )
+{
+  DALI_LOG_TRACE_METHOD_FMT(gRenderTaskLogFilter, "this:%p RefreshRate:%d\n", this, refreshRate);
+
+  mRefreshRate = refreshRate;
+
+  if( mRefreshRate > 0 )
+  {
+    mState = RENDER_CONTINUOUSLY;
+
+    if( mFrameBufferResourceId )
+    {
+      // Don't need tracking
+      DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
+      if( mCompleteStatusManager != NULL )
+      {
+        mCompleteStatusManager->StopTrackingResource( mFrameBufferResourceId );
+      }
+    }
+  }
+  else
+  {
+    mState = RENDER_ONCE_WAITING_FOR_RESOURCES;
+    mWaitingToRender = true;
+    mNotifyTrigger = false;
+
+    if( mFrameBufferResourceId )
+    {
+      DALI_ASSERT_DEBUG(mCompleteStatusManager && "Ready state tracker is null");
+      if( mCompleteStatusManager != NULL )
+      {
+        mCompleteStatusManager->TrackResource( mFrameBufferResourceId );
+      }
+    }
+  }
+
+  mFrameCounter = 0u;
+}
+
+unsigned int RenderTask::GetRefreshRate() const
+{
+  return mRefreshRate;
+}
+
+bool RenderTask::ReadyToRender( BufferIndex updateBufferIndex )
+{
+  // If the source node of the render task is invisible we should still render
+  // We want the render task to complete and possible clear colors to happen
+
+  // Check source node
+  if ( NULL == mSourceNode ||
+       ( !mSourceNode->IsRoot() && NULL == mSourceNode->GetParent() ) )
+  {
+    TASK_LOG_FMT(Debug::General, " =F  No source actor  FC:%d\n", mFrameCounter );
+
+    // Source node is missing or disconnected
+    return false;
+  }
+
+  // Check camera node
+  if ( NULL == mCameraNode ||
+       NULL == mCameraNode->GetParent() ||
+       !mCameraNode->HasAttachment() )
+  {
+    // Camera node is missing or disconnected
+    TASK_LOG_FMT(Debug::General, " =F  No Camera  FC:%d\n", mFrameCounter );
+
+    return false;
+  }
+
+  TASK_LOG_FMT(Debug::General, " =T (FBO ID:%d) FC:%d\n", mFrameBufferResourceId , mFrameCounter );
+  return true;
+}
+
+bool RenderTask::IsRenderRequired()
+{
+  bool required = false;
+
+  switch( mState )
+  {
+    case RENDER_CONTINUOUSLY:
+      required = (mFrameCounter == 0);
+      break;
+
+    case RENDER_ONCE_WAITING_FOR_RESOURCES:
+      required = true;
+      break;
+
+    default:
+      required = false;
+      break;
+  }
+
+  TASK_LOG_FMT( Debug::General, " State:%s = %s\n", STATE_STRING(mState), required?"T":"F" );
+
+  return required;
+}
+
+void RenderTask::SetResourcesFinished( bool resourcesFinished )
+{
+  mResourcesFinished = resourcesFinished;
+}
+
+// Called every frame regardless of whether render was required.
+// If render was not required, ignore resourcesFinished.
+void RenderTask::UpdateState()
+{
+  TASK_LOG_FMT( Debug::General, "(mResourcesFinished:%s)  FC:%d State:%s RR:%d\n", mResourcesFinished?"T":"F", mFrameCounter, STATE_STRING(mState), mRefreshRate );
+
+  switch( mState )
+  {
+    case RENDER_CONTINUOUSLY:
+    {
+      if( mRefreshRate != Dali::RenderTask::REFRESH_ALWAYS )
+      {
+        if( mFrameCounter == 0 )
+        {
+          if( mResourcesFinished )
+          {
+            ++mFrameCounter; // Only start skipping frames when resources are loaded
+          }
+        }
+        else // Continue counting to skip frames
+        {
+          ++mFrameCounter;
+          if( mFrameCounter >= mRefreshRate )
+          {
+            mFrameCounter = 0;
+          }
+        }
+      }
+      // else do nothing
+    }
+    break;
+
+    case RENDER_ONCE_WAITING_FOR_RESOURCES:
+    {
+      if( mResourcesFinished )
+      {
+        mState = RENDERED_ONCE;
+      }
+    }
+    break;
+
+    case RENDERED_ONCE:
+    {
+      if( mFrameBufferResourceId > 0 )
+      {
+        // Query if the framebuffer is complete:
+        DALI_ASSERT_DEBUG(mCompleteStatusManager && "Complete status tracker is null");
+        if( mCompleteStatusManager != NULL &&
+            CompleteStatusManager::COMPLETE == mCompleteStatusManager->GetStatus( mFrameBufferResourceId ) )
+        {
+          mWaitingToRender = false;
+          mNotifyTrigger = true;
+        }
+        else
+        {
+          mWaitingToRender = true;
+        }
+      }
+      else
+      {
+        mWaitingToRender = false;
+        mNotifyTrigger = true;
+      }
+    }
+    break;
+
+    default:
+      break;
+  }
+
+  TASK_LOG_FMT( Debug::General, " EXIT FC:%d State:%s Notify:%s\n", mFrameCounter, STATE_STRING(mState), mNotifyTrigger?"T":"F");
+}
+
+bool RenderTask::IsWaitingToRender()
+{
+  TASK_LOG_FMT(Debug::Verbose, " State:%s waiting:%s \n", STATE_STRING(mState), mWaitingToRender?"T":"F");
+  return mWaitingToRender;
+}
+
+bool RenderTask::HasRendered()
+{
+  bool notify = false;
+  if( mNotifyTrigger == true )
+  {
+    ++mRenderedOnceCounter;
+    mState = RENDERED_ONCE_AND_NOTIFIED;
+    mNotifyTrigger = false;
+    notify = true;
+  }
+
+  TASK_LOG_FMT(Debug::Verbose, " State:%s hasRendered:%s \n", STATE_STRING(mState), notify?"T":"F");
+  return notify;
+}
+
+unsigned int RenderTask::GetRenderedOnceCounter() const
+{
+  return mRenderedOnceCounter;
+}
+
+
+const Matrix& RenderTask::GetViewMatrix( BufferIndex bufferIndex ) const
+{
+  DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
+
+  return mCameraAttachment->GetViewMatrix( bufferIndex );
+}
+
+SceneGraph::CameraAttachment& RenderTask::GetCameraAttachment() const
+{
+  DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
+  return *mCameraAttachment;
+}
+
+const Matrix& RenderTask::GetProjectionMatrix( BufferIndex bufferIndex ) const
+{
+  DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
+
+  return mCameraAttachment->GetProjectionMatrix( bufferIndex );
+}
+
+void RenderTask::PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( NULL != mCameraAttachment );
+
+  TASK_LOG(Debug::General);
+
+  Viewport viewport;
+  bool viewportSet = QueryViewport( updateBufferIndex, viewport );
+
+  instruction.Reset( mCameraAttachment,
+                     GetFrameBufferId(),
+                     viewportSet ? &viewport : NULL,
+                     mClearEnabled ? &GetClearColor( updateBufferIndex ) : NULL );
+}
+
+bool RenderTask::ViewMatrixUpdated()
+{
+  bool retval = false;
+  if( mCameraAttachment )
+  {
+    retval = mCameraAttachment->ViewMatrixUpdated();
+  }
+  return retval;
+}
+
+void RenderTask::SetCompleteStatusManager(CompleteStatusManager* completeStatusManager)
+{
+  mCompleteStatusManager = completeStatusManager;
+}
+
+void RenderTask::SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
+{
+  mViewportPosition.Set( updateBufferIndex, value );
+}
+
+const Vector2& RenderTask::GetViewportPosition( BufferIndex bufferIndex ) const
+{
+  return mViewportPosition[bufferIndex];
+}
+
+void RenderTask::BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value )
+{
+  mViewportPosition.Bake( updateBufferIndex, value );
+}
+
+void RenderTask::SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
+{
+  mViewportSize.Set( updateBufferIndex, value );
+}
+
+const Vector2& RenderTask::GetViewportSize( BufferIndex bufferIndex ) const
+{
+  return mViewportSize[bufferIndex];
+}
+
+void RenderTask::BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value )
+{
+  mViewportSize.Bake( updateBufferIndex, value );
+}
+
+bool RenderTask::GetViewportEnabled( BufferIndex bufferIndex ) const
+{
+  if(fabsf(mViewportPosition[bufferIndex].x) > Math::MACHINE_EPSILON_1 ||
+     fabsf(mViewportPosition[bufferIndex].y) > Math::MACHINE_EPSILON_1 ||
+     fabsf(mViewportSize[bufferIndex].width) > Math::MACHINE_EPSILON_1 ||
+     fabsf(mViewportSize[bufferIndex].height) > Math::MACHINE_EPSILON_1)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+Node* RenderTask::GetCamera() const
+{
+  return mCameraNode;
+}
+
+void RenderTask::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  // Reset default properties
+  mViewportPosition.ResetToBaseValue( updateBufferIndex );
+  mViewportSize.ResetToBaseValue( updateBufferIndex );
+  mClearColor.ResetToBaseValue( updateBufferIndex );
+}
+
+RenderTask::RenderTask()
+: mViewportPosition( Vector2::ZERO),
+  mViewportSize( Vector2::ZERO),
+  mClearColor( Dali::RenderTask::DEFAULT_CLEAR_COLOR ),
+  mCompleteStatusManager( NULL ),
+  mSourceNode( NULL ),
+  mCameraNode( NULL ),
+  mCameraAttachment( NULL ),
+  mFrameBufferResourceId( 0 ),
+  mResourcesFinished( false ),
+  mWaitingToRender( false ),
+  mNotifyTrigger( false ),
+  mExclusive( Dali::RenderTask::DEFAULT_EXCLUSIVE ),
+  mClearEnabled( Dali::RenderTask::DEFAULT_CLEAR_ENABLED ),
+  mCullMode( Dali::RenderTask::DEFAULT_CULL_MODE ),
+  mRenderTarget( NULL ),
+  mState( (Dali::RenderTask::DEFAULT_REFRESH_RATE == Dali::RenderTask::REFRESH_ALWAYS)
+          ? RENDER_CONTINUOUSLY
+          : RENDER_ONCE_WAITING_FOR_RESOURCES ),
+  mRefreshRate( Dali::RenderTask::DEFAULT_REFRESH_RATE ),
+  mFrameCounter( 0u ),
+  mRenderedOnceCounter( 0u )
+{
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/render-tasks/scene-graph-render-task.h b/dali/internal/update/render-tasks/scene-graph-render-task.h
new file mode 100644 (file)
index 0000000..c1f0796
--- /dev/null
@@ -0,0 +1,504 @@
+#ifndef __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H__
+#define __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/viewport.h>
+#include <dali/public-api/render-tasks/render-task.h>
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/animatable-property.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+class FrameBufferTexture;
+class CompleteStatusManager;
+
+namespace SceneGraph
+{
+class Node;
+class CameraAttachment;
+class RenderInstruction;
+
+/**
+ * RenderTasks describe how the Dali scene should be rendered.
+ */
+class RenderTask : public PropertyOwner
+{
+public:
+  enum State
+  {
+    RENDER_CONTINUOUSLY,               ///< mRefreshRate > 0
+    RENDER_ONCE_WAITING_FOR_RESOURCES, ///< mRefreshRate = REFRESH_ONCE
+    RENDERED_ONCE,                     ///< mRefreshRate = REFRESH_ONCE & rendered
+    RENDERED_ONCE_AND_NOTIFIED         ///< mRefreshRate = REFRESH_ONCE & rendered & notified
+  };
+
+  /**
+   * Create a new RenderTask
+   */
+  static RenderTask* New();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~RenderTask();
+
+  /**
+   * Set the nodes to be rendered.
+   * @param[in] node This node and its children will be rendered.
+   */
+  void SetSourceNode( Node* node );
+
+  /**
+   * Retrieve the source node.
+   * @return This node and its children will be rendered.
+   */
+  Node* GetSourceNode() const;
+
+  /**
+   * Set whether the RenderTask has exclusive access to the source nodes.
+   * @param[in] exclusive True if the source nodes will only be rendered by this render-task.
+   */
+  void SetExclusive( bool exclusive );
+
+  /**
+   * Query whether the RenderTask has exclusive access to the source actors.
+   * @return True if the source actors will only be rendered by this render-task.
+   */
+  bool IsExclusive() const;
+
+  /**
+   * Set the node from which the scene is viewed.
+   * @param[in] node The scene is viewed from the perspective of this node.
+   */
+  void SetCameraNode( Node* node );
+
+  /**
+   * Set the frame-buffer used as a render target.
+   * @param[in] resourceId The resource ID of the frame-buffer, or zero if not rendering off-screen.
+   */
+  void SetFrameBufferId( unsigned int resourceId );
+
+  /**
+   * Retrieve the resource ID of the frame-buffer.
+   * @return The resource ID, or zero if not rendering off-screen.
+   */
+  unsigned int GetFrameBufferId() const;
+
+  /**
+   * Set the value of property viewport-position
+   * This value will persist only for the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The value of the property
+   */
+  void SetViewportPosition( BufferIndex updateBufferIndex, const Vector2& value );
+
+  /**
+   * Get the value of property viewport-position
+   * @warning Should only be called from the Update thread
+   * @param[in] bufferIndex The buffer to read from.
+   * @return the value of the property.
+   */
+  const Vector2& GetViewportPosition( BufferIndex bufferIndex ) const;
+
+  /**
+   * Bake the value of the property viewport-position
+   * This will also set the base value
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The new value for property.
+   */
+  void BakeViewportPosition( BufferIndex updateBufferIndex, const Vector2& value );
+
+  /**
+   * Set the value of property viewport-size
+   * This value will persist only for the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The value of the property
+   */
+  void SetViewportSize( BufferIndex updateBufferIndex, const Vector2& value );
+
+  /**
+   * Get the value of property viewport-size
+   * @warning Should only be called from the Update thread
+   * @param[in] bufferIndex The buffer to read from.
+   * @return the value of the property.
+   */
+  const Vector2& GetViewportSize( BufferIndex bufferIndex ) const;
+
+  /**
+   * Bake the value of the property viewport-size
+   * This will also set the base value
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The new value for property.
+   */
+  void BakeViewportSize( BufferIndex updateBufferIndex, const Vector2& value );
+
+  /**
+   * Get the value of property viewport-enabled
+   * @warning Should only be called from the Update thread
+   * @param[in] bufferIndex The buffer to read from.
+   * @return the value of the property.
+   */
+  bool GetViewportEnabled( BufferIndex bufferIndex ) const;
+
+  /**
+   * Query whether the optional viewport is set.
+   * @param[in] bufferIndex The buffer to read from.
+   * @param[out] viewport The viewport position and size is populated.
+   * @return true if the viewport has been set
+   */
+  bool QueryViewport( BufferIndex bufferIndex, Viewport& viewport ) const;
+
+  /**
+   * Set the value of property clear-color
+   * This value will persist only for the current frame.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The value of the property
+   */
+  void SetClearColor( BufferIndex updateBufferIndex, const Vector4& value );
+
+  /**
+   * Get the value of property clear-color
+   * @warning Should only be called from the Update thread
+   * @param[in] bufferIndex The buffer to read from.
+   * @return the value of the property.
+   */
+  const Vector4& GetClearColor( BufferIndex bufferIndex ) const;
+
+  /**
+   * Bake the value of the property clear-color
+   * This will also set the base value
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] value The new value for property.
+   */
+  void BakeClearColor( BufferIndex updateBufferIndex, const Vector4& value );
+
+  /**
+   * @copydoc Dali::RenderTask::SetClearEnabled()
+   */
+  void SetClearEnabled( bool enabled );
+
+  /**
+   * @copydoc Dali::RenderTask::GetClearEnabled()
+   */
+  bool GetClearEnabled() const;
+
+  /**
+   * @copydoc Dali::RenderTask::SetCullMode()
+   */
+  void SetCullMode( bool mode );
+
+  /**
+   * @copydoc Dali::RenderTask::GetCullMode()
+   */
+  bool GetCullMode() const;
+
+  /**
+   * Set the refresh-rate of the RenderTask.
+   * @param[in] refreshRate The new refresh rate.
+   */
+  void SetRefreshRate( unsigned int refreshRate );
+
+  /**
+   * Retrieve the refresh-rate of the RenderTask.
+   * @return The refresh rate.
+   */
+  unsigned int GetRefreshRate() const;
+
+  /**
+   * Check if the render task is ready for rendering.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return True if the render-task is ready for rendering.
+   */
+  bool ReadyToRender( BufferIndex updateBufferIndex );
+
+  /**
+   * True if a render is required. If the current state is RENDER_CONTINUOUSLY, then
+   * this returns true if the frame count is zero. If the current state is RENDER_ONCE_WAITING_FOR_RESOURCES, then it always returns true. In all other states, it returns false.
+   * @return true if a render is required
+   */
+  bool IsRenderRequired();
+
+  /**
+   * Set whether all resources were available when the render-task was processed
+   * @param[in] resourcesComplete True if the resources of the source tree are completely loaded.
+   */
+  void SetResourcesFinished( bool resourcesFinished );
+
+  /**
+   * Process a frame. This method is called each frame for every ready render task, regardless
+   * of whether it needs to render (so that the frame counter can be updated).
+   */
+  void UpdateState();
+
+  /**
+   * Return true only if currently waiting for the render task to
+   * finish rendering and the update thread should be kept alive.
+   * @return true if waiting to be rendered
+   */
+  bool IsWaitingToRender();
+
+  /**
+   * Return true when the render task has finished rendering and a notification
+   * needs sending. (Only one notification is sent per render once request)
+   * @return true if notification is required.
+   */
+  bool HasRendered();
+
+  /**
+   * @return The number of times we have transited from RENDERED_ONCE to RENDERED_ONCE_AND_NOTIFIED state.
+   */
+  unsigned int GetRenderedOnceCounter() const;
+
+  /**
+   * Retrieve the view-matrix; this is double buffered for input handling.
+   * @pre GetCameraNode() returns a node with valid CameraAttachment.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The view-matrix.
+   */
+  const Matrix& GetViewMatrix( BufferIndex bufferIndex ) const;
+
+  /**
+   * @brief Retrieve the camera attachment.
+   * @pre GetCameraNode() returns a node with valid CameraAttachment.
+   *
+   * @return The camera attachment.
+   */
+  SceneGraph::CameraAttachment& GetCameraAttachment() const;
+
+  /**
+   * Retrieve the projection-matrix; this is double buffered for input handling.
+   * @pre GetCameraNode() returns a node with valid CameraAttachment.
+   * @param[in] bufferIndex The buffer to read from.
+   * @return The projection-matrix.
+   */
+  const Matrix& GetProjectionMatrix( BufferIndex bufferIndex ) const;
+
+  /**
+   * Prepares the render-instruction buffer to be populated with instructions.
+   * @param[out] instruction to prepare
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void PrepareRenderInstruction( RenderInstruction& instruction, BufferIndex updateBufferIndex );
+
+  /**
+   * @return true if the view matrix has been updated during this or last frame
+   */
+  bool ViewMatrixUpdated();
+
+  /**
+   * Set the complete status tracker.
+   * @param[in] completeStatusManager The complete status Tracker (not owned)
+   */
+  void SetCompleteStatusManager( CompleteStatusManager* completeStatusManager );
+
+  /**
+   * @return A pointer to the camera used by the RenderTask
+   */
+  Node* GetCamera() const;
+
+private:
+
+  /**
+   * Protected constructor.
+   */
+  RenderTask();
+
+  // Undefined
+  RenderTask(const RenderTask&);
+
+  // Undefined
+  RenderTask& operator=(const RenderTask&);
+
+private: // PropertyOwner
+
+  virtual void ResetDefaultProperties( BufferIndex currentBufferIndex );
+
+public: // Animatable Properties
+  AnimatableProperty< Vector2 >   mViewportPosition;    ///< viewport-position
+  AnimatableProperty< Vector2 >   mViewportSize;        ///< viewport-size
+  AnimatableProperty< Vector4 >   mClearColor;          ///< clear-color
+
+private:
+  CompleteStatusManager* mCompleteStatusManager;
+  Node* mSourceNode;
+  Node* mCameraNode;
+  CameraAttachment* mCameraAttachment;
+  unsigned int mFrameBufferResourceId;
+
+  bool mResourcesFinished:1; ///< True if all resources were available when the render-task was processed
+  bool mWaitingToRender:1; ///< True when an render once to FBO is waiting
+  bool mNotifyTrigger:1; ///< True if a render once render task has finished renderering
+  bool mExclusive: 1; ///< Whether the render task has exclusive access to the source actor (node in the scene graph implementation).
+  bool mClearEnabled: 1; ///< Whether previous results are cleared.
+  bool mCullMode: 1; ///< Whether renderers should be frustum culled
+
+  FrameBufferTexture* mRenderTarget;
+  Viewport mViewport;
+
+  State mState;                     ///< Render state.
+  unsigned int mRefreshRate;        ///< REFRESH_ONCE, REFRESH_ALWAYS or render every N frames
+  unsigned int mFrameCounter;       ///< counter for rendering every N frames
+
+  unsigned int mRenderedOnceCounter;  ///< Incremented whenever state changes to RENDERED_ONCE_AND_NOTIFIED
+
+};
+
+// Messages for RenderTask
+
+inline void SetFrameBufferIdMessage( EventThreadServices& eventThreadServices, RenderTask& task, unsigned int resourceId )
+{
+  typedef MessageValue1< RenderTask, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetFrameBufferId, resourceId );
+}
+
+inline void SetClearColorMessage( EventThreadServices& eventThreadServices, RenderTask& task, const Vector4& value )
+{
+  typedef MessageDoubleBuffered1< RenderTask, Vector4 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetClearColor, value );
+}
+
+inline void BakeClearColorMessage( EventThreadServices& eventThreadServices, const RenderTask& task, const Vector4& value )
+{
+  typedef MessageDoubleBuffered1< RenderTask, Vector4 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::BakeClearColor, value );
+}
+
+inline void SetClearEnabledMessage( EventThreadServices& eventThreadServices, RenderTask& task, bool enabled )
+{
+  typedef MessageValue1< RenderTask, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetClearEnabled, enabled );
+}
+
+inline void SetCullModeMessage( EventThreadServices& eventThreadServices, RenderTask& task, bool mode )
+{
+  typedef MessageValue1< RenderTask, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetCullMode, mode );
+}
+
+inline void SetRefreshRateMessage( EventThreadServices& eventThreadServices, RenderTask& task, unsigned int refreshRate )
+{
+  typedef MessageValue1< RenderTask, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetRefreshRate, refreshRate );
+}
+
+inline void SetSourceNodeMessage( EventThreadServices& eventThreadServices, RenderTask& task, const Node* constNode )
+{
+  // Scene graph thread can destroy this object.
+  Node* node = const_cast< Node* >( constNode );
+
+  typedef MessageValue1< RenderTask, Node* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetSourceNode, node );
+}
+
+inline void SetCameraNodeMessage( EventThreadServices& eventThreadServices, RenderTask& task, const Node* constNode )
+{
+  // Scene graph thread can destroy this object.
+  Node* node = const_cast< Node* >( constNode );
+
+  typedef MessageValue1< RenderTask, Node* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetCameraNode, node );
+}
+
+inline void SetExclusiveMessage( EventThreadServices& eventThreadServices, RenderTask& task, bool exclusive )
+{
+  typedef MessageValue1< RenderTask, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::SetExclusive, exclusive );
+}
+
+inline void BakeViewportPositionMessage( EventThreadServices& eventThreadServices, const RenderTask& task, const Vector2& value )
+{
+  typedef MessageDoubleBuffered1< RenderTask, Vector2 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::BakeViewportPosition, value );
+}
+
+inline void BakeViewportSizeMessage( EventThreadServices& eventThreadServices, const RenderTask& task, const Vector2& value )
+{
+  typedef MessageDoubleBuffered1< RenderTask, Vector2 > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &task, &RenderTask::BakeViewportSize, value );
+}
+
+} // namespace SceneGraph
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_SCENE_GRAPH_RENDER_TASK_H__
diff --git a/dali/internal/update/rendering/scene-graph-geometry.cpp b/dali/internal/update/rendering/scene-graph-geometry.cpp
new file mode 100644 (file)
index 0000000..59c16e8
--- /dev/null
@@ -0,0 +1,355 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "scene-graph-geometry.h"
+
+// INTERNAL HEADERS
+#include <dali/internal/update/controllers/scene-controller.h>
+#include <dali/internal/render/renderers/render-geometry.h>
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+Geometry::Geometry()
+: mIndexBuffer( NULL ),
+  mRenderGeometry(0),
+  mSceneController(0),
+  mRendererRefCount(0u),
+  mCenter(),
+  mHalfExtents(),
+  mRadius( 0.0f ),
+  mGeometryType(Dali::Geometry::TRIANGLES),
+  mRequiresDepthTest(false)
+{
+
+  // Observe our own PropertyOwner's uniform map
+  AddUniformMapObserver( *this );
+}
+
+Geometry::~Geometry()
+{
+  // @todo Inform renderers of deletion of buffers?
+
+  // could remove self from own uniform map observer, but it's about to be destroyed.
+}
+
+void Geometry::AddVertexBuffer( PropertyBuffer* vertexBuffer )
+{
+  mVertexBuffers.PushBack( vertexBuffer );
+  CalculateExtents( vertexBuffer );
+  vertexBuffer->AddUniformMapObserver(*this);
+  mConnectionObservers.ConnectionsChanged(*this);
+
+  if( mRenderGeometry )
+  {
+    mSceneController->GetRenderMessageDispatcher().AddPropertyBuffer( *mRenderGeometry, vertexBuffer, GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
+  }
+}
+
+void Geometry::RemoveVertexBuffer( PropertyBuffer* vertexBuffer )
+{
+  DALI_ASSERT_DEBUG( NULL != vertexBuffer );
+
+  // Find the object and destroy it
+  Vector<PropertyBuffer*>::Iterator match = std::find(
+    mVertexBuffers.Begin(),
+    mVertexBuffers.End(),
+    vertexBuffer );
+
+  DALI_ASSERT_DEBUG( mVertexBuffers.End() != match );
+  if( mVertexBuffers.End() != match )
+  {
+    vertexBuffer->RemoveUniformMapObserver(*this);
+    mVertexBuffers.Erase( match );
+    mConnectionObservers.ConnectionsChanged(*this);
+
+    if( mRenderGeometry )
+    {
+      mSceneController->GetRenderMessageDispatcher().RemovePropertyBuffer( *mRenderGeometry, vertexBuffer );
+    }
+  }
+}
+
+void Geometry::SetIndexBuffer( PropertyBuffer* indexBuffer )
+{
+  if( mIndexBuffer != indexBuffer )
+  {
+    mIndexBuffer = indexBuffer;
+    indexBuffer->AddUniformMapObserver(*this);
+    mConnectionObservers.ConnectionsChanged(*this);
+
+    if( mRenderGeometry )
+    {
+      mSceneController->GetRenderMessageDispatcher().AddPropertyBuffer( *mRenderGeometry, indexBuffer, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
+    }
+  }
+}
+
+void Geometry::ClearIndexBuffer()
+{
+  if( mIndexBuffer )
+  {
+    mIndexBuffer->RemoveUniformMapObserver(*this);
+
+    if( mRenderGeometry )
+    {
+      mSceneController->GetRenderMessageDispatcher().RemovePropertyBuffer( *mRenderGeometry, mIndexBuffer );
+    }
+  }
+  mIndexBuffer = 0;
+  mConnectionObservers.ConnectionsChanged(*this);
+}
+
+void Geometry::SetGeometryType( BufferIndex bufferIndex, Geometry::GeometryType geometryType )
+{
+  mGeometryType.Set( bufferIndex, geometryType);
+}
+
+Vector<PropertyBuffer*>& Geometry::GetVertexBuffers()
+{
+  return mVertexBuffers;
+}
+
+PropertyBuffer* Geometry::GetIndexBuffer()
+{
+  return mIndexBuffer;
+}
+
+Geometry::GeometryType Geometry::GetGeometryType( BufferIndex bufferIndex) const
+{
+  int geometryType = mGeometryType[ bufferIndex ];
+  return static_cast< GeometryDataProvider::GeometryType > ( geometryType );
+}
+
+bool Geometry::GetRequiresDepthTesting( BufferIndex bufferIndex ) const
+{
+  return mRequiresDepthTest.GetBoolean( bufferIndex );
+}
+
+void Geometry::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  // Reset the animated properties
+  mCenter.ResetToBaseValue( updateBufferIndex );
+  mHalfExtents.ResetToBaseValue( updateBufferIndex );
+  mRadius.ResetToBaseValue( updateBufferIndex );
+
+  // Age the double buffered properties
+  mGeometryType.CopyPrevious(updateBufferIndex);
+  mRequiresDepthTest.CopyPrevious(updateBufferIndex);
+}
+
+void Geometry::CalculateExtents( PropertyBuffer* vertexBuffer )
+{
+  // TODO calculate extents for all vertex buffers attached to geometry
+  unsigned int elementIndex = 0;
+  unsigned int elementCount = vertexBuffer->GetElementCount( 0 );
+  unsigned int elementCount1 = vertexBuffer->GetElementCount( 1 );
+
+  // Select the double buffered element list that is the largest...
+  if ( elementCount < elementCount1 )
+  {
+    elementCount = elementCount1;
+    elementIndex = 1;
+  }
+
+  unsigned int attributeCount = vertexBuffer->GetAttributeCount( elementIndex );
+  unsigned int elementSize = vertexBuffer->GetElementSize( elementIndex );
+
+  std::string posName( "aPos" );
+  std::size_t found;
+
+  float left = 0.0f;
+  float right = 0.0f;
+  float top = 0.0f;
+  float bottom = 0.0f;
+
+  // Find the position attribute index
+  for ( unsigned int i = 0; i < attributeCount; ++i )
+  {
+    found = vertexBuffer->GetAttributeName( 0, i ).find( posName );
+    if ( found != std::string::npos )
+    {
+      unsigned int offset = vertexBuffer->GetAttributeOffset( elementIndex, i );
+      const PropertyBufferDataProvider::BufferType& data = vertexBuffer->GetData( elementIndex );
+
+      // Check attribute type to determine correct position type
+      Property::Type positionType = vertexBuffer->GetAttributeType( elementIndex, i );
+      Vector3 halfExtents;
+      Vector3 center;
+      switch ( positionType )
+      {
+        case Property::VECTOR2:
+        {
+          for ( unsigned int j = 0; j < elementCount; ++j )
+          {
+            const Vector2* position = reinterpret_cast< const Vector2* >( &data[ offset ] );
+            offset += elementSize;
+
+            if ( position->x < left )
+            {
+              left = position->x;
+            }
+            if ( position->x > right )
+            {
+              right = position->x;
+            }
+            if ( position->y < top )
+            {
+              top = position->y;
+            }
+            if ( position->y > bottom )
+            {
+              bottom = position->y;
+            }
+          }
+
+          halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, 0.0f );
+          center = Vector3( halfExtents.x + left , halfExtents.y + top, 0.0f );
+          break;
+        }
+        case Property::VECTOR3:
+        {
+          float near = 0.0f;
+          float far = 0.0f;
+          for ( unsigned int j = 0; j < elementCount; ++j )
+          {
+            const Vector3* position = reinterpret_cast< const Vector3* >( &data[ offset ] );
+            offset += elementSize;
+
+            if ( position->x < left )
+            {
+              left = position->x;
+            }
+            if ( position->x > right )
+            {
+              right = position->x;
+            }
+            if ( position->y < top )
+            {
+              top = position->y;
+            }
+            if ( position->y > bottom )
+            {
+              bottom = position->y;
+            }
+            if ( position->z > far )
+            {
+              far = position->z;
+            }
+            if ( position->z < near )
+            {
+              near = position->z;
+            }
+          }
+          halfExtents = Vector3( ( right - left ) * 0.5f, ( bottom - top ) * 0.5f, ( far - near ) * 0.5f );
+          center = Vector3( halfExtents.x + left , halfExtents.y + top, halfExtents.z + near );
+          break;
+        }
+        default:
+        {
+          break;
+        }
+      }
+      mCenter.Bake( 0, center );
+      mCenter.Bake( 1, center );
+      mHalfExtents.Bake( 0, halfExtents );
+      mHalfExtents.Bake( 1, halfExtents );
+
+      float radius = halfExtents.x;
+      if ( radius < halfExtents.y )
+      {
+        radius = halfExtents.y;
+      }
+      mRadius.SetInitial( radius );
+    }
+  }
+}
+
+void Geometry::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void Geometry::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void Geometry::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Add(observer);
+}
+
+void Geometry::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Remove(observer);
+}
+
+void Geometry::UniformMappingsChanged( const UniformMap& mappings )
+{
+  // Our uniform map, or that of one of the watched children has changed.
+  // Inform connected observers.
+  mConnectionObservers.ConnectedUniformMapChanged();
+}
+
+RenderGeometry* Geometry::GetRenderGeometry(SceneController* sceneController)
+{
+  if(!mRenderGeometry)
+  {
+    //Create RenderGeometry
+    mSceneController = sceneController;
+    mRenderGeometry = new RenderGeometry( *this );
+
+    size_t vertexBufferCount( mVertexBuffers.Size() );
+    for( size_t i(0); i<vertexBufferCount; ++i )
+    {
+      mRenderGeometry->AddPropertyBuffer( mVertexBuffers[i], GpuBuffer::ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
+    }
+
+    if( mIndexBuffer )
+    {
+      mRenderGeometry->AddPropertyBuffer( mIndexBuffer, GpuBuffer::ELEMENT_ARRAY_BUFFER, GpuBuffer::STATIC_DRAW );
+    }
+
+    //Transfer ownership to RenderManager
+    sceneController->GetRenderMessageDispatcher().AddGeometry( *mRenderGeometry );
+  }
+
+  ++mRendererRefCount;
+  return mRenderGeometry;
+}
+
+void Geometry::OnRendererDisconnect()
+{
+  --mRendererRefCount;
+  if( mRendererRefCount == 0 )
+  {
+    //Delete the corresponding RenderGeometry via message to RenderManager
+    mSceneController->GetRenderMessageDispatcher().RemoveGeometry( *mRenderGeometry );
+
+    mRenderGeometry = 0;
+    mSceneController = 0;
+  }
+}
+
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/update/rendering/scene-graph-geometry.h b/dali/internal/update/rendering/scene-graph-geometry.h
new file mode 100644 (file)
index 0000000..5f6d02b
--- /dev/null
@@ -0,0 +1,258 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_H
+#define DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/rendering/geometry.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/property-boolean.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/update/common/scene-graph-connection-change-propagator.h>
+#include <dali/internal/update/common/scene-graph-property-buffer.h>
+#include <dali/internal/render/data-providers/geometry-data-provider.h>
+#include <dali/internal/render/data-providers/render-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class SceneController;
+class RenderGeometry;
+
+/**
+ * This scene graph object is a property owner. It describes a geometry using a
+ * number of PropertyBuffers acting as Vertex buffers.
+ */
+class Geometry : public PropertyOwner, public GeometryDataProvider, public UniformMap::Observer
+{
+public:
+
+  /**
+   * Constructor
+   */
+  Geometry();
+
+  /**
+   * Destructor
+   */
+  virtual ~Geometry();
+
+  /**
+   * Add a property buffer to be used as a vertex buffer
+   */
+  void AddVertexBuffer( PropertyBuffer* vertexBuffer );
+
+  /**
+   * Remove a property buffer to be used as a vertex buffer
+   * @param[in] vertexBuffer the associated vertex buffer to remove
+   */
+  void RemoveVertexBuffer( PropertyBuffer* vertexBuffer );
+
+  /**
+   * Set the buffer to be used as a source of indices for the geometry
+   * @param[in] indexBuffer the Property buffer describing the indexes for Line, Triangle tyes.
+   */
+  void SetIndexBuffer( PropertyBuffer* indexBuffer );
+
+  /**
+   * Clear the index buffer if it is no longer required, e.g. if changing geometry type
+   * to POINTS.
+   */
+  void ClearIndexBuffer();
+
+  /**
+   * Set the type of geometry to draw (Points, Lines, Triangles, etc)
+   * @param[in] bufferIndex Index for double buffered values
+   * @param[in] geometryType The geometry type
+   */
+  void SetGeometryType( BufferIndex bufferIndex, GeometryType geometryType );
+
+  /**
+   * Connect the object to the scene graph
+   *
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * Disconnect the object from the scene graph
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * @copydoc ConnectionObservers::AddObserver
+   */
+  void AddConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+  /**
+   * @copydoc ConnectionObservers::RemoveObserver
+   */
+  void RemoveConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+public: // UniformMap::Observer
+  /**
+   * @copydoc UniformMap::Observer::UniformMappingsChanged
+   */
+  virtual void UniformMappingsChanged( const UniformMap& mappings );
+
+  /**
+   * Get the vertex buffers of the geometry
+   * @return A const reference to the vertex buffers
+   */
+  Vector<PropertyBuffer*>& GetVertexBuffers();
+
+  /**
+   * Get the index buffer of the geometry
+   * @return A pointer to the index buffer if it exists, or NULL if it doesn't.
+   */
+   PropertyBuffer* GetIndexBuffer();
+
+   /**
+    * Gets the associated RenderGeometry
+    * @param[in] sceneController The scene controller
+    * @return The RenderGeometry associated to this Geometry
+    */
+   RenderGeometry* GetRenderGeometry(SceneController* sceneController);
+
+   /**
+    * Called from renderers using this geometry when they get disconnected from the scenegraph
+    */
+   void OnRendererDisconnect();
+
+
+public: // GeometryDataProvider
+  /**
+   * Get the type of geometry to draw
+   * @param[in] bufferIndex Index for double buffered values
+   */
+  virtual GeometryType GetGeometryType( BufferIndex bufferIndex ) const;
+
+  /**
+   * Returns true if this geometry requires depth testing, e.g. if it is
+   * a set of vertices with z != 0
+   * @param[in] bufferIndex Index for double buffered values
+   */
+  virtual bool GetRequiresDepthTesting( BufferIndex bufferIndex ) const;
+
+protected: // From PropertyOwner
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+private:
+
+  /**
+   * @brief Calculate the extents of geometry contained in a vertex buffer.
+   *
+   * @param[in] vertexBuffer pointer to a vertex buffer.
+   */
+  void CalculateExtents( PropertyBuffer* vertexBuffer );
+
+  Vector<PropertyBuffer*> mVertexBuffers; ///< The vertex buffers
+  PropertyBuffer* mIndexBuffer;  ///< The index buffer if required
+  ConnectionChangePropagator mConnectionObservers;
+
+  RenderGeometry*               mRenderGeometry;
+  SceneController*              mSceneController;
+  unsigned int                  mRendererRefCount;
+
+public: // Properties
+  AnimatableProperty<Vector3>   mCenter;
+  AnimatableProperty<Vector3>   mHalfExtents;
+  AnimatableProperty<float>     mRadius;
+  DoubleBufferedProperty<int>   mGeometryType;
+  DoubleBufferedProperty<bool>  mRequiresDepthTest;
+};
+
+inline void AddVertexBufferMessage( EventThreadServices& eventThreadServices , const Geometry& geometry, const PropertyBuffer& vertexBuffer )
+{
+  typedef MessageValue1< Geometry, PropertyBuffer* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &geometry, &Geometry::AddVertexBuffer, const_cast<PropertyBuffer*>(&vertexBuffer) );
+}
+
+inline void RemoveVertexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, const PropertyBuffer& vertexBuffer )
+{
+  typedef MessageValue1< Geometry, PropertyBuffer* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &geometry, &Geometry::RemoveVertexBuffer, const_cast<PropertyBuffer*>(&vertexBuffer) );
+}
+
+inline void SetIndexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, const PropertyBuffer& indexBuffer )
+{
+  typedef MessageValue1< Geometry, PropertyBuffer* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &geometry, &Geometry::SetIndexBuffer, const_cast<PropertyBuffer*>(&indexBuffer) );
+}
+
+inline void ClearIndexBufferMessage( EventThreadServices& eventThreadServices, const Geometry& geometry )
+{
+  typedef Message< Geometry > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &geometry, &Geometry::ClearIndexBuffer );
+}
+
+} // namespace SceneGraph
+
+// Declare enum as a message parameter type
+template <> struct ParameterType< SceneGraph::Geometry::GeometryType > : public BasicType< SceneGraph::Geometry::GeometryType > {};
+
+namespace SceneGraph
+{
+
+inline void SetGeometryTypeMessage( EventThreadServices& eventThreadServices, const Geometry& geometry, SceneGraph::Geometry::GeometryType geometryType )
+{
+  typedef MessageDoubleBuffered1< Geometry, SceneGraph::Geometry::GeometryType > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &geometry, &Geometry::SetGeometryType, geometryType );
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif // DALI_INTERNAL_SCENE_GRAPH_GEOMETRY_H
diff --git a/dali/internal/update/rendering/scene-graph-material.cpp b/dali/internal/update/rendering/scene-graph-material.cpp
new file mode 100644 (file)
index 0000000..021eb9c
--- /dev/null
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "scene-graph-material.h"
+
+// INTERNAL HEADERS
+#include <dali/public-api/actors/blending.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/devel-api/rendering/material.h>
+#include <dali/internal/common/internal-constants.h>
+#include <dali/internal/update/rendering/scene-graph-sampler.h>
+#include <dali/internal/render/data-providers/sampler-data-provider.h>
+#include <dali/internal/render/shaders/scene-graph-shader.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+namespace
+{
+const unsigned int DEFAULT_BLENDING_OPTIONS( BlendingOptions().GetBitmask() );
+}
+
+Material::Material()
+: mColor( Color::WHITE ),
+  mBlendColor( Color::TRANSPARENT ),
+  mFaceCullingMode(Dali::Material::NONE),
+  mBlendingMode(Dali::BlendingMode::AUTO),
+  mBlendingOptions( DEFAULT_BLENDING_OPTIONS ),
+  mShader(NULL),
+  mBlendPolicy(OPAQUE)
+{
+  // Observe own property-owner's uniform map
+  AddUniformMapObserver( *this );
+}
+
+Material::~Material()
+{
+}
+
+void Material::SetShader( Shader* shader )
+{
+  mShader = shader;
+  mShader->AddUniformMapObserver( *this );
+
+  // Inform NewRenderer about this shader: (Will force a re-load of the
+  // shader from the data providers)
+  mConnectionObservers.ConnectionsChanged(*this);
+}
+
+Shader* Material::GetShader() const
+{
+  // @todo - Fix this - move shader setup to the Renderer connect to stage...
+  return mShader;
+}
+
+void Material::AddSampler( Sampler* sampler )
+{
+  mSamplers.PushBack( sampler );
+
+  sampler->AddConnectionObserver( *this );
+  sampler->AddUniformMapObserver( *this );
+
+  mConnectionObservers.ConnectionsChanged(*this);
+}
+
+void Material::RemoveSampler( Sampler* sampler )
+{
+  Vector<Sampler*>::Iterator match = std::find( mSamplers.Begin(), mSamplers.End(), sampler );
+
+  DALI_ASSERT_DEBUG( mSamplers.End() != match );
+  if( mSamplers.End() != match )
+  {
+    sampler->RemoveConnectionObserver( *this );
+    sampler->RemoveUniformMapObserver( *this );
+    mSamplers.Erase( match );
+    mConnectionObservers.ConnectionsChanged(*this);
+  }
+  else
+  {
+    DALI_ASSERT_DEBUG( 0 && "Sampler not found" );
+  }
+}
+
+void Material::PrepareRender( BufferIndex bufferIndex )
+{
+  mBlendPolicy = OPAQUE;
+
+  // @todo MESH_REWORK Add dirty flags to reduce processing.
+
+  switch(mBlendingMode[bufferIndex])
+  {
+    case BlendingMode::OFF:
+    {
+      mBlendPolicy = OPAQUE;
+      break;
+    }
+    case BlendingMode::ON:
+    {
+      mBlendPolicy = TRANSPARENT;
+      break;
+    }
+    case BlendingMode::AUTO:
+    {
+      bool opaque = true;
+
+      //  @todo: MESH_REWORK - Change hints for new SceneGraphShader:
+      // If shader hint OUTPUT_IS_OPAQUE is enabled, set policy to ALWAYS_OPAQUE
+      // If shader hint OUTPUT_IS_TRANSPARENT is enabled, set policy to ALWAYS_TRANSPARENT
+      // else test remainder, and set policy to either ALWAYS_TRANSPARENT or USE_ACTOR_COLOR
+
+      if( mShader->GeometryHintEnabled( Dali::ShaderEffect::HINT_BLENDING ) )
+      {
+        opaque = false;
+      }
+
+      if( opaque )
+      {
+        // Check the material color:
+        opaque = ( mColor[ bufferIndex ].a >= FULLY_OPAQUE );
+      }
+
+      if( opaque )
+      {
+        // Require that all affecting samplers are opaque
+        unsigned int opaqueCount=0;
+        unsigned int affectingCount=0;
+
+        for( Vector<Sampler*>::ConstIterator iter = mSamplers.Begin();
+             iter != mSamplers.End(); ++iter )
+        {
+          const Sampler* sampler = *iter;
+          if( sampler != NULL )
+          {
+            if( sampler->AffectsTransparency( bufferIndex ) )
+            {
+              affectingCount++;
+              if( sampler->IsFullyOpaque( bufferIndex ) )
+              {
+                opaqueCount++;
+              }
+            }
+          }
+        }
+        opaque = (opaqueCount == affectingCount);
+      }
+
+      mBlendPolicy = opaque ? Material::USE_ACTOR_COLOR : Material::TRANSPARENT;
+    }
+  }
+}
+
+Vector<Sampler*>& Material::GetSamplers()
+{
+  return mSamplers;
+}
+
+Material::BlendPolicy Material::GetBlendPolicy() const
+{
+  return mBlendPolicy;
+}
+
+void Material::SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options )
+{
+  mBlendingOptions.Set( updateBufferIndex, options );
+}
+
+const Vector4& Material::GetBlendColor(BufferIndex bufferIndex) const
+{
+  return mBlendColor[bufferIndex];
+}
+
+BlendingFactor::Type Material::GetBlendSrcFactorRgb( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendSrcFactorRgb();
+}
+
+BlendingFactor::Type Material::GetBlendSrcFactorAlpha( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendSrcFactorAlpha();
+}
+
+BlendingFactor::Type Material::GetBlendDestFactorRgb( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendDestFactorRgb();
+}
+
+BlendingFactor::Type Material::GetBlendDestFactorAlpha( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendDestFactorAlpha();
+}
+
+BlendingEquation::Type Material::GetBlendEquationRgb( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendEquationRgb();
+}
+
+BlendingEquation::Type Material::GetBlendEquationAlpha( BufferIndex bufferIndex ) const
+{
+  BlendingOptions blendingOptions;
+  blendingOptions.SetBitmask( mBlendingOptions[ bufferIndex ] );
+  return blendingOptions.GetBlendEquationAlpha();
+}
+
+void Material::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void Material::DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void Material::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Add(observer);
+}
+
+void Material::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Remove(observer);
+}
+
+void Material::UniformMappingsChanged( const UniformMap& mappings )
+{
+  // Our uniform map, or that of one of the watched children has changed.
+  // Inform connected observers.
+  mConnectionObservers.ConnectedUniformMapChanged();
+}
+
+void Material::ConnectionsChanged( PropertyOwner& owner )
+{
+  mConnectionObservers.ConnectionsChanged(*this);
+}
+
+void Material::ConnectedUniformMapChanged( )
+{
+  mConnectionObservers.ConnectedUniformMapChanged();
+}
+
+void Material::ResetDefaultProperties( BufferIndex updateBufferIndex )
+{
+  mColor.ResetToBaseValue( updateBufferIndex );
+  mBlendColor.ResetToBaseValue( updateBufferIndex );
+  mFaceCullingMode.CopyPrevious( updateBufferIndex );
+
+  mBlendingMode.CopyPrevious( updateBufferIndex );
+  mBlendingOptions.CopyPrevious( updateBufferIndex );
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/update/rendering/scene-graph-material.h b/dali/internal/update/rendering/scene-graph-material.h
new file mode 100644 (file)
index 0000000..d6b16e3
--- /dev/null
@@ -0,0 +1,268 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_MATERIAL_H
+#define DALI_INTERNAL_SCENE_GRAPH_MATERIAL_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/internal/common/buffer-index.h>
+#include <dali/internal/common/blending-options.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/animatable-property.h>
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/scene-graph-connection-change-propagator.h>
+#include <dali/internal/update/common/uniform-map.h>
+#include <dali/internal/render/data-providers/material-data-provider.h>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class Sampler;
+class Shader;
+class ConnectionObserver;
+class SceneController;
+
+class Material : public PropertyOwner, public MaterialDataProvider, public UniformMap::Observer, public ConnectionChangePropagator::Observer
+{
+public:
+  /**
+   * This enum defines the outputs of the PrepareRender step, and is used
+   * by the Renderer to determine final opacity.
+   */
+  enum BlendPolicy
+  {
+    OPAQUE,          ///< If the renderer should always be opaque
+    TRANSPARENT,     ///< If the renderer should always be transparent
+    USE_ACTOR_COLOR  ///< If the renderer should determine opacity using the actor color
+  };
+
+  /**
+   * Constructor
+   */
+  Material();
+
+  /**
+   * Destructor
+   */
+  virtual ~Material();
+
+  /**
+   * Set the shader effect for this material
+   * @param[in] shader The shader effect to use
+   */
+  void SetShader( Shader* shader );
+
+  /**
+   * Add a sampler (image + sampler modes) to the material
+   * @param[in] sampler A sampler to add
+   */
+  void AddSampler( Sampler* sampler );
+
+  /**
+   * Remove a sampler (image + sampler modes) from the material
+   * @param[in] sampler A sampler to remove
+   */
+  void RemoveSampler( Sampler* sampler );
+
+  /**
+   * Prepare the material for rendering.
+   *
+   * Determine whether blending is enabled for this material, and store the result.
+   * @param[in] bufferIndex The current buffer index
+   */
+  void PrepareRender( BufferIndex bufferIndex );
+
+  /**
+   * Return the blend policy ( a combination of all the different shader hints, color, samper and image properties ).
+   * This should only be called from the update thread
+   * @return The material's blend policy
+   */
+  BlendPolicy GetBlendPolicy() const;
+
+  /**
+   * Set the blending options. This should only be called from the update thread.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @param[in] options A bitmask of blending options.
+   */
+  void SetBlendingOptions( BufferIndex updateBufferIndex, unsigned int options );
+
+public: // Implementation of MaterialDataProvider
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendColor
+   */
+  virtual const Vector4& GetBlendColor(BufferIndex bufferIndex) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendSrcFactorRgb
+   */
+  virtual BlendingFactor::Type GetBlendSrcFactorRgb(BufferIndex bufferIndex) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendSrcFactorAlpha
+   */
+  virtual BlendingFactor::Type GetBlendSrcFactorAlpha( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendDestFactorRgb
+   */
+  virtual BlendingFactor::Type GetBlendDestFactorRgb( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendDestFactorAlpha
+   */
+  virtual BlendingFactor::Type GetBlendDestFactorAlpha( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendEquationRgb
+   */
+  virtual BlendingEquation::Type GetBlendEquationRgb( BufferIndex bufferIndex ) const;
+
+  /**
+   * @copydoc MaterialDataProvider::GetBlendEquationAlpha
+   */
+  virtual BlendingEquation::Type GetBlendEquationAlpha( BufferIndex bufferIndex ) const;
+
+public: // Implementation of ObjectOwnerContainer template methods
+  /**
+   * Connect the object to the scene graph
+   *
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * Disconnect the object from the scene graph
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+public: // Implementation of ConnectionChangePropagator
+  /**
+   * @copydoc ConnectionChangePropagator::AddObserver
+   */
+  void AddConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+  /**
+   * @copydoc ConnectionChangePropagator::RemoveObserver
+   */
+  void RemoveConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+public:
+  /**
+   * Get the shader effect of this material
+   * @return the shader effect;
+   */
+  Shader* GetShader() const;
+
+  /**
+   * Get the samplers this material uses.
+   * @return the samplers
+   */
+  Vector<Sampler*>& GetSamplers();
+
+public: // UniformMap::Observer
+  /**
+   * @copydoc UniformMap::Observer::UniformMappingsChanged
+   */
+  virtual void UniformMappingsChanged( const UniformMap& mappings );
+
+public: // ConnectionChangePropagator::Observer
+
+  /**
+   * @copydoc ConnectionChangePropagator::ConnectionsChanged
+   */
+  virtual void ConnectionsChanged( PropertyOwner& owner );
+
+  /**
+   * @copydoc ConnectionChangePropagator::ConnectedUniformMapChanged
+   */
+  virtual void ConnectedUniformMapChanged( );
+
+public: // PropertyOwner implementation
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+public: // Property data
+  AnimatableProperty<Vector4> mColor;
+  AnimatableProperty<Vector4> mBlendColor;
+  DoubleBufferedProperty<int> mFaceCullingMode;
+  DoubleBufferedProperty<int> mBlendingMode;
+  DoubleBufferedProperty<int> mBlendingOptions;
+
+private:
+  Shader* mShader;
+  Vector<Sampler*> mSamplers; // Not owned
+  ConnectionChangePropagator mConnectionObservers;
+  BlendPolicy mBlendPolicy; ///< The blend policy as determined by PrepareRender
+};
+
+inline void SetShaderMessage( EventThreadServices& eventThreadServices, const Material& material, const Shader& shader )
+{
+  typedef MessageValue1< Material, Shader* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &material, &Material::SetShader, const_cast<Shader*>(&shader) );
+}
+
+inline void AddSamplerMessage( EventThreadServices& eventThreadServices, const Material& material, const Sampler& sampler )
+{
+  typedef MessageValue1< Material, Sampler* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &material, &Material::AddSampler, const_cast<Sampler*>(&sampler) );
+}
+
+inline void RemoveSamplerMessage( EventThreadServices& eventThreadServices, const Material& material, Sampler& sampler )
+{
+  typedef MessageValue1< Material, Sampler* > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &material, &Material::RemoveSampler, const_cast<Sampler*>(&sampler) );
+}
+
+inline void SetBlendingOptionsMessage( EventThreadServices& eventThreadServices, const Material& material, unsigned int options )
+{
+  typedef MessageDoubleBuffered1< Material, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  new (slot) LocalType( &material, &Material::SetBlendingOptions, options );
+}
+
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
+
+#endif //  DALI_INTERNAL_SCENE_GRAPH_MATERIAL_H
diff --git a/dali/internal/update/rendering/scene-graph-sampler.cpp b/dali/internal/update/rendering/scene-graph-sampler.cpp
new file mode 100644 (file)
index 0000000..4c99c8d
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include "scene-graph-sampler.h"
+
+// EXTERNAL HEADERS
+
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+
+Sampler::Sampler( const std::string& textureUnitUniformName )
+: mMinFilter( Dali::Sampler::DEFAULT ),
+  mMagFilter( Dali::Sampler::DEFAULT ),
+  mUWrapMode( Dali::Sampler::CLAMP_TO_EDGE ),
+  mVWrapMode( Dali::Sampler::CLAMP_TO_EDGE ),
+  mAffectsTransparency( true ),
+  mTextureUnitUniformName( textureUnitUniformName ),
+  mFullyOpaque(true)
+{
+  mTextureId[ 0 ] = mTextureId[ 1 ] = 0u;
+}
+
+Sampler::~Sampler()
+{
+}
+
+void Sampler::SetTextureUnitUniformName( const std::string& textureUnitUniformName )
+{
+  mTextureUnitUniformName = textureUnitUniformName;
+}
+
+void Sampler::SetTexture( BufferIndex bufferIndex, Integration::ResourceId textureId )
+{
+  if( mTextureId[bufferIndex] != textureId )
+  {
+    mTextureId[ bufferIndex ] = textureId;
+    mConnectionObservers.ConnectionsChanged(*this);
+  }
+}
+
+void Sampler::SetFilterMode( BufferIndex bufferIndex, FilterMode minFilter, FilterMode magFilter )
+{
+  mMinFilter.Set(bufferIndex, minFilter);
+  mMagFilter.Set(bufferIndex, magFilter);
+}
+
+void Sampler::SetWrapMode( BufferIndex bufferIndex, WrapMode uWrap, WrapMode vWrap )
+{
+}
+
+const std::string& Sampler::GetTextureUnitUniformName() const
+{
+  return mTextureUnitUniformName;
+}
+
+Integration::ResourceId Sampler::GetTextureId( BufferIndex bufferIndex ) const
+{
+  return mTextureId[bufferIndex];
+}
+
+Sampler::FilterMode Sampler::GetMinifyFilterMode( BufferIndex bufferIndex ) const
+{
+  return static_cast<Sampler::FilterMode>(mMinFilter[bufferIndex]);
+}
+
+Sampler::FilterMode Sampler::GetMagnifyFilterMode( BufferIndex bufferIndex ) const
+{
+  return static_cast<Sampler::FilterMode>(mMagFilter[bufferIndex]);
+}
+
+Sampler::WrapMode Sampler::GetUWrapMode( BufferIndex bufferIndex ) const
+{
+  return static_cast<Sampler::WrapMode>(mUWrapMode[bufferIndex]);
+}
+
+Sampler::WrapMode Sampler::GetVWrapMode( BufferIndex bufferIndex ) const
+{
+  return static_cast<Sampler::WrapMode>(mVWrapMode[bufferIndex]);
+}
+
+bool Sampler::AffectsTransparency( BufferIndex bufferIndex ) const
+{
+  return mAffectsTransparency[bufferIndex] ;
+}
+
+void Sampler::SetFullyOpaque( bool fullyOpaque )
+{
+  mFullyOpaque = fullyOpaque;
+}
+
+bool Sampler::IsFullyOpaque( BufferIndex bufferIndex ) const
+{
+  return mFullyOpaque;
+}
+
+void Sampler::ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex )
+{
+}
+
+void Sampler::DisconnectFromSceneGraph(SceneController& sceneController, BufferIndex bufferIndex)
+{
+}
+
+void Sampler::AddConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Add(observer);
+}
+
+void Sampler::RemoveConnectionObserver( ConnectionChangePropagator::Observer& observer )
+{
+  mConnectionObservers.Remove(observer);
+}
+
+void Sampler::ResetDefaultProperties( BufferIndex bufferIndex )
+{
+  mTextureId[ bufferIndex ] = mTextureId[ 1 - bufferIndex ];
+  mMinFilter.CopyPrevious( bufferIndex );
+  mMagFilter.CopyPrevious( bufferIndex );
+  mUWrapMode.CopyPrevious( bufferIndex );
+  mVWrapMode.CopyPrevious( bufferIndex );
+  mAffectsTransparency.CopyPrevious( bufferIndex );
+}
+
+} // namespace SceneGraph
+} // namespace Internal
+} // namespace Dali
diff --git a/dali/internal/update/rendering/scene-graph-sampler.h b/dali/internal/update/rendering/scene-graph-sampler.h
new file mode 100644 (file)
index 0000000..f3d0cd7
--- /dev/null
@@ -0,0 +1,250 @@
+#ifndef DALI_INTERNAL_SCENE_GRAPH_SAMPLER_H
+#define DALI_INTERNAL_SCENE_GRAPH_SAMPLER_H
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dali/devel-api/rendering/sampler.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/update/common/double-buffered.h>
+#include <dali/internal/update/common/double-buffered-property.h>
+#include <dali/internal/update/common/property-owner.h>
+#include <dali/internal/update/common/scene-graph-connection-change-propagator.h>
+#include <dali/internal/update/resources/bitmap-metadata.h>
+#include <dali/internal/render/data-providers/sampler-data-provider.h>
+
+#include <string>
+
+namespace Dali
+{
+namespace Internal
+{
+namespace SceneGraph
+{
+class SceneController;
+
+class Sampler : public PropertyOwner, public SamplerDataProvider
+{
+public:
+  typedef Dali::Sampler::FilterMode FilterMode;
+  typedef Dali::Sampler::WrapMode   WrapMode;
+
+  /**
+   * Constructor
+   */
+  Sampler( const std::string& samplerName );
+
+  /**
+   * Destructor
+   */
+  virtual ~Sampler();
+
+  /**
+   * Set the uniform name of this sampler. This allows the shader to find the
+   * GL index of this sampler.
+   */
+  void SetTextureUnitUniformName( const std::string& textureUnitUniformName );
+
+  /**
+   * Set the texture identity of this sampler (needs to double buffer this value because
+   * it can be read through the data provider interface in the render thread )
+   * @param[in] bufferIndex The buffer index to use
+   * @param[in] textureId The identity of the texture
+   */
+  void SetTexture( BufferIndex bufferIndex, Integration::ResourceId textureId );
+
+  /**
+   * Set the filter modes for minify and magnify filters
+   * @param[in] bufferIndex The buffer index to use
+   * @param[in] minFilter The minify filter
+   * @param[in] magFilter The magnify filter
+   */
+  void SetFilterMode( BufferIndex bufferIndex, FilterMode minFilter, FilterMode magFilter );
+
+  /**
+   * @param[in] bufferIndex The buffer index to use
+   */
+  void SetWrapMode( BufferIndex bufferIndex, WrapMode uWrap, WrapMode vWrap );
+
+  /**
+   * @param[in] bufferIndex The buffer index to use
+   * @return true if this sampler affects transparency of the material
+   * @note this should only be called from Update thread
+   */
+  bool AffectsTransparency( BufferIndex bufferIndex ) const;
+
+  /**
+   * Sets whether the associated texture is fully opaque or not.
+   * @param[in] fullyOpaque true if it's fully opaque
+   */
+  void SetFullyOpaque( bool fullyOpaque );
+
+  /**
+   * @param[in] bufferIndex The buffer index to use
+   * @return true if the texture is fully opaque
+   * @note this should only be called from Update thread
+   */
+  bool IsFullyOpaque( BufferIndex bufferIndex ) const;
+
+
+public: // SamplerDataProvider interface - called from RenderThread
+  /**
+   * Get the texture unit uniform name
+   * @return the name of the texture unit uniform
+   */
+  virtual const std::string& GetTextureUnitUniformName() const;
+
+  /**
+   * Get the texture ID
+   * @param[in] bufferIndex The buffer index to use
+   * @return the identity of the associated texture
+   */
+  virtual Integration::ResourceId GetTextureId(BufferIndex buffer) const;
+
+  /**
+   * Get the filter mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The minify filter mode
+   */
+  virtual FilterMode GetMinifyFilterMode( BufferIndex bufferIndex ) const;
+
+  /**
+   * Get the filter mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The magnify filter mode
+   */
+  virtual FilterMode GetMagnifyFilterMode( BufferIndex bufferIndex ) const;
+
+  /**
+   * Get the horizontal wrap mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The horizontal wrap mode
+   */
+  virtual WrapMode GetUWrapMode( BufferIndex bufferIndex ) const;
+
+  /**
+   * Get the vertical wrap mode
+   * @param[in] bufferIndex The buffer index to use
+   * @return The vertical wrap mode
+   */
+  virtual WrapMode GetVWrapMode( BufferIndex bufferIndex ) const;
+
+  /**
+   * Connect the object to the scene graph
+   *
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void ConnectToSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * Disconnect the object from the scene graph
+   * @param[in] sceneController The scene controller - used for sending messages to render thread
+   * @param[in] bufferIndex The current buffer index - used for sending messages to render thread
+   */
+  void DisconnectFromSceneGraph( SceneController& sceneController, BufferIndex bufferIndex );
+
+  /**
+   * @copydoc ConnectionChangePropagator::AddObserver
+   */
+  void AddConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+  /**
+   * @copydoc ConnectionChangePropagator::RemoveObserver
+   */
+  void RemoveConnectionObserver(ConnectionChangePropagator::Observer& observer);
+
+public: // PropertyOwner implementation
+  /**
+   * @copydoc Dali::Internal::SceneGraph::PropertyOwner::ResetDefaultProperties()
+   */
+  virtual void ResetDefaultProperties( BufferIndex updateBufferIndex );
+
+public: // Properties
+  DoubleBufferedProperty<int>  mMinFilter;    ///< The minify filter
+  DoubleBufferedProperty<int>  mMagFilter;    ///< The magnify filter
+  DoubleBufferedProperty<int>  mUWrapMode;    ///< The horizontal wrap mode
+  DoubleBufferedProperty<int>  mVWrapMode;    ///< The vertical wrap mode
+  DoubleBufferedProperty<bool> mAffectsTransparency; ///< If this sampler affects renderer transparency
+
+private:
+  std::string mTextureUnitUniformName; ///< The name of the uniform of the texture unit
+  Integration::ResourceId mTextureId[ 2 ]; //< double buffered
+  ConnectionChangePropagator mConnectionObservers; ///< Connection observers that will be informed when textures change.
+  bool mFullyOpaque; // Update only flag - no need for double buffering
+};
+
+} // namespace SceneGraph
+
+inline void SetTextureUnitUniformNameMessage( EventThreadServices& eventThreadServices, const SceneGraph::Sampler& sampler, const std::string& name )
+{
+  typedef MessageValue1< SceneGraph::Sampler, std::string > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &sampler, &SceneGraph::Sampler::SetTextureUnitUniformName, name );
+}
+
+
+inline void SetTextureMessage( EventThreadServices& eventThreadServices, const SceneGraph::Sampler& sampler, unsigned int resourceId )
+{
+  typedef MessageDoubleBuffered1< SceneGraph::Sampler, unsigned int > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &sampler, &SceneGraph::Sampler::SetTexture, resourceId );
+}
+
+// Declare enum as a message parameter type outside the SceneGraph namespace
+template <> struct ParameterType< SceneGraph::Sampler::FilterMode > : public BasicType< SceneGraph::Sampler::FilterMode > {};
+
+
+inline void SetFilterModeMessage( EventThreadServices& eventThreadServices, const SceneGraph::Sampler& sampler, SceneGraph::Sampler::FilterMode minFilter, SceneGraph::Sampler::FilterMode magFilter )
+{
+  typedef MessageDoubleBuffered2< SceneGraph::Sampler, SceneGraph::Sampler::FilterMode, SceneGraph::Sampler::FilterMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &sampler, &SceneGraph::Sampler::SetFilterMode, minFilter, magFilter );
+}
+
+// Declare enum as a message parameter type
+template <> struct ParameterType< SceneGraph::Sampler::WrapMode > : public BasicType< SceneGraph::Sampler::WrapMode > {};
+
+
+inline void SetWrapModeMessage( EventThreadServices& eventThreadServices, const SceneGraph::Sampler& sampler, SceneGraph::Sampler::WrapMode horizontalWrap, SceneGraph::Sampler::WrapMode verticalWrap )
+{
+  typedef MessageDoubleBuffered2< SceneGraph::Sampler, SceneGraph::Sampler::WrapMode, SceneGraph::Sampler::WrapMode > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &sampler, &SceneGraph::Sampler::SetWrapMode, horizontalWrap, verticalWrap );
+}
+
+} // namespace Internal
+} // namespace Dali
+
+
+#endif //  DALI_INTERNAL_SCENE_GRAPH_SAMPLER_H
diff --git a/dali/internal/update/resources/bitmap-metadata.cpp b/dali/internal/update/resources/bitmap-metadata.cpp
new file mode 100644 (file)
index 0000000..3fce21d
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/resources/bitmap-metadata.h>
+
+// EXTERNAL INCLUDES
+#include <math.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+BitmapMetadata BitmapMetadata::New(NativeImageInterfacePtr nativeImage)
+{
+  return BitmapMetadata(nativeImage->GetWidth(), nativeImage->GetHeight(), nativeImage->RequiresBlending(), ! nativeImage->RequiresBlending());
+}
+
+BitmapMetadata BitmapMetadata::New(Integration::Bitmap* const bitmap)
+{
+  return BitmapMetadata(bitmap->GetImageWidth(), bitmap->GetImageHeight(), Pixel::HasAlpha(bitmap->GetPixelFormat()), bitmap->IsFullyOpaque());
+}
+
+
+BitmapMetadata BitmapMetadata::New(unsigned int width,
+                                   unsigned int height,
+                                   bool hasAlphaChannel)
+{
+  return BitmapMetadata(width, height, hasAlphaChannel, !hasAlphaChannel );
+}
+
+
+BitmapMetadata::BitmapMetadata( unsigned int width,
+                                unsigned int height,
+                                bool hasAlphaChanne,
+                                bool opaqueness )
+: mImageWidth(width),
+  mImageHeight(height),
+  mHasAlphaChannel(hasAlphaChanne),
+  mOpaqueness(opaqueness),
+  mIsNativeImage(false),
+  mIsFramebuffer(false)
+{
+}
+
+BitmapMetadata::BitmapMetadata( )
+: mImageWidth(0),
+  mImageHeight(0),
+  mHasAlphaChannel(true),
+  mOpaqueness(false),
+  mIsNativeImage(false),
+  mIsFramebuffer(false)
+{
+}
+
+BitmapMetadata::BitmapMetadata( const BitmapMetadata& rhs )
+: mImageWidth(rhs.mImageWidth),
+  mImageHeight(rhs.mImageHeight),
+  mHasAlphaChannel(rhs.mHasAlphaChannel),
+  mOpaqueness(rhs.mOpaqueness),
+  mIsNativeImage(rhs.mIsNativeImage),
+  mIsFramebuffer(rhs.mIsFramebuffer)
+{
+}
+
+BitmapMetadata& BitmapMetadata::operator=( const BitmapMetadata& rhs )
+{
+  mImageWidth = rhs.mImageWidth;
+  mImageHeight =rhs.mImageHeight;
+  mHasAlphaChannel = rhs.mHasAlphaChannel;
+  mOpaqueness = rhs.mOpaqueness;
+  mIsNativeImage = rhs.mIsNativeImage;
+  mIsFramebuffer = rhs.mIsFramebuffer;
+  return *this;
+}
+
+void BitmapMetadata::Update(NativeImageInterfacePtr nativeImage)
+{
+  mImageWidth  = nativeImage->GetWidth();
+  mImageHeight = nativeImage->GetHeight();
+  mHasAlphaChannel = nativeImage->RequiresBlending();
+  mOpaqueness  = ! mHasAlphaChannel;
+  mIsNativeImage = true;
+}
+
+void BitmapMetadata::Update(Integration::Bitmap* const bitmap)
+{
+  mImageWidth  = bitmap->GetImageWidth();
+  mImageHeight = bitmap->GetImageHeight();
+  mHasAlphaChannel = Pixel::HasAlpha(bitmap->GetPixelFormat());
+  mOpaqueness  = bitmap->IsFullyOpaque();
+  mIsNativeImage = false;
+}
+
+unsigned int BitmapMetadata::GetWidth() const
+{
+  return mImageWidth;
+}
+
+unsigned int BitmapMetadata::GetHeight() const
+{
+  return mImageHeight;
+}
+
+bool BitmapMetadata::HasAlphaChannel() const
+{
+  return mHasAlphaChannel;
+}
+
+bool BitmapMetadata::IsFullyOpaque() const
+{
+  return mOpaqueness;
+}
+
+void BitmapMetadata::SetWidth(unsigned int width)
+{
+  mImageWidth = width;
+}
+
+void BitmapMetadata::SetHeight(unsigned int height)
+{
+  mImageHeight = height;
+}
+
+void BitmapMetadata::SetHasAlphaChannel( bool hasAlphaChannel )
+{
+  mHasAlphaChannel = hasAlphaChannel;
+}
+
+void BitmapMetadata::SetOpaqueness(bool opaqueness)
+{
+  mOpaqueness = opaqueness;
+}
+
+void BitmapMetadata::SetIsNativeImage( bool isNativeImage )
+{
+  mIsNativeImage = isNativeImage;
+}
+
+bool BitmapMetadata::GetIsNativeImage()
+{
+  return mIsNativeImage;
+}
+
+void BitmapMetadata::SetIsFramebuffer( bool isFramebuffer )
+{
+  mIsFramebuffer = isFramebuffer;
+}
+
+bool BitmapMetadata::GetIsFramebuffer()
+{
+  return mIsFramebuffer;
+}
+
+
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/resources/bitmap-metadata.h b/dali/internal/update/resources/bitmap-metadata.h
new file mode 100644 (file)
index 0000000..13bd699
--- /dev/null
@@ -0,0 +1,156 @@
+#ifndef __DALI_BITMAP_METADATA_H__
+#define  __DALI_BITMAP_METADATA_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/bitmap.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/images/native-image-interface.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+/**
+ * Texture class.
+ */
+class BitmapMetadata
+{
+public:
+  /**
+   * Creates a BitmapMetadata object from a native image (eg.: EGLImage).
+   * @param[in] nativeImage The native image to load
+   * @return A newly allocated BitmapMetadata
+   */
+  static BitmapMetadata New(NativeImageInterfacePtr nativeImage);
+
+  /**
+   * Creates a new BitmapMetadata object from a Bitmap
+   * @param[in] bitmap The bitmap
+   * @return A newly allocated BitmapMetadata
+   */
+  static BitmapMetadata New(Integration::Bitmap* const bitmap);
+
+  /**
+   * Creates a new BitmapMetadata object from framebuffer metadata
+   * @return A newly allocated BitmapMetadata
+   */
+  static BitmapMetadata New(unsigned int width, unsigned int height, bool hasAlphaChannel);
+
+  /**
+   * Constructor
+   */
+  BitmapMetadata( unsigned int width, unsigned int height, bool hasAlphaChanne, bool opaqueness );
+
+  /**
+   * Copy constructor
+   */
+  BitmapMetadata( const BitmapMetadata& rhs );
+
+  /**
+   * Assignment operator
+   */
+  BitmapMetadata& operator=( const BitmapMetadata& rhs );
+
+  /**
+   * Default Constructor
+   */
+  BitmapMetadata();
+
+  /**
+   * Updates the metadata with information from the native image
+   * @param[in] nativeImage The native image that was updated
+   */
+  void Update(NativeImageInterfacePtr nativeImage);
+
+  /**
+   * Updates the metadata with information from the bitmap
+   * @param[in] bitmap The bitmap that was updated
+   */
+  void Update(Integration::Bitmap* const bitmap);
+
+  /**
+   * Return the width of image in pixels.
+   * @return width
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * Return the height of image in pixels.
+   * @return height
+   */
+  unsigned int GetHeight() const;
+
+  /**
+   * Query whether the texture data has an alpha channel.
+   * @return True if the texture data has an alpha channel.
+   */
+  bool HasAlphaChannel() const;
+
+  /**
+   * Query whether the texture is completely opaque
+   * @return True if all pixels of the texture data are opaque
+   */
+  bool IsFullyOpaque() const;
+
+  /**
+   * Set the width of image
+   * @param[in] width The width of the image
+   */
+  void SetWidth(unsigned int width);
+
+  /**
+   * Set the height of image
+   * @param[in] height The height of the image in pixels
+   */
+  void SetHeight(unsigned int height);
+
+  /**
+   * Set whether the texture has alpha channel
+   * @param[in] hasAlphaChannel whether the texture has alpha channel
+   */
+  void SetHasAlphaChannel( bool hasAlphaChannel );
+
+  /**
+   * Set whether the texture is completely opaque, i.e.
+   * true if all pixels of the texture data are opaque.
+   * @param[in] opaqueness If the alpha channel is set to fully opaque.
+   */
+  void SetOpaqueness(bool opaqueness);
+
+  void SetIsNativeImage( bool isNativeImage );
+  bool GetIsNativeImage( );
+  void SetIsFramebuffer( bool isFramebuffer );
+  bool GetIsFramebuffer( );
+
+private:
+  unsigned int  mImageWidth;      ///< width of the original image
+  unsigned int  mImageHeight;     ///< height of the original image
+  bool          mHasAlphaChannel:1; ///< Pixel format of the contained image data.
+  bool          mOpaqueness:1;    ///< Whether the bitmap was fully opaque when loaded / updated
+  bool          mIsNativeImage:1; ///< Whether the image is native or not
+  bool          mIsFramebuffer:1; ///< Whether the image is an FBO
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_BITMAP_METADATA_H__
diff --git a/dali/internal/update/resources/complete-status-manager-debug.h b/dali/internal/update/resources/complete-status-manager-debug.h
new file mode 100644 (file)
index 0000000..3cb0fb5
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __DALI_INTERNAL_UPDATE_COMPLETE_STATUS_MANAGER_DEBUG_H__
+#define __DALI_INTERNAL_UPDATE_COMPLETE_STATUS_MANAGER_DEBUG_H__
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+namespace Dali
+{
+namespace Internal
+{
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gCompleteStatusLogFilter = Debug::Filter::New(Debug::Concise, false, "LOG_COMPLETE_STATUS_MANAGER");
+#define TRACKER_LOG(level)                                              \
+  DALI_LOG_INFO(gCompleteStatusLogFilter, level, "CompleteStatusManager::%s: this:%p\n", __FUNCTION__, this)
+#define TRACKER_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gCompleteStatusLogFilter, level, "CompleteStatusManager::%s: this:%p " format, __FUNCTION__, this, ## args)
+#else
+#define TRACKER_LOG(level)
+#define TRACKER_LOG_FMT(level, format, args...)
+#endif
+
+}//Internal
+}//Dali
+
+#endif // __DALI_INTERNAL_UPDATE_COMPLETE_STATUS_MANAGER_DEBUG_H__
diff --git a/dali/internal/update/resources/complete-status-manager.cpp b/dali/internal/update/resources/complete-status-manager.cpp
new file mode 100644 (file)
index 0000000..2a4079a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/resources/complete-status-manager.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/gl-sync-abstraction.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/update/resources/resource-manager.h>
+#include <dali/internal/update/resources/resource-tracker.h>
+#include <dali/internal/update/resources/sync-resource-tracker.h>
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/update/resources/complete-status-manager-debug.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+CompleteStatusManager::CompleteStatusManager( Integration::GlSyncAbstraction& glSyncAbstraction,
+                                              SceneGraph::RenderMessageDispatcher& renderMessageDispatcher,
+                                              ResourceManager& resourceManager )
+: mGlSyncAbstraction(glSyncAbstraction),
+  mRenderMessageDispatcher(renderMessageDispatcher),
+  mResourceManager(resourceManager)
+{
+  TRACKER_LOG(Debug::Verbose);
+}
+
+CompleteStatusManager::~CompleteStatusManager()
+{
+  // Delete all extant resource trackers
+  CompleteStatusManager::TrackedResourcesIter iter = mTrackedResources.begin();
+  CompleteStatusManager::TrackedResourcesIter end = mTrackedResources.end();
+  while( iter != end )
+  {
+    delete iter->second;
+    ++iter;
+  }
+
+  TRACKER_LOG(Debug::Verbose);
+}
+
+void CompleteStatusManager::TrackResource( Integration::ResourceId id )
+{
+  TRACKER_LOG_FMT( Debug::General, "id:%d\n", id );
+
+  CompleteStatusManager::TrackedResourcesIter iter = mTrackedResources.find(id);
+  if( iter == mTrackedResources.end() )
+  {
+    // Create new tracker for ID
+    ResourceTracker* resourceTracker = CreateResourceTracker( id );
+    resourceTracker->Initialize();
+    mTrackedResources[id] = resourceTracker;
+  }
+  else
+  {
+    // We've found existing tracker. Reset it
+    iter->second->Reset();
+  }
+}
+
+void CompleteStatusManager::StopTrackingResource( Integration::ResourceId id )
+{
+  TRACKER_LOG_FMT( Debug::General, "id:%d\n", id );
+
+  CompleteStatusManager::TrackedResourcesIter iter = mTrackedResources.find(id);
+  if( iter != mTrackedResources.end() )
+  {
+    iter->second->OnDestroy();
+    delete iter->second;
+    mTrackedResources.erase(iter);
+  }
+}
+
+ResourceTracker* CompleteStatusManager::FindResourceTracker( Integration::ResourceId id )
+{
+  ResourceTracker* tracker = NULL;
+
+  TrackedResourcesIter iter = mTrackedResources.find(id);
+  if( iter != mTrackedResources.end() )
+  {
+    tracker = iter->second;
+  }
+
+  TRACKER_LOG_FMT(Debug::General, "id:%d = tracker:%p\n", id, tracker);
+  return tracker;
+}
+
+CompleteStatusManager::CompleteState CompleteStatusManager::GetStatus( Integration::ResourceId id )
+{
+  CompleteState readiness = CompleteStatusManager::NOT_READY;
+
+  if( 0 != id )
+  {
+    TrackedResourcesIter iter = mTrackedResources.find(id);
+    if( iter != mTrackedResources.end() )
+    {
+      if( iter->second->IsComplete() )
+      {
+        readiness = CompleteStatusManager::COMPLETE;
+      }
+    }
+    else if( mResourceManager.IsResourceLoaded(id) )
+    {
+      readiness = CompleteStatusManager::COMPLETE;
+    }
+    else if( mResourceManager.IsResourceLoadFailed(id) )
+    {
+      readiness = CompleteStatusManager::NEVER;
+    }
+  }
+  else
+  {
+    // Loading is essentially finished if we don't have a resource ID
+    readiness = CompleteStatusManager::COMPLETE;
+  }
+
+  TRACKER_LOG_FMT(Debug::General, "id:%d = %s\n", id, (readiness==CompleteStatusManager::COMPLETE)?"COMPLETE":((readiness==CompleteStatusManager::NEVER)?"NEVER":"NOT_READY"));
+
+  return readiness;
+}
+
+ResourceTracker* CompleteStatusManager::CreateResourceTracker( Integration::ResourceId id )
+{
+  ResourceTracker* resourceTracker = NULL;
+  BitmapMetadata bitmapMetadata = mResourceManager.GetBitmapMetadata( id );
+  if( bitmapMetadata.GetIsNativeImage() && bitmapMetadata.GetIsFramebuffer()  )
+  {
+    resourceTracker = new SyncResourceTracker( mGlSyncAbstraction, mRenderMessageDispatcher );
+  }
+  else
+  {
+    resourceTracker = new ResourceTracker();
+  }
+  return resourceTracker;
+}
+
+} // Internal
+} // Dali
diff --git a/dali/internal/update/resources/complete-status-manager.h b/dali/internal/update/resources/complete-status-manager.h
new file mode 100644 (file)
index 0000000..de384ae
--- /dev/null
@@ -0,0 +1,136 @@
+#ifndef __DALI_INTERNAL_COMPLETE_STATUS_MANAGER_H__
+#define __DALI_INTERNAL_COMPLETE_STATUS_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+
+namespace Integration
+{
+class GlSyncAbstraction;
+}
+
+namespace Internal
+{
+class ResourceManager;
+class ResourceTracker;
+
+namespace SceneGraph
+{
+class RenderMessageDispatcher;
+}
+
+/**
+ * Class to manage resource tracking and completion status.
+ *
+ * Resources that are tracked are usually Framebuffer objects that are
+ * being rendered to by a RenderOnce render task.
+ *
+ * These need to change completion status either when all resources used by
+ * the framebuffer are complete, or when the framebuffer is backed by a native
+ * image and the native image has been written to by GL.
+ *
+ * This class uses ResourceManager to determine the complete status
+ * of non-tracked resources.
+ */
+class CompleteStatusManager
+{
+public:
+  /**
+   * Resource readiness state
+   */
+  enum CompleteState
+  {
+    NOT_READY, ///< Resource is not ready yet
+    COMPLETE,  ///< Resource has finished loading, or is otherwise complete
+    NEVER      ///< Resource will never be complete, e.g. load failed.
+  };
+
+  /**
+   * Constructor.
+   *
+   * @param[in] glSyncAbstraction The GlSyncObject abstraction (for creating RenderTrackers)
+   * @param[in] renderQueue The render queue (For passing ownership of RenderTrackers to RenderManager)
+   * @param[in] renderManager The render manager
+   * @param[in] query Update buffer query
+   * @param[in] resourceManager The resource manager (For handling untracked resources)
+   */
+  CompleteStatusManager( Integration::GlSyncAbstraction& glSyncAbstraction,
+                         SceneGraph::RenderMessageDispatcher& renderMessageDispatcher,
+                         ResourceManager& resourceManager );
+
+  /**
+   * Destructor
+   */
+  ~CompleteStatusManager();
+
+  /**
+   * @param[in] id The resource id to track
+   */
+  void TrackResource( Integration::ResourceId id );
+
+  /**
+   * Stop tracking the resource ID. Will remove any resource / render trackers for this ID.
+   * @param[in] id The resource id to stop tracking
+   */
+  void StopTrackingResource ( Integration::ResourceId id );
+
+  /**
+   * Get the resource tracker associated with this id
+   * @param[in] id The resource id
+   * @return a valid tracker if this resource is being tracked, or NULL.
+   */
+  ResourceTracker* FindResourceTracker( Integration::ResourceId id );
+
+  /**
+   * Gets the complete status of the resource.  If it has a tracker,
+   * it returns the status from the resource tracker, otherwise it
+   * returns the load status from the resource manager
+   *
+   * @param[in] id The resource id @return The complete state of the
+   * resource
+   */
+  CompleteState GetStatus( Integration::ResourceId id );
+
+private:
+  /**
+   * Factory method to create a ResourceTracker or GlResourceTracker for this resource id.
+   * It creates a ResourceTracker for framebuffers without native images, or a GlResourceTracker
+   * for framebuffers with native images that require Gl FenceSync.
+   * @param[in] id The resource id
+   */
+  ResourceTracker* CreateResourceTracker(Integration::ResourceId id);
+
+  typedef std::map< Integration::ResourceId, ResourceTracker* > TrackedResources;
+  typedef TrackedResources::iterator TrackedResourcesIter;
+
+  Integration::GlSyncAbstraction& mGlSyncAbstraction; ///< The synchronisation interface
+  SceneGraph::RenderMessageDispatcher& mRenderMessageDispatcher; ///< Render thread message dispatcher
+  ResourceManager& mResourceManager;   ///< The resource manager
+  TrackedResources mTrackedResources;  ///< Tracked resources
+};
+
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_COMPLETE_STATUS_MANAGER_H__
diff --git a/dali/internal/update/resources/resource-manager-declarations.h b/dali/internal/update/resources/resource-manager-declarations.h
new file mode 100644 (file)
index 0000000..8fbadac
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef __DALI_INTERNAL_RESOURCE_MANAGER_DECLARATIONS_H__
+#define __DALI_INTERNAL_RESOURCE_MANAGER_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/resource-cache.h>
+#include <dali/internal/update/common/double-buffered.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+typedef Integration::ResourceId ResourceId;
+
+/**
+ * Post processing required on the resource after the resource has been modified by the render thread
+ * Should only be handled by update thread
+ */
+struct ResourcePostProcessRequest
+{
+  enum PostProcess
+  {
+    UPLOADED,
+    DELETED
+  };
+
+  ResourceId   id;
+  PostProcess  postProcess;
+
+  ResourcePostProcessRequest( ResourceId anId, PostProcess aPostProcess )
+  : id(anId), postProcess(aPostProcess)
+  {
+  }
+};
+
+typedef SceneGraph::DoubleBuffered<std::vector< ResourcePostProcessRequest> > ResourcePostProcessList;
+
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_MANAGER_DECLARATIONS_H__
diff --git a/dali/internal/update/resources/resource-manager.cpp b/dali/internal/update/resources/resource-manager.cpp
new file mode 100644 (file)
index 0000000..2d6a140
--- /dev/null
@@ -0,0 +1,695 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/resources/resource-manager.h>
+
+// EXTERNAL INCLUDES
+#include <stdio.h>
+#include <typeinfo>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/map-wrapper.h>
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/public-api/math/vector2.h>
+
+#include <dali/integration-api/debug.h>
+
+#include <dali/internal/common/message.h>
+#include <dali/internal/common/image-attributes.h>
+
+#include <dali/internal/event/common/notification-manager.h>
+#include <dali/internal/event/resources/resource-type-path.h>
+#include <dali/internal/event/resources/resource-client.h>
+
+#include <dali/internal/update/common/discard-queue.h>
+#include <dali/internal/update/resources/bitmap-metadata.h>
+#include <dali/internal/render/queue/render-queue.h>
+
+#include <dali/internal/render/common/texture-cache-dispatcher.h>
+#include <dali/internal/render/common/post-process-resource-dispatcher.h>
+
+using namespace Dali::Integration;
+
+using Dali::Internal::SceneGraph::DiscardQueue;
+using Dali::Internal::SceneGraph::RenderQueue;
+using Dali::Internal::SceneGraph::TextureCacheDispatcher;
+
+namespace Dali
+{
+namespace Internal
+{
+
+typedef std::set<ResourceId>                     LiveRequestContainer;
+typedef LiveRequestContainer::iterator           LiveRequestIter;
+typedef LiveRequestContainer::size_type          LiveRequestSize;
+
+typedef std::map<ResourceId, ResourceTypeId>     DeadRequestContainer;
+typedef DeadRequestContainer::iterator           DeadRequestIter;
+typedef std::pair<ResourceId, ResourceTypeId>    DeadRequestPair;
+
+typedef std::vector<ResourceId>                  NotifyQueue;
+typedef NotifyQueue::iterator                    NotifyQueueIter;
+
+typedef std::map<ResourceId, BitmapMetadata>     BitmapMetadataCache;
+typedef BitmapMetadataCache::iterator            BitmapMetadataIter;
+typedef std::pair<ResourceId, BitmapMetadata>    BitmapMetadataPair;
+
+
+static inline bool RemoveId( LiveRequestContainer& container, ResourceId id )
+{
+  return container.erase(id) != 0;
+}
+
+struct ResourceManager::ResourceManagerImpl
+{
+  ResourceManagerImpl( PlatformAbstraction& platformAbstraction,
+                       NotificationManager& notificationManager,
+                       SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
+                       ResourcePostProcessList& resourcePostProcessQueue,
+                       SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
+                       DiscardQueue& discardQueue,
+                       RenderQueue& renderQueue )
+  : mPlatformAbstraction(platformAbstraction),
+    mNotificationManager(notificationManager),
+    mResourceClient(NULL),
+    mTextureCacheDispatcher(textureCacheDispatcher),
+    mResourcePostProcessQueue(resourcePostProcessQueue),
+    mPostProcessResourceDispatcher(postProcessResourceDispatcher),
+    mDiscardQueue(discardQueue),
+    mRenderQueue(renderQueue),
+    mNotificationCount(0),
+    cacheUpdated(false)
+  {
+  }
+
+  ~ResourceManagerImpl()
+  {
+  }
+
+  PlatformAbstraction&     mPlatformAbstraction;
+  NotificationManager&     mNotificationManager;
+  ResourceClient*          mResourceClient; // (needs to be a ptr - it's not instantiated yet)
+  TextureCacheDispatcher&  mTextureCacheDispatcher;
+  ResourcePostProcessList& mResourcePostProcessQueue;
+  SceneGraph::PostProcessResourceDispatcher& mPostProcessResourceDispatcher;
+  DiscardQueue&            mDiscardQueue; ///< Unwanted resources are added here during UpdateCache()
+  RenderQueue&             mRenderQueue;
+  unsigned int             mNotificationCount;
+  bool                     cacheUpdated; ///< returned by UpdateCache(). Set true in NotifyTickets to indicate a change in a resource
+
+  /**
+   * These containers are used to processs requests, and ResourceCache callbacks.
+   * The live request containers are simply sets of integer resource ids.
+   * The ID of a new request will be placed in the loading container.
+   * If the Ticket is destroyed during the load, the ID will be removed.
+   * If the load fails, the ID will be moved to the failed container.
+   * When the Ticket is notified of the failure, the ID will be removed.
+   * If the load succeeds, the ID will be moved to the new-completed container.
+   * When the Ticket is notified of the completion, the ID will be moved to the old-completed container.
+   * If a Ticket is destroyed after a successful load, the ID will be moved to the dead container.
+   * When the resources are eventually deleted, the ID will be removed from the dead container.
+   */
+  LiveRequestContainer loadingRequests;
+  LiveRequestContainer newCompleteRequests;
+  LiveRequestContainer oldCompleteRequests;
+  LiveRequestContainer newFailedRequests;
+  LiveRequestContainer oldFailedRequests;
+  DeadRequestContainer deadRequests;
+
+  /**
+   * This is the resource cache. It's filled/emptied from within Core::Update()
+   */
+  BitmapMetadataCache mBitmapMetadata;
+};
+
+ResourceManager::ResourceManager( PlatformAbstraction& platformAbstraction,
+                                  NotificationManager& notificationManager,
+                                  TextureCacheDispatcher& textureCacheDispatcher,
+                                  ResourcePostProcessList& resourcePostProcessQueue,
+                                  SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
+                                  DiscardQueue& discardQueue,
+                                  RenderQueue& renderQueue )
+{
+  mImpl = new ResourceManagerImpl( platformAbstraction,
+                                   notificationManager,
+                                   textureCacheDispatcher,
+                                   resourcePostProcessQueue,
+                                   postProcessResourceDispatcher,
+                                   discardQueue,
+                                   renderQueue );
+}
+
+ResourceManager::~ResourceManager()
+{
+  delete mImpl;
+}
+
+/********************************************************************************
+ ************************ ResourceClient direct interface  **********************
+ ********************************************************************************/
+
+void ResourceManager::SetClient( ResourceClient& client )
+{
+  mImpl->mResourceClient = &client;
+}
+
+/********************************************************************************
+ ************************ UpdateManager direct interface  ***********************
+ ********************************************************************************/
+
+bool ResourceManager::UpdateCache( BufferIndex updateBufferIndex )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "ResourceManager: UpdateCache(bufferIndex:%u)\n", updateBufferIndex);
+
+  // 1) Move unwanted resources to the DiscardQueue
+
+  DiscardDeadResources( updateBufferIndex );
+
+  // 2) Fill the resource cache
+  mImpl->cacheUpdated = false;
+
+  mImpl->mPlatformAbstraction.GetResources(*this);
+
+  return mImpl->cacheUpdated;
+}
+
+void ResourceManager::PostProcessResources( BufferIndex updateBufferIndex )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::Verbose, "ResourceManager: PostProcessResources()\n");
+
+  unsigned int numIds = mImpl->mResourcePostProcessQueue[ updateBufferIndex ].size();
+  unsigned int i;
+
+  // process the list where RenderManager put post process requests
+  for (i = 0; i < numIds; ++i)
+  {
+    ResourcePostProcessRequest ppRequest = mImpl->mResourcePostProcessQueue[ updateBufferIndex ][i];
+    switch(ppRequest.postProcess)
+    {
+      case ResourcePostProcessRequest::UPLOADED:
+      {
+        SendToClient( UploadedMessage( *mImpl->mResourceClient, ppRequest.id ) );
+        break;
+      }
+      case ResourcePostProcessRequest::DELETED:
+      {
+        // TextureObservers handled in TextureCache
+        break;
+      }
+    }
+  }
+
+  mImpl->mResourcePostProcessQueue[ updateBufferIndex ].clear();
+}
+
+
+/********************************************************************************
+ *************************** CoreImpl direct interface  *************************
+ ********************************************************************************/
+
+bool ResourceManager::ResourcesToProcess()
+{
+  bool workTodo = false;
+
+  // need to make sure we have passed all the notifications to the event handling side
+  workTodo |= !mImpl->newCompleteRequests.empty();
+  workTodo |= !mImpl->newFailedRequests.empty();
+  // check if there's something still loading
+  workTodo |= !mImpl->loadingRequests.empty();
+
+  return workTodo;
+}
+
+
+/********************************************************************************
+ ********************************* Message handlers *****************************
+ ********************************************************************************/
+
+void ResourceManager::HandleLoadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleLoadResourceRequest(id:%u, path:%s, type.id:%d)\n", id, typePath.path.c_str(), typePath.type->id);
+
+  // Add ID to the loading set
+  mImpl->loadingRequests.insert(id);
+
+  // Make the load request last
+  mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
+}
+
+void ResourceManager::HandleDecodeResourceRequest(
+  ResourceId id,
+  const ResourceTypePath& typePath,
+  RequestBufferPtr buffer,
+  Integration::LoadResourcePriority priority )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleDecodeResourceRequest(id:%u, buffer.size:%u, type.id:%u)\n", id, buffer->GetVector().Size(), typePath.type->id);
+
+  // Add ID to the loading set
+  mImpl->loadingRequests.insert(id);
+
+  // Make the load request, stuffing the buffer of encoded bytes into the same field used when saving resources:
+  mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, "", buffer, priority));
+}
+
+void ResourceManager::HandleAddBitmapImageRequest( ResourceId id, BitmapPtr bitmap )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddBitmapImageRequest(id:%u)\n", id);
+
+  mImpl->oldCompleteRequests.insert(id);
+  mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New( bitmap.Get() )));
+  mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap.Get() );
+}
+
+void ResourceManager::HandleAddNativeImageRequest(ResourceId id, NativeImageInterfacePtr nativeImage)
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddNativeImageRequest(id:%u)\n", id);
+
+  mImpl->oldCompleteRequests.insert(id);
+
+  mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(nativeImage)));
+  mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImage );
+}
+
+void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
+
+  mImpl->oldCompleteRequests.insert(id);
+
+  BitmapMetadata bitmapMetadata = BitmapMetadata::New(width, height, Pixel::HasAlpha(pixelFormat));
+  bitmapMetadata.SetIsFramebuffer(true);
+  mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, bitmapMetadata));
+
+  mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, width, height, pixelFormat, bufferFormat );
+}
+
+void ResourceManager::HandleAddFrameBufferImageRequest( ResourceId id, NativeImageInterfacePtr nativeImage )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAddFrameBufferImageRequest(id:%u)\n", id);
+
+  mImpl->oldCompleteRequests.insert(id);
+
+  BitmapMetadata bitmapMetadata = BitmapMetadata::New(nativeImage);
+  bitmapMetadata.SetIsNativeImage(true);
+  bitmapMetadata.SetIsFramebuffer(true);
+  mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, bitmapMetadata));
+
+  mImpl->mTextureCacheDispatcher.DispatchCreateTextureForFrameBuffer( id, nativeImage );
+}
+
+void ResourceManager::HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat )
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleAllocateTextureRequest(id:%u)\n", id);
+
+  mImpl->oldCompleteRequests.insert(id);
+  mImpl->mTextureCacheDispatcher.DispatchCreateTexture( id, width, height, pixelFormat, true /* true = clear the texture */ );
+}
+
+void ResourceManager::HandleUpdateBitmapAreaRequest( ResourceId textureId, const RectArea& area )
+{
+  if( textureId )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTextureArea( textureId, area );
+  }
+}
+
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset )
+{
+  if( destId && bitmap )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, bitmap, xOffset, yOffset );
+  }
+}
+
+void ResourceManager::HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset )
+{
+  if( destId && srcId )
+  {
+    mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( destId, srcId, xOffset, yOffset );
+  }
+}
+
+void ResourceManager::HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, LoadResourcePriority priority, bool resetFinishedStatus )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO( Debug::Filter::gResource, Debug::General, "ResourceManager: HandleReloadRequest(id:%u, path:%s)\n", id, typePath.path.c_str() );
+
+  bool resourceIsAlreadyLoading = true;
+
+  if( resetFinishedStatus )
+  {
+    if( ! RemoveId( mImpl->newCompleteRequests, id ) )
+    {
+      RemoveId( mImpl->oldCompleteRequests, id );
+    }
+  }
+
+  // ID might be in the loading set
+  LiveRequestIter iter = mImpl->loadingRequests.find( id );
+  if ( iter == mImpl->loadingRequests.end() )
+  {
+    // Add ID to the loading set
+    mImpl->loadingRequests.insert(id);
+    resourceIsAlreadyLoading = false;
+  }
+
+  if ( !resourceIsAlreadyLoading )
+  {
+    // load resource again
+    mImpl->mPlatformAbstraction.LoadResource(ResourceRequest(id, *typePath.type, typePath.path, priority));
+    SendToClient( LoadingMessage( *mImpl->mResourceClient, id ) );
+  }
+}
+
+void ResourceManager::HandleDiscardResourceRequest( ResourceId deadId, ResourceTypeId typeId )
+{
+  bool wasComplete = false;
+  bool wasLoading = false;
+
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: HandleDiscardResourceRequest(id:%u)\n", deadId);
+
+  // Search for the ID in one of the live containers
+  // IDs are only briefly held in the new-completed or failed containers; check those last
+  // Try removing from the old-completed requests
+  bool foundLiveRequest = wasComplete = RemoveId(mImpl->oldCompleteRequests, deadId);
+
+  // Try removing from the loading requests
+  if (!foundLiveRequest)
+  {
+    foundLiveRequest = wasLoading = RemoveId(mImpl->loadingRequests, deadId);
+  }
+
+  // Try removing from the new completed requests
+  if (!foundLiveRequest)
+  {
+    foundLiveRequest = wasComplete = RemoveId(mImpl->newCompleteRequests, deadId);
+  }
+
+  // Try removing from the new failed requests
+  if (!foundLiveRequest)
+  {
+    foundLiveRequest = RemoveId(mImpl->newFailedRequests, deadId);
+  }
+
+  // Try removing from the old failed requests
+  if (!foundLiveRequest)
+  {
+    foundLiveRequest = RemoveId(mImpl->oldFailedRequests, deadId);
+  }
+
+  // ID should be in one of the live sets
+  if (!foundLiveRequest)
+  {
+    DALI_LOG_WARNING("HandleDiscardResourceRequest: ID should be in one of the live sets!\n");
+  }
+  DALI_ASSERT_DEBUG(foundLiveRequest);
+
+  if (wasComplete)
+  {
+    if(typeId == ResourceBitmap ||
+       typeId == ResourceNativeImage ||
+       typeId == ResourceTargetImage )
+    {
+       // remove the meta data
+      mImpl->mBitmapMetadata.erase( deadId );
+
+      // destroy the texture
+      mImpl->mTextureCacheDispatcher.DispatchDiscardTexture( deadId );
+    }
+    else
+    {
+      // Move ID from completed to dead set
+      mImpl->deadRequests.insert(DeadRequestPair(deadId, typeId));
+    }
+  }
+
+  if (wasLoading)
+  {
+    mImpl->mPlatformAbstraction.CancelLoad(deadId, typeId);
+  }
+}
+
+void ResourceManager::HandleCreateGlTextureRequest(ResourceId id)
+{
+  mImpl->mTextureCacheDispatcher.DispatchCreateGlTexture( id );
+}
+
+/********************************************************************************
+ ******************** Update thread object direct interface  ********************
+ ********************************************************************************/
+
+bool ResourceManager::IsResourceLoaded(ResourceId id)
+{
+  bool loaded = false;
+
+  if( id > 0 )
+  {
+    LiveRequestIter iter = mImpl->newCompleteRequests.find(id);
+    if( iter != mImpl->newCompleteRequests.end() )
+    {
+      loaded = true;
+    }
+    else
+    {
+      iter = mImpl->oldCompleteRequests.find(id);
+      if( iter != mImpl->oldCompleteRequests.end() )
+      {
+        loaded = true;
+      }
+    }
+  }
+
+  return loaded;
+}
+
+bool ResourceManager::IsResourceLoadFailed(ResourceId id)
+{
+  bool loadFailed = false;
+
+  if( id > 0 )
+  {
+    LiveRequestIter iter = mImpl->newFailedRequests.find(id);
+    if( iter != mImpl->newFailedRequests.end() )
+    {
+      loadFailed = true;
+    }
+    else
+    {
+      iter = mImpl->oldFailedRequests.find(id);
+      if( iter != mImpl->oldFailedRequests.end() )
+      {
+        loadFailed = true;
+      }
+    }
+  }
+
+  return loadFailed;
+}
+
+BitmapMetadata ResourceManager::GetBitmapMetadata(ResourceId id)
+{
+  BitmapMetadata metadata;
+
+  if( id > 0 )
+  {
+    BitmapMetadataIter iter = mImpl->mBitmapMetadata.find(id);
+    if( iter != mImpl->mBitmapMetadata.end() )
+    {
+      metadata = iter->second;
+    }
+  }
+
+  return metadata;
+}
+
+/********************************************************************************
+ ************************* ResourceCache Implementation  ************************
+ ********************************************************************************/
+
+void ResourceManager::LoadResponse( ResourceId id, ResourceTypeId type, ResourcePointer resource, LoadStatus loadStatus )
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: LoadResponse(id:%u, status=%s)\n", id, loadStatus==RESOURCE_LOADING?"LOADING":loadStatus==RESOURCE_PARTIALLY_LOADED?"PARTIAL":"COMPLETE");
+
+  // ID might be in the loading set
+  LiveRequestIter iter = mImpl->loadingRequests.find(id);
+
+  if ( iter != mImpl->loadingRequests.end() )
+  {
+    if( loadStatus == RESOURCE_COMPLETELY_LOADED )
+    {
+      // Remove from the loading set
+      mImpl->loadingRequests.erase(iter);
+
+      // Add the ID to the new-completed set, and store the resource
+      mImpl->newCompleteRequests.insert(id);
+    }
+
+    switch ( type )
+    {
+      case ResourceBitmap:
+      {
+        DALI_ASSERT_DEBUG( loadStatus == RESOURCE_COMPLETELY_LOADED && "Partial results not handled for image loading.\n" );
+        Bitmap* const bitmap = static_cast<Bitmap*>( resource.Get() );
+        if( !bitmap )
+        {
+          DALI_LOG_ERROR( "Missing bitmap in loaded resource with id %u.\n", id );
+          break;
+        }
+        unsigned int bitmapWidth  = bitmap->GetImageWidth();
+        unsigned int bitmapHeight = bitmap->GetImageHeight();
+
+        if( Bitmap::PackedPixelsProfile * packedBitmap = bitmap->GetPackedPixelsProfile() )
+        {
+          bitmapWidth  = packedBitmap->GetBufferWidth();
+          bitmapHeight = packedBitmap->GetBufferHeight();
+        }
+        ImageAttributes attrs = ImageAttributes::New( bitmapWidth, bitmapHeight ); ///!< Issue #AHC01
+        UpdateImageTicket (id, attrs);
+
+        // Check for reloaded bitmap
+        BitmapMetadataIter iter = mImpl->mBitmapMetadata.find(id);
+        if (iter != mImpl->mBitmapMetadata.end())
+        {
+          iter->second.Update(bitmap);
+          mImpl->mTextureCacheDispatcher.DispatchUpdateTexture( id, bitmap );
+        }
+        else
+        {
+          mImpl->mTextureCacheDispatcher.DispatchCreateTextureForBitmap( id, bitmap );
+          mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(bitmap)));
+        }
+
+        break;
+      }
+
+      case ResourceNativeImage:
+      {
+        NativeImageInterfacePtr nativeImg( static_cast<NativeImageInterface*>(resource.Get()) );
+
+        ImageAttributes attrs = ImageAttributes::New(nativeImg->GetWidth(), nativeImg->GetHeight());
+
+        mImpl->mBitmapMetadata.insert(BitmapMetadataPair(id, BitmapMetadata::New(nativeImg)));
+        mImpl->mTextureCacheDispatcher.DispatchCreateTextureForNativeImage( id, nativeImg );
+
+        UpdateImageTicket (id, attrs);
+        break;
+      }
+
+      case ResourceTargetImage:
+      {
+        break;
+      }
+    }
+
+    // Let ResourceClient know that the resource manager has loaded something that its clients might want to hear about:
+    NotifyTickets();
+
+    // flag that a load has completed and the cache updated
+    mImpl->cacheUpdated = true;
+  }
+  else
+  {
+    // This warning can fire if a cancelled load is forgotten here while already complete on a resource thread:
+    DALI_LOG_WARNING( "Received a notification for an untracked resource: (id:%u, status=%s)\n", id, loadStatus==RESOURCE_LOADING?"LOADING":loadStatus==RESOURCE_PARTIALLY_LOADED?"PARTIAL":"COMPLETE");
+  }
+}
+
+void ResourceManager::LoadFailed(ResourceId id, ResourceFailure failure)
+{
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: LoadFailed(id:%u)\n", id);
+
+  // ID might be in the loading set
+  LiveRequestIter iter = mImpl->loadingRequests.find(id);
+
+  if (iter != mImpl->loadingRequests.end())
+  {
+    // Remove from the loading set
+    mImpl->loadingRequests.erase(iter);
+
+    // Add the ID to the failed set, this will trigger a notification during UpdateTickets
+    mImpl->newFailedRequests.insert(id);
+
+    // Let NotificationManager know that the resource manager needs to do some processing
+    NotifyTickets();
+
+    mImpl->cacheUpdated = true;
+  }
+}
+
+/********************************************************************************
+ ********************************* Private Methods  *****************************
+ ********************************************************************************/
+
+void ResourceManager::NotifyTickets()
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  // Success notifications
+  for (LiveRequestIter iter = mImpl->newCompleteRequests.begin(); iter != mImpl->newCompleteRequests.end(); ++iter)
+  {
+    // Move to oldCompleteRequests
+    mImpl->oldCompleteRequests.insert(*iter);
+
+    SendToClient( LoadingSucceededMessage( *mImpl->mResourceClient, *iter ) );
+  }
+  mImpl->newCompleteRequests.clear();
+
+  // Failure notifications
+  for (LiveRequestIter iter = mImpl->newFailedRequests.begin(); iter != mImpl->newFailedRequests.end(); ++iter)
+  {
+    // Move to oldFailedRequests
+    mImpl->oldFailedRequests.insert(*iter);
+
+    // We should have a matching request ticket
+    SendToClient( LoadingFailedMessage( *mImpl->mResourceClient, *iter ) );
+  }
+  mImpl->newFailedRequests.clear();
+}
+
+void ResourceManager::UpdateImageTicket( ResourceId id, ImageAttributes& attributes ) ///!< Issue #AHC01
+{
+  DALI_ASSERT_DEBUG( mImpl->mResourceClient != NULL );
+  // ResourceLoader should load images considering the requested size
+  DALI_LOG_INFO(Debug::Filter::gResource, Debug::General, "ResourceManager: UpdateImageTicket(id:%u)\n", id);
+
+  // Let NotificationManager know that the resource manager needs to do some processing
+  SendToClient( UpdateImageTicketMessage( *mImpl->mResourceClient, id, attributes) );
+}
+
+void ResourceManager::SendToClient( MessageBase* message )
+{
+  mImpl->mNotificationManager.QueueMessage( message );
+}
+
+void ResourceManager::DiscardDeadResources( BufferIndex updateBufferIndex )
+{
+  for (DeadRequestIter iter = mImpl->deadRequests.begin(); iter != mImpl->deadRequests.end(); )
+  {
+    // Erase the item and increment the iterator
+    mImpl->deadRequests.erase(iter++);
+  }
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/dali/internal/update/resources/resource-manager.h b/dali/internal/update/resources/resource-manager.h
new file mode 100644 (file)
index 0000000..8a28390
--- /dev/null
@@ -0,0 +1,574 @@
+#ifndef __DALI_INTERNAL_RESOURCE_MANAGER_H__
+#define __DALI_INTERNAL_RESOURCE_MANAGER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/devel-api/common/ref-counted-dali-vector.h>
+
+#include <dali/integration-api/bitmap.h>
+#include <dali/integration-api/platform-abstraction.h>
+#include <dali/integration-api/resource-cache.h>
+
+#include <dali/internal/common/message.h>
+#include <dali/internal/event/common/event-thread-services.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/internal/event/resources/resource-type-path.h>
+#include <dali/internal/event/resources/resource-client-declarations.h>
+#include <dali/internal/update/resources/resource-manager-declarations.h>
+#include <dali/internal/update/resources/bitmap-metadata.h>
+
+namespace Dali
+{
+
+class NativeImageInterface;
+
+namespace Integration
+{
+struct ResourceType;
+}
+
+namespace Internal
+{
+
+class ImageAttributes;
+
+// value types used by messages
+template <> struct ParameterType< Integration::LoadResourcePriority >
+: public BasicType< Integration::LoadResourcePriority > {};
+template <> struct ParameterType< Pixel::Format >
+: public BasicType< Pixel::Format > {};
+template <> struct ParameterType< RenderBuffer::Format >
+: public BasicType< RenderBuffer::Format > {};
+template <> struct ParameterType< Integration::ResourceTypeId >
+: public BasicType< Integration::ResourceTypeId > {};
+
+namespace SceneGraph
+{
+class DiscardQueue;
+class RenderQueue;
+class TextureCacheDispatcher;
+class PostProcessResourceDispatcher;
+}
+
+class NotificationManager;
+
+/** Raw bytes of a resource laid out exactly as it wouldbe in a file, but in memory. */
+typedef Dali::RefCountedVector<uint8_t> RequestBuffer;
+/** Counting smart pointer for managing a buffer of raw bytes. */
+typedef IntrusivePtr<RequestBuffer> RequestBufferPtr;
+
+/**
+ * ResourceManager keeps track of resource loading requests, and caches resources that are loaded.
+ * It uses ResourceTicket objects, to keep track of the lifetime of each request.
+ * If the same resource is required by two client objects, they will share the same ResourceTicket
+ * i.e. only one load will occur using the native filesystem.
+ *
+ * Multi-threading notes:
+ * Resources are received from the PlatformAbstraction API during the Core::Render() method, which
+ * may be called from a dedicated rendering thread.
+ * Loading requests must be made from the application's main thread e.g. when Dali::Image is created.
+ */
+class ResourceManager : public Integration::ResourceCache
+{
+public:
+
+  /**
+   * Create a resource manager.
+   * There should exactly one of these objects per Dali Core.
+   * @param[in] platformAbstraction Used to request resources from the native filesystem.
+   * @param[in] notificationManager Used to send NotifyTickets message.
+   * @param[in] postProcessResourcesQueue Used for performing post processing on resources
+   * @param[in] discardQueue Used to cleanup nodes & resources when no longer in use.
+   * @param[in] renderQueue Used to queue resource updates until the next Render.
+   */
+  ResourceManager( Integration::PlatformAbstraction& platformAbstraction,
+                   NotificationManager& notificationManager,
+                   SceneGraph::TextureCacheDispatcher& textureCacheDispatcher,
+                   ResourcePostProcessList& postProcessResourcesQueue,
+                   SceneGraph::PostProcessResourceDispatcher& postProcessResourceDispatcher,
+                   SceneGraph::DiscardQueue& discardQueue,
+                   SceneGraph::RenderQueue& renderQueue );
+
+  /**
+   * Virtual destructor.
+   */
+  virtual ~ResourceManager();
+
+public: // Used by ResourceClient
+
+  /********************************************************************************
+   ************************ ResourceClient direct interface  **********************
+   ********************************************************************************/
+
+  /**
+   * Resource client passes itself for secondary intialisation.
+   * (The resource client requires the ResourceManager to be instantiated first).
+   * @param[in] resourceClient The ResourceClient.
+   */
+  void SetClient( ResourceClient& resourceClient );
+
+  /********************************************************************************
+   ************************ UpdateManager direct interface  ***********************
+   ********************************************************************************/
+
+  /**
+   * Called to update the resource cache before rendering.
+   * New resources will be added to the cache using PlatformAbstraction::FillResourceCache().
+   * Unwanted resources will be added to the DiscardQueue.
+   * @param[in] updateBufferIndex The current update buffer index.
+   * @return true, if a resource load was completed or failed
+   */
+  bool UpdateCache( BufferIndex updateBufferIndex );
+
+  /**
+   * Iterate through the post process queue, performing requested updates.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void PostProcessResources( BufferIndex updateBufferIndex );
+
+  /********************************************************************************
+   *************************** CoreImpl direct interface  *************************
+   ********************************************************************************/
+
+  /**
+   * Returns whether the Resource Manager is still processing any resource requests.
+   * @return true if still processing, false otherwise.
+   */
+  bool ResourcesToProcess();
+
+  /********************************************************************************
+   ********************************* Message handlers *****************************
+   ********************************************************************************/
+
+  /**
+   * Request a resource from the native filesystem.
+   * @param[in] id The Id of the requested resource
+   * @param[in] typePath The type & path of requested resource.
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
+   */
+  void HandleLoadResourceRequest( ResourceId id,
+                                  const ResourceTypePath& typePath,
+                                  Integration::LoadResourcePriority priority );
+
+  /**
+   * Decode a resource from a memory buffer with the semantics of loading.
+   * Notifications of partial completion, success, and failure will happen via
+   * the same loading notification path used for loading from files: Update()
+   * will retrieve loading events in its main loop and notify listeners to its
+   * own loading events, and forward them, still as loading events, to the event
+   * thread via its update queue.
+   * Resource manager and lower levels make no attempt to detect resource
+   * aliases as is done for multiple requests to load the same resource
+   * file, so the caller is responsible for ensuring that it only requests
+   * the decoding of an in-memory resource once and for doing the sharing of the
+   * resulting object itself. Ultimately this responsibility resides with the
+   * application.
+   * @note ! Only Bitmap resources are supported for decoding from memory !
+   * @param[in] id The Id of the requested resource.
+   * @param[in] typePath The type of the requested resource and a path that is ignored.
+   * @param[in] buffer The raw encoded bytes of the resource as they would appear in a file.
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being loaded.
+   */
+  void HandleDecodeResourceRequest( ResourceId id,
+                                    const ResourceTypePath& typePath,
+                                    RequestBufferPtr buffer,
+                                    Integration::LoadResourcePriority priority );
+
+  /**
+   * Injects a bitmap resource (does not require loading).
+   * @pre bitmap has to be initialized
+   * @param[in] id The resource id
+   * @param[in] bitmap an initialized bitmap
+   */
+  void HandleAddBitmapImageRequest(ResourceId id, Integration::BitmapPtr bitmap);
+
+  /**
+   * Add an existing resource to the resource manager.
+   * @param[in] id The resource id
+   * @param [in] resourceData the NativeImageInterface object
+   * @return A ref-counted request object. Keep a copy until the resource is no longer required.
+   */
+  void HandleAddNativeImageRequest( ResourceId id, NativeImageInterfacePtr resourceData );
+
+  /**
+   * Add an existing resource to the resource manager.
+   * @param[in] id The resource id
+   * @param[in] width       width in pixels
+   * @param[in] height      height in pixels
+   * @param[in] pixelFormat Pixel format
+   */
+  void HandleAddFrameBufferImageRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat, RenderBuffer::Format bufferFormat );
+
+  /**
+   * Add an existing resource to the resource manager.
+   * @param[in] id            The resource id
+   * @param[in] nativeImage   The NativeImage
+   */
+  void HandleAddFrameBufferImageRequest( ResourceId id, NativeImageInterfacePtr nativeImage );
+
+  /**
+   * Allocate a new empty texture.
+   * @param[in] id The resource id
+   * @param[in] width       width in pixels
+   * @param[in] height      height in pixels
+   * @param[in] pixelFormat Pixel format
+   */
+  void HandleAllocateTextureRequest( ResourceId id, unsigned int width, unsigned int height, Pixel::Format pixelFormat );
+
+  /**
+   * Update bitmap area request
+   * @param[in] textureId The resource ID of a bitmap-texture to remove.
+   * @param[in] area The updated area. Zero width/height indicates the whole bitmap has been updated
+   */
+  void HandleUpdateBitmapAreaRequest( ResourceId textureId, const Dali::RectArea& area );
+
+  /**
+   * Upload a bitmap to a position within a specified texture
+   * @param[in] destId The destination texture ID
+   * @param[in] bitmap The pointer pointing to the bitmap data to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void HandleUploadBitmapRequest( ResourceId destId, Integration::BitmapPtr bitmap, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Upload a bitmap to a position within a specified texture
+   * @param[in] destId The destination texture ID
+   * @param[in] srcId The resource ID of the bitmap to upload
+   * @param [in] xOffset Specifies an offset in the x direction within the texture
+   * @param [in] yOffset Specifies an offset in the y direction within the texture
+   */
+  void HandleUploadBitmapRequest( ResourceId destId, ResourceId srcId, std::size_t xOffset, std::size_t yOffset );
+
+  /**
+   * Request reloading a resource from the native filesystem.
+   * @param[in] id The resource id
+   * @param[in] typePath The type & path of the resource
+   * @param[in] priority The priority of the request. This is ignored if the resource is already being refreshed.
+   * @param[in] resetFinishedStatus True if the finished status of the resource id should be reset
+   */
+  void HandleReloadResourceRequest( ResourceId id, const ResourceTypePath& typePath, Integration::LoadResourcePriority priority, bool resetFinishedStatus );
+
+  /**
+   * Resource ticket has been discarded, throw away the actual resource
+   */
+  void HandleDiscardResourceRequest( ResourceId id, Integration::ResourceTypeId typeId );
+
+   /**
+    * @brief Create GL texture for resource.
+    * @param[in] id The resource id.
+    */
+   void HandleCreateGlTextureRequest( ResourceId id );
+
+  /********************************************************************************
+   ******************** Update thread object direct interface  ********************
+   ********************************************************************************/
+
+  /**
+   * Check if a resource has completed loading.
+   * @param[in] id The ID of a bitmap/texture resource.
+   * @return true if the bitmap or texture has finished loading
+   */
+  bool IsResourceLoaded(ResourceId id);
+
+  /**
+   * Check if a resource has failed to load, e.g. file not found, etc.
+   * @param[in] id The ID of a bitmap/texture resource.
+   * @return true if the bitmap or texture has failed to load
+   */
+  bool IsResourceLoadFailed(ResourceId id);
+
+  /**
+   * Get bitmap metadata. This stores meta data about the resource, but
+   * doesn't keep track of the resource
+   */
+  BitmapMetadata GetBitmapMetadata(ResourceId id);
+
+    /********************************************************************************
+   ************************* ResourceCache Implementation  ************************
+   ********************************************************************************/
+public:
+
+  /**
+   * @copydoc Integration::ResourceCache::LoadResponse
+   */
+  virtual void LoadResponse(ResourceId id, Integration::ResourceTypeId type, Integration::ResourcePointer resource, Integration::LoadStatus loadStatus);
+
+  /**
+   * @copydoc Integration::ResourceCache::LoadFailed
+   */
+  virtual void LoadFailed(ResourceId id, Integration::ResourceFailure failure);
+
+  /********************************************************************************
+   ********************************* Private Methods  *****************************
+   ********************************************************************************/
+
+  /**
+   * Sends notification messages for load sucess & failure,
+   * pushes from newComplete / newFailed into oldComplete / oldFailed respectively
+   */
+  void NotifyTickets();
+
+  /**
+   * Triggers message to Event thread to update the ticket's image attributes
+   * @pre An Image resource with the given id should exist in the cache.
+   * @param id ID of the image resource
+   * @param attributes Resource image attributes
+   */
+  void UpdateImageTicket( ResourceId id, ImageAttributes& attributes );
+
+  /**
+   * Send message to ResourceClient in event thread
+   * @param[in] message The message to send
+   */
+  void SendToClient( MessageBase* message );
+
+  /**
+   * Discard all dead resources.
+   * @param[in] updateBufferIndex The current update buffer index.
+   */
+  void DiscardDeadResources( BufferIndex updateBufferIndex );
+
+private:
+
+  // Undefined
+  ResourceManager( const ResourceManager& resourceManager );
+
+  // Undefined
+  ResourceManager& operator=( const ResourceManager& rhs );
+
+private:
+  struct ResourceManagerImpl;
+  ResourceManagerImpl* mImpl;
+};
+
+// Messages sent to resource manager from other threads:
+// These functions are run on other threads and insert messages to be
+// picked-up by the update thread in its main loop and executed on that in
+// submission order.
+
+inline void RequestLoadResourceMessage( EventThreadServices& eventThreadServices,
+                                        ResourceManager& manager,
+                                        ResourceId id,
+                                        const ResourceTypePath& typePath,
+                                        Integration::LoadResourcePriority priority )
+{
+  typedef MessageValue3< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleLoadResourceRequest, id, typePath, priority );
+}
+
+inline void RequestDecodeResourceMessage( EventThreadServices& eventThreadServices,
+                                          ResourceManager& manager,
+                                          const ResourceId id,
+                                          /// We use typePath instead of the raw type for ownership and to enable copying of a concrete type.
+                                          const ResourceTypePath& typePath,
+                                          RequestBufferPtr buffer,
+                                          Integration::LoadResourcePriority priority )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, RequestBufferPtr, Integration::LoadResourcePriority > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleDecodeResourceRequest, id, typePath, buffer, priority );
+}
+
+inline void RequestAddBitmapImageMessage( EventThreadServices& eventThreadServices,
+                                          ResourceManager& manager,
+                                          ResourceId id,
+                                          Integration::Bitmap* resourceData )
+{
+  typedef MessageValue2< ResourceManager, ResourceId, Integration::BitmapPtr > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleAddBitmapImageRequest, id, resourceData );
+}
+
+inline void RequestAddNativeImageMessage( EventThreadServices& eventThreadServices,
+                                          ResourceManager& manager,
+                                          ResourceId id,
+                                          NativeImageInterfacePtr resourceData )
+{
+  typedef MessageValue2< ResourceManager, ResourceId, NativeImageInterfacePtr > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleAddNativeImageRequest, id, resourceData );
+}
+
+inline void RequestAddFrameBufferImageMessage( EventThreadServices& eventThreadServices,
+                                               ResourceManager& manager,
+                                               ResourceId id,
+                                               unsigned int width,
+                                               unsigned int height,
+                                               Pixel::Format pixelFormat,
+                                               RenderBuffer::Format bufferFormat
+                                               )
+{
+  typedef MessageValue5< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format, RenderBuffer::Format > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, width, height, pixelFormat, bufferFormat );
+}
+
+inline void RequestAddFrameBufferImageMessage( EventThreadServices& eventThreadServices,
+                                               ResourceManager& manager,
+                                               ResourceId id,
+                                               NativeImageInterfacePtr resourceData )
+{
+  typedef MessageValue2< ResourceManager, ResourceId, NativeImageInterfacePtr > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleAddFrameBufferImageRequest, id, resourceData );
+}
+
+inline void RequestAllocateTextureMessage( EventThreadServices& eventThreadServices,
+                                           ResourceManager& manager,
+                                           ResourceId id,
+                                           unsigned int width,
+                                           unsigned int height,
+                                           Pixel::Format pixelFormat)
+{
+  typedef MessageValue4< ResourceManager, ResourceId, unsigned int, unsigned int, Pixel::Format > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleAllocateTextureRequest, id, width, height, pixelFormat );
+}
+
+inline void RequestUpdateBitmapAreaMessage( EventThreadServices& eventThreadServices,
+                                            ResourceManager& manager,
+                                            ResourceId id,
+                                            const Dali::RectArea& area )
+{
+  typedef MessageValue2< ResourceManager, ResourceId, Dali::RectArea > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleUpdateBitmapAreaRequest, id, area );
+}
+
+inline void RequestUploadBitmapMessage( EventThreadServices& eventThreadServices,
+                                        ResourceManager& manager,
+                                        ResourceId destId,
+                                        Integration::BitmapPtr bitmap,
+                                        std::size_t xOffset,
+                                        std::size_t yOffset )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, Integration::BitmapPtr , std::size_t, std::size_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, bitmap, xOffset, yOffset );
+}
+
+inline void RequestUploadBitmapMessage( EventThreadServices& eventThreadServices,
+                                        ResourceManager& manager,
+                                        ResourceId destId,
+                                        ResourceId srcId,
+                                        std::size_t xOffset,
+                                        std::size_t yOffset )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, ResourceId, std::size_t, std::size_t > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleUploadBitmapRequest, destId, srcId, xOffset, yOffset );
+}
+
+inline void RequestReloadResourceMessage( EventThreadServices& eventThreadServices,
+                                          ResourceManager& manager,
+                                          ResourceId id,
+                                          const ResourceTypePath& typePath,
+                                          Integration::LoadResourcePriority priority,
+                                          bool resetFinishedStatus )
+{
+  typedef MessageValue4< ResourceManager, ResourceId, ResourceTypePath, Integration::LoadResourcePriority, bool > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ), false );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleReloadResourceRequest, id, typePath, priority, resetFinishedStatus );
+}
+
+inline void RequestDiscardResourceMessage( EventThreadServices& eventThreadServices,
+                                           ResourceManager& manager,
+                                           ResourceId id,
+                                           Integration::ResourceTypeId typeId )
+{
+  typedef MessageValue2< ResourceManager, ResourceId, Integration::ResourceTypeId > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleDiscardResourceRequest, id, typeId );
+}
+
+inline void RequestCreateGlTextureMessage( EventThreadServices& eventThreadServices,
+                                           ResourceManager& manager,
+                                           ResourceId id )
+{
+  typedef MessageValue1< ResourceManager, ResourceId > LocalType;
+
+  // Reserve some memory inside the message queue
+  unsigned int* slot = eventThreadServices.ReserveMessageSlot( sizeof( LocalType ) );
+
+  // Construct message in the message queue memory; note that delete should not be called on the return value
+  new (slot) LocalType( &manager, &ResourceManager::HandleCreateGlTextureRequest, id );
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_MANAGER_H__
diff --git a/dali/internal/update/resources/resource-tracker-debug.h b/dali/internal/update/resources/resource-tracker-debug.h
new file mode 100644 (file)
index 0000000..3cfaf15
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TRACKER_DEBUG_H__
+#define __DALI_INTERNAL_RESOURCE_TRACKER_DEBUG_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gResourceTrackerLogFilter;
+
+#define TRACKER_LOG(level)                                              \
+  DALI_LOG_INFO(gResourceTrackerLogFilter, level, "ResourceTracker::%s: this:%p\n", __FUNCTION__, this)
+#define TRACKER_LOG_FMT(level, format, args...) \
+  DALI_LOG_INFO(gResourceTrackerLogFilter, level, "ResourceTracker::%s: this:%p " format, __FUNCTION__, this, ## args)
+
+#else // DEBUG_ENABLED
+
+#define TRACKER_LOG(level)
+#define TRACKER_LOG_FMT(level, format, args...)
+
+#endif
+
+} // Internal
+} // Dali
+
+
+#endif // __DALI_INTERNAL_RESOURCE_TRACKER_H__
diff --git a/dali/internal/update/resources/resource-tracker.cpp b/dali/internal/update/resources/resource-tracker.cpp
new file mode 100644 (file)
index 0000000..ed1cc91
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/resources/resource-tracker.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/internal/update/resources/resource-tracker-debug.h>
+
+// EXTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Internal
+{
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gResourceTrackerLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_RESOURCE_TRACKER");
+#endif
+
+ResourceTracker::ResourceTracker()
+: mComplete(false)
+{
+}
+
+ResourceTracker::~ResourceTracker()
+{
+}
+
+void ResourceTracker::Initialize()
+{
+}
+
+void ResourceTracker::OnDestroy()
+{
+}
+
+void ResourceTracker::Reset()
+{
+  TRACKER_LOG(Debug::General);
+  mComplete = false;
+  DoReset();
+}
+
+void ResourceTracker::SetComplete()
+{
+  TRACKER_LOG(Debug::General);
+  DoSetComplete();
+}
+
+bool ResourceTracker::IsComplete()
+{
+  return DoIsComplete();
+}
+
+void ResourceTracker::DoReset()
+{
+}
+
+void ResourceTracker::DoSetComplete( )
+{
+  // Allow derived types to override complete behaviour - so do here
+  // rather than in SetComplete
+  mComplete = true;
+}
+
+bool ResourceTracker::DoIsComplete()
+{
+  return mComplete;
+}
+
+
+} // Internal
+} // Dali
diff --git a/dali/internal/update/resources/resource-tracker.h b/dali/internal/update/resources/resource-tracker.h
new file mode 100644 (file)
index 0000000..fbd7cd8
--- /dev/null
@@ -0,0 +1,116 @@
+#ifndef __DALI_INTERNAL_RESOURCE_TRACKER_H__
+#define __DALI_INTERNAL_RESOURCE_TRACKER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/integration-api/resource-declarations.h>
+#include <dali/internal/update/common/scene-graph-buffers.h>
+
+namespace Dali
+{
+namespace Integration
+{
+class GlSyncAbstraction;
+}
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderTracker;
+class RenderMessageDispatcher;
+}
+
+/**
+ * Class to track completion of a resource.
+ * Created for resource objects that can change completion status during update passes,
+ * such as chained framebuffers. This base class is designed to be used on resources that
+ * change completion in the update thread.
+ */
+class ResourceTracker
+{
+public:
+  /**
+   * Constructor
+   */
+  ResourceTracker();
+
+  /**
+   * Destructor
+   */
+  virtual ~ResourceTracker();
+
+  /**
+   * Second stage initialization
+   */
+  virtual void Initialize();
+
+  /**
+   * first stage destruction
+   * Called from CompleteStatusManager when the object is about to be deleted
+   */
+  virtual void OnDestroy();
+
+  /**
+   * Reset the tracker
+   */
+  void Reset();
+
+  /**
+   * Set the tracker to be complete (Derived types may ignore this)
+   */
+  void SetComplete( );
+
+  /**
+   * @return TRUE if the resource is complete
+   */
+  bool IsComplete();
+
+protected:
+  /**
+   * Do the reset. Allows derived types to handle the reset themselves.
+   */
+  virtual void DoReset();
+
+  /**
+   * Do the SetComplete. Allows derived types to handle the completeness themselves.
+   */
+  virtual void DoSetComplete();
+
+  /**
+   * Do the IsComplete. Allows derived types to perform their own handling
+   */
+  virtual bool DoIsComplete();
+
+  bool mComplete; ///< TRUE if tracked resource has completed
+
+private:
+  /**
+   * Undefined Copy Constructor and assignment operator
+   */
+  ResourceTracker(const ResourceTracker& rhs);
+  ResourceTracker& operator=(const ResourceTracker& rhs);
+};
+
+
+
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_RESOURCE_TRACKER_H__
diff --git a/dali/internal/update/resources/sync-resource-tracker.cpp b/dali/internal/update/resources/sync-resource-tracker.cpp
new file mode 100644 (file)
index 0000000..d2a5533
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/resources/sync-resource-tracker.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/controllers/render-message-dispatcher.h>
+#include <dali/internal/render/queue/render-queue.h>
+#include <dali/internal/render/common/render-tracker.h>
+#include <dali/internal/render/common/render-manager.h>
+#include <dali/internal/update/resources/resource-tracker-debug.h>
+
+// EXTERNAL INCLUDES
+
+namespace Dali
+{
+namespace Internal
+{
+
+SyncResourceTracker::SyncResourceTracker( Integration::GlSyncAbstraction& glSyncAbstraction,
+                                      SceneGraph::RenderMessageDispatcher& renderMessageDispatcher)
+: ResourceTracker(),
+  mGlSyncAbstraction(glSyncAbstraction),
+  mRenderMessageDispatcher(renderMessageDispatcher),
+  mRenderTracker(NULL)
+{
+}
+
+SyncResourceTracker::~SyncResourceTracker()
+{
+}
+
+void SyncResourceTracker::Initialize()
+{
+  mRenderTracker = new SceneGraph::RenderTracker(mGlSyncAbstraction);
+
+  // Pass ownership of render tracker to render manager, keep pointer for access
+  mRenderMessageDispatcher.AddRenderTracker( *mRenderTracker );
+}
+
+void SyncResourceTracker::OnDestroy()
+{
+  if( mRenderTracker != NULL )
+  {
+    mRenderMessageDispatcher.RemoveRenderTracker( *mRenderTracker );
+    mRenderTracker = NULL;
+  }
+}
+
+SceneGraph::RenderTracker* SyncResourceTracker::GetRenderTracker()
+{
+  return mRenderTracker;
+}
+
+void SyncResourceTracker::DoReset()
+{
+  if( mRenderTracker != NULL )
+  {
+    mRenderTracker->ResetSyncFlag();
+  }
+}
+
+void SyncResourceTracker::DoSetComplete()
+{
+  // Do nothing with this status, we are using only the RenderTracker to manage completeness
+}
+
+bool SyncResourceTracker::DoIsComplete()
+{
+  if( ! mComplete && mRenderTracker != NULL )
+  {
+    if( mRenderTracker->IsSynced() )
+    {
+      TRACKER_LOG_FMT(Debug::General, " Synced");
+      mComplete = true;
+    }
+  }
+  return mComplete;
+}
+
+} // Internal
+} // Dali
diff --git a/dali/internal/update/resources/sync-resource-tracker.h b/dali/internal/update/resources/sync-resource-tracker.h
new file mode 100644 (file)
index 0000000..dff8137
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef __DALI_INTERNAL_SYNC_RESOURCE_TRACKER_H__
+#define __DALI_INTERNAL_SYNC_RESOURCE_TRACKER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/internal/update/resources/resource-tracker.h>
+
+namespace Dali
+{
+namespace Integration
+{
+class GlSyncAbstraction;
+}
+
+namespace Internal
+{
+
+namespace SceneGraph
+{
+class RenderTracker;
+class RenderMessageDispatcher;
+}
+
+/**
+ * Class to track completion of a resource.
+ * This class is designed to be used on resources that change completion in the render thread.
+ * Used by RenderTasks that render to a framebuffer backed by a native image, i.e. it
+ * needs GlFenceSync to determine when GL has written to the native image.
+ */
+class SyncResourceTracker : public ResourceTracker
+{
+public:
+  /**
+   * Constructor
+   */
+  SyncResourceTracker( Integration::GlSyncAbstraction& glSyncAbstraction,
+                       SceneGraph::RenderMessageDispatcher& renderMessageDispatcher);
+
+  /**
+   * Destructor
+   */
+  virtual ~SyncResourceTracker();
+
+  /**
+   * Second stage initialization.
+   * Creates a RenderTracker object to handle fence sync
+   */
+  virtual void Initialize();
+
+  /**
+   * first stage destruction
+   * Called from CompleteStatusManager when the object is about to be deleted
+   */
+  virtual void OnDestroy();
+
+   /**
+   * Get the render tracker.
+   * @return The render tracker
+   */
+  SceneGraph::RenderTracker* GetRenderTracker();
+
+protected:
+  /**
+   * Do the reset. Resets the RenderTracker
+   */
+  virtual void DoReset();
+
+  /**
+   * Ignore complete status from update thread
+   */
+  virtual void DoSetComplete();
+
+  /**
+   * Do the IsComplete. Allows derived types to perform their own handling
+   */
+  virtual bool DoIsComplete();
+
+private:
+
+  /**
+   * Undefined Copy Constructor
+   */
+  SyncResourceTracker(const SyncResourceTracker& rhs);
+
+  /**
+   * @brief Undefined Assignment Operator
+   */
+  SyncResourceTracker& operator=(const SyncResourceTracker& rhs);
+
+private:
+  Integration::GlSyncAbstraction& mGlSyncAbstraction; ///< The synchronisation interface
+  SceneGraph::RenderMessageDispatcher& mRenderMessageDispatcher; ///< RenderManager message dispatcher
+  SceneGraph::RenderTracker* mRenderTracker; ///< The GL Fence Sync tracker object
+};
+
+} // Internal
+} // Dali
+
+#endif // __DALI_INTERNAL_SYNC_RESOURCE_TRACKER_H__
diff --git a/dali/internal/update/touch/history.h b/dali/internal/update/touch/history.h
new file mode 100644 (file)
index 0000000..438cfef
--- /dev/null
@@ -0,0 +1,296 @@
+#ifndef __DALI_INTERNAL_HISTORY_H__
+#define __DALI_INTERNAL_HISTORY_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <limits>
+
+// INTERNAL INCLUDES
+#include <dali/devel-api/common/set-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+/**
+ * HistoryPair
+ * represents a key-value element in the HistoryContainer
+ */
+template<class T>
+struct HistoryPairType
+{
+public:
+
+  HistoryPairType(float firstValue)
+  : first(firstValue)
+  {
+  }
+
+  HistoryPairType(float firstValue, T secondValue)
+  : first(firstValue),
+    second(secondValue)
+  {
+  }
+
+  bool operator<(const HistoryPairType& rhs) const
+  {
+    return first < rhs.first;
+  }
+
+  float first;
+  T second;
+};
+
+/**
+ * History container.
+ * This container is used for keeping a list of element pairs while providing an API that can
+ * generate interpolated values of requested elements that lie between two stored elements.
+ *
+ * e.g. stored values:
+ *
+ * 1.0 - 10
+ * 2.0 - 30
+ * 3.0 - 50
+ *
+ * Requesting value at key 1.5 will use the adjacent stored keys (1.0 and 2.0) to return an
+ * interpolated value of 20.0 (i.e. 0.5 of the way between 10 and 30).
+ *
+ * Requesting value at key 2.9 will use the adjacent stored keys (2.0 and 3.0) to return an
+ * interpolated value of 48.0 (i.e. 0.9 of the way between 30 and 50)
+ */
+class History
+{
+  typedef HistoryPairType<Vector2> HistoryPair;
+  typedef std::set<HistoryPair> HistoryContainer;
+  typedef HistoryContainer::iterator HistoryContainerIter;
+
+public:
+
+  /**
+   * History constructor
+   */
+  History()
+  : mMaxSize(std::numeric_limits<size_t>::max())
+  {
+  }
+
+  /**
+   * History destructor
+   */
+  ~History()
+  {
+  }
+
+  /**
+   * Sets the maximum size of the history container in terms of elements stored, default is no limit
+   * @param[in] maxSize The maximum number of elements stored in container
+   */
+  void SetMaxSize(size_t maxSize)
+  {
+    mMaxSize = maxSize;
+
+    if(mHistory.size() > mMaxSize)
+    {
+      // determine reduction in history size, and remove these elements
+      size_t reduction = mHistory.size() - mMaxSize;
+
+      while(reduction--)
+      {
+        mHistory.erase(mHistory.begin() );
+      }
+    }
+  }
+
+  void Clear()
+  {
+    mHistory.clear();
+  }
+
+  /**
+   * Adds an element (y) to the container at position (x)
+   *
+   * @param[in] x Key position value to add
+   * @param[in] y Value to add at Key.
+   */
+  void Add(float x, const Vector2& y)
+  {
+    if(mHistory.size() >= mMaxSize)
+    {
+      RemoveTail();
+    }
+
+    mHistory.insert(HistoryPair(x,y));
+  }
+
+  /**
+   * Removes first element in the container
+   */
+  void RemoveTail()
+  {
+    mHistory.erase(mHistory.begin());
+  }
+
+  /**
+   * Retrieves value from the history using key (x).
+   * If the requested key (x) lies between two points, a linearly interpolated value between the two
+   * points is returned.
+   *
+   * @param[in] x Key position to retrieve
+   *
+   * @return The interpolated Value is returned for this position.
+   */
+  Vector2 Get(float x) const
+  {
+    HistoryContainerIter i = mHistory.lower_bound(x);
+
+    if(i == mHistory.end())
+    {
+      --i;
+    }
+
+    // For samples based on first point, just return position.
+    if(i == mHistory.begin())
+    {
+      return i->second;
+    }
+
+    // within begin() ... end() range
+    float x2 = i->first;
+    Vector2 y2 = i->second;
+
+    --i;
+    float x1 = i->first;
+    Vector2 y1 = i->second;
+
+    // For samples based on first 2 points, just use linear interpolation
+    // TODO: Should really perform quadratic interpolation whenever there are 3+
+    // points.
+    if(i == mHistory.begin())
+    {
+      return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
+    }
+
+    // For samples based elsewhere, always use quadratic interpolation.
+    --i;
+    float x0 = i->first;
+    Vector2 y0 = i->second;
+
+    if(i != mHistory.begin())
+    {
+      --i;
+      float xn = i->first;
+      Vector2 yn = i->second;
+
+      x2 = (x2 + x1) * 0.5f;
+      x1 = (x1 + x0) * 0.5f;
+      x0 = (xn + x0) * 0.5f;
+
+      y2 = (y2 + y1) * 0.5f;
+      y1 = (y1 + y0) * 0.5f;
+      y0 = (yn + y0) * 0.5f;
+    }
+    // Quadratic equation:
+
+    // y = ax^2 + bx + c
+    // by making touches relative to x0, y0 (i.e. x0 = 0, y0 = 0)
+    // we get c = 0, and equation becomes:
+    // y = ax^2 + bx
+    // 1) Y1 = a . X1^2 + b X1
+    // 2) Y2 = a . X2^2 + b X2
+    // solving simulatenous equations gets:
+
+    // make time (x) & position (y) relative to x0, y0
+    y1 -= y0;
+    y2 -= y0;
+    x1 -= x0;
+    x2 -= x0;
+
+    x -= x0;
+
+    Vector2 a = ( y1 - (y2 * x1) / x2 ) / (x1 * (x1 - x2) );
+    Vector2 b = ( y1 / x1 ) - (a * x1);
+
+    return a * x * x + b * x + y0;
+  }
+
+  /**
+   * Retrieves a value from the history relative to the head.
+   *
+   * @note If the Keys (x) in the history decrease in value the further back you go. Then a
+   * negative deltaX value should be supplied to refer to these keys relative to the head key.
+   *
+   * @param[in] deltaX Key position to retrieve relative to head key
+   *
+   * @return The interpolated Value is returned for this relative position.
+   */
+  Vector2 GetRelativeToHead(float deltaX) const
+  {
+    HistoryContainerIter i = mHistory.end();
+    --i;
+    return Get(i->first + deltaX);
+  }
+
+  /**
+   * Retrieves the head time value.
+   *
+   * @retrun The head time value.
+   */
+  float GetHeadTime() const
+  {
+    HistoryContainerIter i = mHistory.end();
+    if(i==mHistory.begin())
+    {
+      return 0.0f;
+    }
+    --i;
+    return i->first;
+  }
+
+  /**
+   * Retrieves the head value.
+   *
+   * @return The head value.
+   */
+  Vector2 GetHead() const
+  {
+    HistoryContainerIter i = mHistory.end();
+    if(i==mHistory.begin())
+    {
+      return Vector2();
+    }
+    --i;
+    return i->second;
+  }
+
+private:
+
+  HistoryContainer mHistory;                ///< History container
+  size_t mMaxSize;                          ///< Current maximum size of container
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_HISTORY_H__
diff --git a/dali/internal/update/touch/touch-resampler.cpp b/dali/internal/update/touch/touch-resampler.cpp
new file mode 100644 (file)
index 0000000..78bab12
--- /dev/null
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/update/touch/touch-resampler.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/update/touch/history.h>
+#include <dali/integration-api/events/touch-data.h>
+#include <dali/integration-api/events/touch-event-integ.h>
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+namespace
+{
+
+static const unsigned int MaxPendingTouches(16u); ///< Queue can keep track of a maximum of 16 events per update refresh.
+
+/**
+ * Conversion function. To convert from raw touch data (which is either
+ * in a Down, Up or Motion state) to TouchPoint states.
+ * @param[in] touch The raw touch data state.
+ * @return[out] The TouchPoint state.
+ */
+TouchPoint::State GetStateFromTouch( const Dali::Integration::TouchData& touch )
+{
+  switch(touch.type)
+  {
+    case Dali::Integration::TouchData::Down:
+    {
+      return TouchPoint::Down;
+    }
+    case Dali::Integration::TouchData::Up:
+    {
+      return TouchPoint::Up;
+    }
+    case Dali::Integration::TouchData::Motion:
+    {
+      return TouchPoint::Motion;
+    }
+  } // end switch
+
+  DALI_ASSERT_ALWAYS(false); // should never reach here as we handle all possible cases in above switch
+
+  return TouchPoint::Last;
+}
+
+}
+
+/**
+ * TouchTracker keeps track of a single finger's touch movement from touch
+ * down to release. While the caller can then inspect the touch position and
+ * incidents that occured at a convenient time i.e. update-time.
+ * Typically there is 1 to 2 touches that occur between two updates.
+ *
+ * The application developer is interested in the touch position at a constant
+ * time point relative to the visual update (e.g. Always 5ms before the next
+ * render) - while touches rarely occur at the same time due to a difference
+ * in frequency amongst other timing issues.
+ *
+ * The application developer also wants to know if Up, Down or Motion events
+ * occured. But multiple motion "Motion 1 & Motion 2" events within a frame are
+ * wasteful information so they're consolidated into just "Motion 2".
+ * "Motion & Up" events within a frame are also wasteful, they're consolidated
+ * into just "Up". However "Down & Motion", or "Down & Up" events both need
+ * to be propagated to the user.
+ *
+ * Theoretically a double tap, given sufficient slow down of the update thread
+ * could also be propagated to the user with this system as "Down 1, Up 1, Down 2, Up 2"
+ */
+class TouchTracker
+{
+
+public:
+
+  /**
+   * Construct a TouchTracker based on an inital touch.
+   * This initial touch should be a Down press.
+   * @param[in] data The initial TouchData to populate this with.
+   */
+  TouchTracker(Dali::Integration::TouchData& data)
+  : mActive(true),
+    mIndex(data.index),
+    mPreviousType(data.type),
+    mStartTimestamp(data.timestamp)
+  {
+    mTouchHistory.SetMaxSize(5);
+    mIncidents.push_back(data);
+
+    mTouchHistory.Add(0.0f, Vector2(data.x, data.y));
+  }
+
+  /**
+   * Call SendTouchData to send this object some touch data.
+   * @param[in] data The data to send
+   */
+  void SendTouchData(Dali::Integration::TouchData& data)
+  {
+    mTouchHistory.Add(data.timestamp - mStartTimestamp, Vector2(data.x, data.y));
+
+    if(!mIncidents.size() || mPreviousType != data.type)
+    {
+      mIncidents.push_back(data);
+      mPreviousType = data.type;
+    }
+    else // If there are multiple touches on this frame, and previous is the same, then overwrite previous.
+    {
+      mIncidents[mIncidents.size()-1] = data;
+    }
+  }
+
+  /**
+   * Query the this object's touch position at a given timestamp
+   * @param[in] timestamp The point in time where the touch is wished
+   * to be known (using same timestamp scale as that provided in the
+   * TouchData)
+   * @return The interpolated touch position is returned.
+   */
+  Vector2 GetTouchPosition(unsigned int timestamp) const
+  {
+    float time( timestamp - mStartTimestamp );
+    Vector2 position = mTouchHistory.Get(time);
+    return position;
+  }
+
+  bool mActive;
+  unsigned int mIndex;
+  Dali::Integration::TouchDataContainer mIncidents;   ///< All of the touches from down to up for this
+  Dali::Integration::TouchData::TouchType mPreviousType;
+  History mTouchHistory;                              ///< Keep track of recent touches
+  unsigned int mStartTimestamp;                       ///< Timestamp of the first touch. Touch history has time relative to first touch.
+};
+
+typedef std::vector<TouchTracker> TouchTrackerContainer;
+typedef TouchTrackerContainer::iterator TouchTrackerIter;
+typedef TouchTrackerContainer::const_iterator TouchTrackerConstIter;
+
+/**
+ * TouchPointsTracker keeps track of all the touch points,
+ * receives touch data and sends to an individual TouchTracker
+ * to handle. It also generates TouchEvents based on all
+ * the TouchTrackers' event data.
+ */
+class TouchPointsTracker
+{
+public:
+
+  /**
+   * Call SendTouchData to send this tracker some touch data.
+   * @param[in] data The data to send
+   */
+  void SendTouchData( Dali::Integration::TouchData& data );
+
+  /**
+   * Query the number of touch events that can be generated from calling GetNextTouchEvent
+   * @return The number of touch events available.
+   */
+  unsigned int GetTouchEventCount() const;
+
+  /**
+   * Populate touchEvent with the next TouchEvent.
+   * The touch event position information is interpolated to produce a touch event that
+   * reflects the time provided (nextRenderTime)
+   *
+   * @note Call GetTouchEventCount() prior to calling this to know whether there are any
+   * TouchEvents available.
+   *
+   * @param[in] touchEvent The touch event to be populated with touch event info.
+   * @param[in] referenceTimestamp The timestamp required to assist touch smoothing.
+   */
+  bool GetNextTouchEvent( Dali::Integration::TouchEvent& touchEvent, unsigned int referenceTimestamp );
+
+private:
+
+  TouchTrackerContainer mTouches;                    ///< A container for each individual touch.
+
+};
+
+void TouchPointsTracker::SendTouchData( Dali::Integration::TouchData& data )
+{
+  // Check if we have a record of this touch index.
+  TouchTrackerIter i = mTouches.begin();
+  TouchTrackerIter endIter = mTouches.end();
+  for(;i != endIter; ++i )
+  {
+    if(i->mIndex == data.index)
+    {
+      i->SendTouchData(data);
+      return;
+    }
+  }
+
+  // If no record exists, then create a new record for this touch index.
+  mTouches.push_back( TouchTracker(data) );
+}
+
+unsigned int TouchPointsTracker::GetTouchEventCount() const
+{
+  TouchTrackerConstIter i = mTouches.begin();
+  TouchTrackerConstIter endIter = mTouches.end();
+  size_t maxTouches(0u);
+  for(;i != endIter; ++i )
+  {
+    // check if touch has incident(s), get max number of incidents on any touch.
+    maxTouches = std::max(maxTouches, i->mIncidents.size());
+  }
+
+  return maxTouches;
+}
+
+bool TouchPointsTracker::GetNextTouchEvent( Dali::Integration::TouchEvent& touchEvent, unsigned int referenceTimestamp )
+{
+  bool hasTouchEvent( GetTouchEventCount() > 0 );
+
+  if( hasTouchEvent )
+  {
+    TouchTrackerIter i = mTouches.begin();
+    TouchTrackerIter endIter = mTouches.end();
+    unsigned int maxTimestamp = 0u;
+
+    for(;i != endIter; ++i )
+    {
+      // check if touch has an incident, if so then take oldest incident off.
+      if(i->mIncidents.size())
+      {
+        const Dali::Integration::TouchData& touchData(*i->mIncidents.begin());
+
+        if(touchData.type == Dali::Integration::TouchData::Motion)
+        {
+          // For Motion, use a smoothed position.
+          Vector2 smoothPosition = i->GetTouchPosition(referenceTimestamp);
+
+          touchEvent.AddPoint( TouchPoint(i->mIndex, TouchPoint::Motion, smoothPosition.x, smoothPosition.y ) );
+          maxTimestamp = std::max(maxTimestamp, touchData.timestamp);
+        }
+        else
+        {
+          // For Up/Down, use a actual touch position.
+          touchEvent.AddPoint( TouchPoint(i->mIndex, GetStateFromTouch(touchData), touchData.x, touchData.y ) );
+          maxTimestamp = std::max(maxTimestamp, touchData.timestamp);
+        }
+
+        i->mIncidents.erase(i->mIncidents.begin());
+        i->mActive = touchData.type != Dali::Integration::TouchData::Up;
+      }
+      else
+      {
+        Vector2 smoothPosition = i->GetTouchPosition(referenceTimestamp);
+
+        // Stationary (TODO: final position should gravitate to real last touch position)
+        touchEvent.AddPoint( TouchPoint(i->mIndex, TouchPoint::Stationary, smoothPosition.x, smoothPosition.y ) );
+      }
+    }
+
+    touchEvent.time = maxTimestamp;
+
+    // clean up list. TODO: change to pointers.
+    TouchTrackerContainer touchesCleaned;
+    for(i = mTouches.begin();i != endIter; ++i )
+    {
+      if(i->mIncidents.size() || i->mActive)
+      {
+        touchesCleaned.push_back(*i);
+      }
+    }
+    mTouches = touchesCleaned;
+  }
+
+  return hasTouchEvent;
+}
+
+TouchResampler* TouchResampler::New()
+{
+  return new TouchResampler();
+}
+
+TouchResampler::~TouchResampler()
+{
+  delete[] mTouchesQueue;
+  delete mTouchPointsTracker;
+}
+
+void TouchResampler::SendTouchData( const Dali::Integration::TouchData& touch )
+{
+  mTouchesQueue[mTouchesWrite] = touch;
+  mTouchesWrite = (mTouchesWrite + 1) % MaxPendingTouches;
+  // TODO: Should only do this if it has been concluded that the down touch hits an Actor listening for touch.
+  // I think needs to send a down touch to Event thread to evaluate hit-test, and if valid, then enable update Required.
+
+  mUpdateRequired = true;
+}
+
+void TouchResampler::Update()
+{
+  while(mTouchesRead != mTouchesWrite)
+  {
+    mTouchPointsTracker->SendTouchData( mTouchesQueue[mTouchesRead] );
+
+    mTouchesRead = (mTouchesRead + 1) % MaxPendingTouches;
+  }
+}
+
+bool TouchResampler::GetNextTouchEvent( Dali::Integration::TouchEvent& touchEvent, unsigned int time )
+{
+  touchEvent.points.clear();
+  touchEvent.time = 0u;
+
+  return mTouchPointsTracker->GetNextTouchEvent( touchEvent, time );
+}
+
+bool TouchResampler::NeedsUpdate()
+{
+  bool updateRequired(mUpdateRequired);
+
+  mUpdateRequired = false;
+
+  return updateRequired;
+}
+
+TouchResampler::TouchResampler()
+: mUpdateRequired(false),
+  mTouchesQueue(new Dali::Integration::TouchData[MaxPendingTouches]),
+  mTouchesRead(0u),
+  mTouchesWrite(0u),
+  mTouchPointsTracker(new TouchPointsTracker())
+{
+}
+
+} // namespace Internal
+
+} // namespace Dali
+
diff --git a/dali/internal/update/touch/touch-resampler.h b/dali/internal/update/touch/touch-resampler.h
new file mode 100644 (file)
index 0000000..d301a0d
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef __DALI_INTERNAL_TOUCH_RESAMPLER_H__
+#define __DALI_INTERNAL_TOUCH_RESAMPLER_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+
+namespace Integration
+{
+
+struct TouchData;
+struct TouchEvent;
+
+} // namespace Integration
+
+namespace Internal
+{
+
+class TouchPointsTracker;
+
+/**
+ * The TouchResampler is responsible for receiving and regulating raw input touches, generating
+ * TouchEvents at a regulated frequency suitable for the update/render cycle.
+ *
+ * Usage:
+ *
+ * // Touch Thread...
+ * OnTouchEvent(const Dali::Integration::TouchData& rawTouchData)
+ * {
+ *   mResampler.SendTouchData( rawTouchData );
+ * }
+ *
+ * // Update Thread...
+ * OnUpdate(unsigned int timestamp)
+ * {
+ *   mResampler.Update();
+ *
+ *   while(mResampler.GetNextTouchEvent( touchEvent, timestamp ))
+ *   {
+ *     // send resampled touchEvent on to Application Thread.
+ *   }
+ * }
+ *
+ *
+ * Feed touch Events in at any frequency, and new touch Events will come out at the desired
+ * frequency of the caller.
+ */
+class TouchResampler
+{
+public:
+
+  /**
+   * Create a touch Resampler
+   */
+  static TouchResampler* New();
+
+  /**
+   * Virtual destructor
+   */
+  virtual ~TouchResampler();
+
+  /**
+   * Whenever there is new raw touch data it should be sent into the touch-resampler.
+   * This will queue the data, and it will be processed on every update
+   * (at the video refresh frequency e.g. 60Hz)
+   * @param[in] touch The latest touch data
+   */
+  void SendTouchData( const Dali::Integration::TouchData& touch );
+
+  /**
+   * Update should be called on every update frame (i.e. at video refresh frequency)
+   * This will identify all the touch incidents that occured since the past call.
+   */
+  void Update();
+
+  /**
+   * Calling GetNextTouchEvent after an Update will retrieve each TouchEvent that
+   * was generated by Update.
+   * @param[in] touchEvent Reference to a TouchEvent structure to be populated with
+   * a single TouchEvent.
+   * @param[in] time The time of interest in touch space-time that the caller
+   * is interested in.
+   */
+  bool GetNextTouchEvent( Dali::Integration::TouchEvent& touchEvent, unsigned int time );
+
+  /**
+   * Returns whether an update is required
+   * @note this changes the internal mUpdateRequired flag to false upon calling.
+   */
+  bool NeedsUpdate();
+
+private:
+
+  /**
+   * Protected constructor.
+   */
+  TouchResampler();
+
+  // Undefined
+  TouchResampler(const TouchResampler&);
+
+  // Undefined
+  TouchResampler& operator=(const TouchResampler&);
+
+private:
+
+  bool mUpdateRequired;
+  Dali::Integration::TouchData* mTouchesQueue;                    ///< Circular buffer.
+  volatile unsigned int mTouchesRead;                             ///< Circular buffer read offset.
+  volatile unsigned int mTouchesWrite;                            ///< Circular buffer write offset.
+  TouchPointsTracker* mTouchPointsTracker;
+
+};
+
+} // namespace Internal
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_TOUCH_RESAMPLER_H__
diff --git a/dali/public-api/actors/actor-enumerations.h b/dali/public-api/actors/actor-enumerations.h
new file mode 100644 (file)
index 0000000..23aa9d2
--- /dev/null
@@ -0,0 +1,138 @@
+#ifndef __DALI_ACTOR_ENUMERATIONS_H__
+#define __DALI_ACTOR_ENUMERATIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+/**
+ * @brief Actor color mode.
+ *
+ * @since_tizen 2.4
+ */
+enum ColorMode
+{
+  USE_OWN_COLOR,                 ///< Actor will use its own color
+  USE_PARENT_COLOR,              ///< Actor will use its parent color
+  USE_OWN_MULTIPLY_PARENT_COLOR, ///< Actor will blend its color with its parents color.
+  USE_OWN_MULTIPLY_PARENT_ALPHA  ///< Actor will blend its alpha with its parents alpha. This means when parent fades in or out child does as well. This is the default.
+};
+
+/**
+ * @brief Actor position inheritance mode.
+ * @since_tizen 2.4
+ */
+enum PositionInheritanceMode
+{
+  INHERIT_PARENT_POSITION,                 ///< Actor will inherit its parent position. This is the default
+  USE_PARENT_POSITION,                     ///< Actor will copy its parent position. This is useful if many actors are stacked together in the same place. This option ignores parent origin and anchor point.
+  USE_PARENT_POSITION_PLUS_LOCAL_POSITION, ///< Actor will copy its parent position and add local position. This is useful if many actors are stacked together in the same place with an offset.  This option ignores parent origin and anchor point.
+  DONT_INHERIT_POSITION                    ///< Actor will not inherit position. Local position is treated as world position. This is useful if a constraint is used to override local position or if an actor is positioned globally. This option ignores parent origin, anchor point and local position.
+};
+
+/**
+ * @brief Dimensions for layout
+ * @since_tizen 2.4
+ */
+namespace Dimension
+{
+enum Type
+{
+  WIDTH  = 0x1,       ///< Width dimension
+  HEIGHT = 0x2,       ///< Height dimension
+
+  ALL_DIMENSIONS = 0x3  ///< Mask to cover all flags
+};
+
+enum Meta
+{
+  DIMENSION_COUNT = 2  ///< Number of dimensions - update this if adding new dimension
+};
+}
+
+/**
+ * @brief Size negotiation resize policies
+ * @since_tizen 2.4
+ */
+namespace ResizePolicy
+{
+enum Type
+{
+  FIXED,                 ///< Size is fixed as set by SetSize
+  USE_NATURAL_SIZE,      ///< Size is to use the actor's natural size
+  FILL_TO_PARENT,        ///< Size is to fill up to the actor's parent's bounds. Aspect ratio not maintained.
+  SIZE_RELATIVE_TO_PARENT,        ///< The actors size will be ( ParentSize * SizeRelativeToParentFactor ).
+  SIZE_FIXED_OFFSET_FROM_PARENT,  ///< The actors size will be ( ParentSize + SizeRelativeToParentFactor ).
+  FIT_TO_CHILDREN,       ///< Size will adjust to wrap around all children
+  DIMENSION_DEPENDENCY,  ///< One dimension is dependent on the other
+  USE_ASSIGNED_SIZE      ///< The size will be assigned to the actor
+};
+const Type DEFAULT = USE_NATURAL_SIZE; ///< Default resize policy
+}
+
+/**
+ * @brief Policies to determine how an actor should resize itself when having its size set in size negotiation
+ * @since_tizen 2.4
+ */
+namespace SizeScalePolicy
+{
+enum Type
+{
+  USE_SIZE_SET,                ///< Use the size that was set
+  FIT_WITH_ASPECT_RATIO,       ///< Fit within the size set maintaining natural size aspect ratio
+  FILL_WITH_ASPECT_RATIO       ///< Fill up the size set maintaining natural size aspect ratio. May exceed size bounds in one dimension.
+};
+}
+
+/**
+ * @brief Different types of alignment.
+ * @since_tizen 2.4
+ */
+namespace HorizontalAlignment
+{
+enum Type
+{
+  LEFT,         ///< Align horizontally left
+  CENTER,       ///< Align horizontally center
+  RIGHT         ///< Align horiztonally right
+};
+}
+
+namespace VerticalAlignment
+{
+enum Type
+{
+  TOP,          ///< Align vertically top
+  CENTER,       ///< Align vertically center
+  BOTTOM        ///< Align vertically bottom
+};
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ACTOR_ENUMERATIONS_H__
diff --git a/dali/public-api/actors/actor.cpp b/dali/public-api/actors/actor.cpp
new file mode 100644 (file)
index 0000000..c37d7db
--- /dev/null
@@ -0,0 +1,598 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/actor.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector2.h>
+
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/rendering/renderer-impl.h>
+#include <dali/internal/event/actor-attachments/actor-attachment-impl.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/size-negotiation/relayout-controller-impl.h>
+
+namespace Dali
+{
+
+Actor::Actor()
+{
+}
+
+Actor Actor::New()
+{
+  Internal::ActorPtr internal = Internal::Actor::New();
+
+  return Actor(internal.Get());
+}
+
+Actor Actor::DownCast( BaseHandle handle )
+{
+  return Actor( dynamic_cast<Dali::Internal::Actor*>(handle.GetObjectPtr()) );
+}
+
+Actor::~Actor()
+{
+}
+
+Actor::Actor(const Actor& copy)
+: Handle(copy)
+{
+}
+
+Actor& Actor::operator=(const Actor& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+const std::string& Actor::GetName() const
+{
+  return GetImplementation(*this).GetName();
+}
+
+void Actor::SetName(const std::string& name)
+{
+  GetImplementation(*this).SetName(name);
+}
+
+unsigned int Actor::GetId() const
+{
+  return GetImplementation(*this).GetId();
+}
+
+bool Actor::IsRoot() const
+{
+  return GetImplementation(*this).IsRoot();
+}
+
+bool Actor::OnStage() const
+{
+  return GetImplementation(*this).OnStage();
+}
+
+bool Actor::IsLayer() const
+{
+  return GetImplementation(*this).IsLayer();
+}
+
+Layer Actor::GetLayer()
+{
+  return GetImplementation(*this).GetLayer();
+}
+
+void Actor::Add(Actor actor)
+{
+  GetImplementation(*this).Add(GetImplementation(actor));
+}
+
+void Actor::Remove(Actor actor)
+{
+  GetImplementation(*this).Remove(GetImplementation(actor));
+}
+
+void Actor::Unparent()
+{
+  GetImplementation(*this).Unparent();
+}
+
+unsigned int Actor::GetChildCount() const
+{
+  return GetImplementation(*this).GetChildCount();
+}
+
+Actor Actor::GetChildAt(unsigned int index) const
+{
+  Internal::ActorPtr child = GetImplementation(*this).GetChildAt( index );
+  return Actor( child.Get() );
+}
+
+Actor Actor::FindChildByName(const std::string& actorName)
+{
+  Internal::ActorPtr child = GetImplementation(*this).FindChildByName( actorName );
+  return Actor( child.Get() );
+}
+
+Actor Actor::FindChildById(const unsigned int id)
+{
+  Internal::ActorPtr child = GetImplementation(*this).FindChildById( id );
+  return Actor( child.Get() );
+}
+
+Actor Actor::GetParent() const
+{
+  Internal::Actor* parent = GetImplementation(*this).GetParent();
+
+  return Actor(parent);
+}
+
+void Actor::SetParentOrigin(const Vector3& origin)
+{
+  GetImplementation(*this).SetParentOrigin(origin);
+}
+
+Vector3 Actor::GetCurrentParentOrigin() const
+{
+  return GetImplementation(*this).GetCurrentParentOrigin();
+}
+
+void Actor::SetAnchorPoint(const Vector3& anchorPoint)
+{
+  GetImplementation(*this).SetAnchorPoint(anchorPoint);
+}
+
+Vector3 Actor::GetCurrentAnchorPoint() const
+{
+  return GetImplementation(*this).GetCurrentAnchorPoint();
+}
+
+void Actor::SetSize(float width, float height)
+{
+  GetImplementation(*this).SetSize(width, height);
+}
+
+void Actor::SetSize(float width, float height, float depth)
+{
+  GetImplementation(*this).SetSize(width, height, depth);
+}
+
+void Actor::SetSize(const Vector2& size)
+{
+  GetImplementation(*this).SetSize( size );
+}
+
+void Actor::SetSize(const Vector3& size)
+{
+  GetImplementation(*this).SetSize( size );
+}
+
+Vector3 Actor::GetTargetSize() const
+{
+  return GetImplementation(*this).GetTargetSize();
+}
+
+Vector3 Actor::GetCurrentSize() const
+{
+  return GetImplementation(*this).GetCurrentSize();
+}
+
+Vector3 Actor::GetNaturalSize() const
+{
+  return GetImplementation(*this).GetNaturalSize();
+}
+
+void Actor::SetPosition(float x, float y)
+{
+  GetImplementation(*this).SetPosition(x, y);
+}
+
+void Actor::SetPosition(float x, float y, float z)
+{
+  GetImplementation(*this).SetPosition(x, y, z);
+}
+
+void Actor::SetPosition(const Vector3& position)
+{
+  GetImplementation(*this).SetPosition(position);
+}
+
+void Actor::SetX(float x)
+{
+  GetImplementation(*this).SetX(x);
+}
+
+void Actor::SetY(float y)
+{
+  GetImplementation(*this).SetY(y);
+}
+
+void Actor::SetZ(float z)
+{
+  GetImplementation(*this).SetZ(z);
+}
+
+void Actor::TranslateBy(const Vector3& distance)
+{
+  GetImplementation(*this).TranslateBy(distance);
+}
+
+Vector3 Actor::GetCurrentPosition() const
+{
+  return GetImplementation(*this).GetCurrentPosition();
+}
+
+Vector3 Actor::GetCurrentWorldPosition() const
+{
+  return GetImplementation(*this).GetCurrentWorldPosition();
+}
+
+void Actor::SetPositionInheritanceMode( PositionInheritanceMode mode )
+{
+  GetImplementation(*this).SetPositionInheritanceMode( mode );
+}
+
+PositionInheritanceMode Actor::GetPositionInheritanceMode() const
+{
+  return GetImplementation(*this).GetPositionInheritanceMode();
+}
+
+void Actor::SetOrientation(const Radian& angle, const Vector3& axis)
+{
+  GetImplementation(*this).SetOrientation(angle, axis);
+}
+
+void Actor::SetOrientation(const Quaternion& orientation)
+{
+  GetImplementation(*this).SetOrientation(orientation);
+}
+
+void Actor::RotateBy(const Radian& angle, const Vector3& axis)
+{
+  GetImplementation(*this).RotateBy(angle, axis);
+}
+
+void Actor::RotateBy(const Quaternion& relativeRotation)
+{
+  GetImplementation(*this).RotateBy(relativeRotation);
+}
+
+Quaternion Actor::GetCurrentOrientation() const
+{
+  return GetImplementation(*this).GetCurrentOrientation();
+}
+
+void Actor::SetInheritOrientation(bool inherit)
+{
+  GetImplementation(*this).SetInheritOrientation(inherit);
+}
+
+bool Actor::IsOrientationInherited() const
+{
+  return GetImplementation(*this).IsOrientationInherited();
+}
+
+Quaternion Actor::GetCurrentWorldOrientation() const
+{
+  return GetImplementation(*this).GetCurrentWorldOrientation();
+}
+
+void Actor::SetScale(float scale)
+{
+  GetImplementation(*this).SetScale(scale);
+}
+
+void Actor::SetScale(float scaleX, float scaleY, float scaleZ)
+{
+  GetImplementation(*this).SetScale(scaleX, scaleY, scaleZ);
+}
+
+void Actor::SetScale(const Vector3& scale)
+{
+  GetImplementation(*this).SetScale(scale);
+}
+
+void Actor::ScaleBy(const Vector3& relativeScale)
+{
+  GetImplementation(*this).ScaleBy(relativeScale);
+}
+
+Vector3 Actor::GetCurrentScale() const
+{
+  return GetImplementation(*this).GetCurrentScale();
+}
+
+Vector3 Actor::GetCurrentWorldScale() const
+{
+  return GetImplementation(*this).GetCurrentWorldScale();
+}
+
+void Actor::SetInheritScale( bool inherit )
+{
+  GetImplementation(*this).SetInheritScale( inherit );
+}
+
+bool Actor::IsScaleInherited() const
+{
+  return GetImplementation(*this).IsScaleInherited();
+}
+
+void Actor::SetSizeModeFactor(const Vector3& factor)
+{
+  GetImplementation(*this).SetSizeModeFactor(factor);
+}
+
+Vector3 Actor::GetSizeModeFactor() const
+{
+  return GetImplementation(*this).GetSizeModeFactor();
+}
+
+Matrix Actor::GetCurrentWorldMatrix() const
+{
+  return GetImplementation(*this).GetCurrentWorldMatrix();
+}
+
+void Actor::SetVisible(bool visible)
+{
+  GetImplementation(*this).SetVisible(visible);
+}
+
+bool Actor::IsVisible() const
+{
+  return GetImplementation(*this).IsVisible();
+}
+
+void Actor::SetOpacity(float opacity)
+{
+  GetImplementation(*this).SetOpacity(opacity);
+}
+
+float Actor::GetCurrentOpacity() const
+{
+  return GetImplementation(*this).GetCurrentOpacity();
+}
+
+void Actor::SetColor(const Vector4& color)
+{
+  GetImplementation(*this).SetColor(color);
+}
+
+Vector4 Actor::GetCurrentColor() const
+{
+  return GetImplementation(*this).GetCurrentColor();
+}
+
+void Actor::SetColorMode( ColorMode colorMode )
+{
+  GetImplementation(*this).SetColorMode(colorMode);
+}
+
+ColorMode Actor::GetColorMode() const
+{
+  return GetImplementation(*this).GetColorMode();
+}
+
+Vector4 Actor::GetCurrentWorldColor() const
+{
+  return GetImplementation(*this).GetCurrentWorldColor();
+}
+
+void Actor::SetDrawMode( DrawMode::Type drawMode )
+{
+  GetImplementation(*this).SetDrawMode( drawMode );
+}
+
+DrawMode::Type Actor::GetDrawMode() const
+{
+  return GetImplementation(*this).GetDrawMode();
+}
+
+void Actor::SetSensitive(bool sensitive)
+{
+  GetImplementation(*this).SetSensitive(sensitive);
+}
+
+bool Actor::IsSensitive() const
+{
+  return GetImplementation(*this).IsSensitive();
+}
+
+bool Actor::ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const
+{
+  return GetImplementation(*this).ScreenToLocal(localX, localY, screenX, screenY);
+}
+
+void Actor::SetLeaveRequired(bool required)
+{
+  GetImplementation(*this).SetLeaveRequired(required);
+}
+
+bool Actor::GetLeaveRequired() const
+{
+  return GetImplementation(*this).GetLeaveRequired();
+}
+
+void Actor::SetKeyboardFocusable( bool focusable )
+{
+  GetImplementation(*this).SetKeyboardFocusable(focusable);
+}
+
+bool Actor::IsKeyboardFocusable() const
+{
+  return GetImplementation(*this).IsKeyboardFocusable();
+}
+
+void Actor::SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension )
+{
+  GetImplementation(*this).SetResizePolicy( policy, dimension );
+}
+
+ResizePolicy::Type Actor::GetResizePolicy( Dimension::Type dimension ) const
+{
+  return GetImplementation(*this).GetResizePolicy( dimension );
+}
+
+void Actor::SetSizeScalePolicy( SizeScalePolicy::Type policy )
+{
+  GetImplementation(*this).SetSizeScalePolicy( policy );
+}
+
+SizeScalePolicy::Type Actor::GetSizeScalePolicy() const
+{
+  return GetImplementation(*this).GetSizeScalePolicy();
+}
+
+float Actor::GetHeightForWidth( float width )
+{
+  return GetImplementation(*this).GetHeightForWidth( width );
+}
+
+float Actor::GetWidthForHeight( float height )
+{
+  return GetImplementation(*this).GetWidthForHeight( height );
+}
+
+float Actor::GetRelayoutSize( Dimension::Type dimension ) const
+{
+  return GetImplementation(*this).GetRelayoutSize( dimension );
+}
+
+void Actor::SetPadding( const Padding& padding )
+{
+  Internal::Actor& impl = GetImplementation(*this);
+
+  Vector2 widthPadding( padding.left, padding.right );
+  impl.SetPadding( widthPadding, Dimension::WIDTH );
+
+  Vector2 heightPadding( padding.bottom, padding.top );
+  impl.SetPadding( heightPadding, Dimension::HEIGHT );
+}
+
+void Actor::GetPadding( Padding& paddingOut ) const
+{
+  const Internal::Actor& impl = GetImplementation(*this);
+
+  Vector2 widthPadding = impl.GetPadding( Dimension::WIDTH );
+  Vector2 heightPadding = impl.GetPadding( Dimension::HEIGHT );
+
+  paddingOut.left = widthPadding.x;
+  paddingOut.right = widthPadding.y;
+  paddingOut.bottom = heightPadding.x;
+  paddingOut.top = heightPadding.y;
+}
+
+void Actor::SetMinimumSize( const Vector2& size )
+{
+  Internal::Actor& impl = GetImplementation(*this);
+
+  impl.SetMinimumSize( size.x, Dimension::WIDTH );
+  impl.SetMinimumSize( size.y, Dimension::HEIGHT );
+}
+
+Vector2 Actor::GetMinimumSize()
+{
+  Internal::Actor& impl = GetImplementation(*this);
+
+  return Vector2( impl.GetMinimumSize( Dimension::WIDTH ), impl.GetMinimumSize( Dimension::HEIGHT ) );
+}
+
+void Actor::SetMaximumSize( const Vector2& size )
+{
+  Internal::Actor& impl = GetImplementation(*this);
+
+  impl.SetMaximumSize( size.x, Dimension::WIDTH );
+  impl.SetMaximumSize( size.y, Dimension::HEIGHT );
+}
+
+Vector2 Actor::GetMaximumSize()
+{
+  Internal::Actor& impl = GetImplementation(*this);
+
+  return Vector2( impl.GetMaximumSize( Dimension::WIDTH ), impl.GetMaximumSize( Dimension::HEIGHT ) );
+}
+
+int Actor::GetHierarchyDepth()
+{
+  return GetImplementation(*this).GetHierarchyDepth();
+}
+
+Actor::TouchSignalType& Actor::TouchedSignal()
+{
+  return GetImplementation(*this).TouchedSignal();
+}
+
+Actor::HoverSignalType& Actor::HoveredSignal()
+{
+  return GetImplementation(*this).HoveredSignal();
+}
+
+Actor::WheelEventSignalType& Actor::WheelEventSignal()
+{
+  return GetImplementation(*this).WheelEventSignal();
+}
+
+Actor::OnStageSignalType& Actor::OnStageSignal()
+{
+  return GetImplementation(*this).OnStageSignal();
+}
+
+Actor::OffStageSignalType& Actor::OffStageSignal()
+{
+  return GetImplementation(*this).OffStageSignal();
+}
+
+unsigned int Actor::AddRenderer( Renderer& renderer )
+{
+  return GetImplementation(*this).AddRenderer( GetImplementation( renderer ) );
+}
+
+unsigned int Actor::GetRendererCount() const
+{
+  return GetImplementation(*this).GetRendererCount();
+}
+
+Renderer Actor::GetRendererAt( unsigned int index )
+{
+  return Renderer( &GetImplementation(*this).GetRendererAt( index ) );
+}
+
+void Actor::RemoveRenderer( Renderer& renderer )
+{
+  GetImplementation(*this).RemoveRenderer( GetImplementation( renderer ) );
+}
+
+void Actor::RemoveRenderer( unsigned int index )
+{
+  GetImplementation(*this).RemoveRenderer( index );
+}
+
+Actor::OnRelayoutSignalType& Actor::OnRelayoutSignal()
+{
+  return GetImplementation(*this).OnRelayoutSignal();
+}
+
+Actor::Actor(Internal::Actor* internal)
+: Handle(internal)
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/actor.h b/dali/public-api/actors/actor.h
new file mode 100644 (file)
index 0000000..1ca112e
--- /dev/null
@@ -0,0 +1,1535 @@
+#ifndef __DALI_ACTOR_H__
+#define __DALI_ACTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/actors/draw-mode.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/signals/dali-signal.h>
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class Actor;
+}
+
+class Actor;
+class Renderer;
+struct Degree;
+class Quaternion;
+class Layer;
+struct KeyEvent;
+struct TouchEvent;
+struct HoverEvent;
+struct WheelEvent;
+struct Vector2;
+struct Vector3;
+struct Vector4;
+
+typedef Rect<float> Padding;      ///< Padding definition
+
+/**
+ * @brief Actor is the primary object with which Dali applications interact.
+ *
+ * UI controls can be built by combining multiple actors.
+ *
+ * <h3>Multi-Touch Events:</h3>
+ *
+ * Touch or hover events are received via signals; see Actor::TouchedSignal() and Actor::HoveredSignal() for more details.
+ *
+ * <i>Hit Testing Rules Summary:</i>
+ *
+ * - An actor is only hittable if the actor's touch or hover signal has a connection.
+ * - An actor is only hittable when it is between the camera's near and far planes.
+ * - If an actor is made insensitive, then the actor and its children are not hittable; see IsSensitive()
+ * - If an actor's visibility flag is unset, then none of its children are hittable either; see IsVisible()
+ * - To be hittable, an actor must have a non-zero size.
+ * - If an actor's world color is fully transparent, then it is not hittable; see GetCurrentWorldColor()
+ *
+ * <i>Hit Test Algorithm:</i>
+ *
+ * - Stage
+ *   - Gets the first down and the last up touch events to the screen, regardless of actor touch event consumption.
+ *   - Stage's root layer can be used to catch unconsumed touch events.
+ *
+ * - RenderTasks
+ *   - Hit testing is dependent on the camera used, which is specific to each RenderTask.
+ *
+ * - Layers
+ *   - For each RenderTask, hit testing starts from the top-most layer and we go through all the
+ *     layers until we have a hit or there are none left.
+ *   - Before we perform a hit test within a layer, we check if all the layer's parents are visible
+ *     and sensitive.
+ *   - If they are not, we skip hit testing the actors in that layer altogether.
+ *   - If a layer is set to consume all touch, then we do not check any layers behind this layer.
+ *
+ * - Actors
+ *   - The final part of hit testing is performed by walking through the actor tree within a layer.
+ *   - The following pseudocode shows the algorithm used:
+ *     @code
+ *     HIT-TEST-WITHIN-LAYER( ACTOR )
+ *     {
+ *       // Only hit-test the actor and its children if it is sensitive and visible
+ *       IF ( ACTOR-IS-SENSITIVE &&
+ *            ACTOR-IS-VISIBLE )
+ *       {
+ *         // Depth-first traversal within current layer, visiting parent first
+ *
+ *         // Check whether current actor should be hit-tested
+ *         IF ( ( TOUCH-SIGNAL-NOT-EMPTY || HOVER-SIGNAL-NOT-EMPTY ) &&
+ *              ACTOR-HAS-NON-ZERO-SIZE &&
+ *              ACTOR-WORLD-COLOR-IS-NOT-TRANSPARENT )
+ *         {
+ *           // Hit-test current actor
+ *           IF ( ACTOR-HIT )
+ *           {
+ *             IF ( ACTOR-IS-OVERLAY || ( DISTANCE-TO-ACTOR < DISTANCE-TO-LAST-HIT-ACTOR ) )
+ *             {
+ *               // The current actor is the closest actor that was underneath the touch
+ *               LAST-HIT-ACTOR = CURRENT-ACTOR
+ *             }
+ *           }
+ *         }
+ *
+ *         // Keep checking children, in case we hit something closer
+ *         FOR-EACH CHILD (in order)
+ *         {
+ *           IF ( CHILD-IS-NOT-A-LAYER )
+ *           {
+ *             // Continue traversal for this child's sub-tree
+ *             HIT-TEST-WITHIN-LAYER ( CHILD )
+ *           }
+ *           // else we skip hit-testing the child's sub-tree altogether
+ *         }
+ *       }
+ *     }
+ *     @endcode
+ *   - Overlays always take priority (i.e. they're considered closer) regardless of distance.
+ *     The overlay children take priority over their parents, and overlay siblings take priority
+ *     over their previous siblings (i.e. reverse of rendering order):
+ *     @code
+ *           1
+ *          / \
+ *         /   \
+ *        2     5
+ *       / \     \
+ *      /   \     \
+ *     3     4     6
+ *
+ *     Hit Priority of above Actor tree (all overlays): 1 - Lowest. 6 - Highest.
+ *     @endcode
+ *   - Stencil Actors can be used to influence the result of hits on renderable actors within a layer.
+ *     If a Stencil Actor exists on a layer and that Actor is marked visible then a successful
+ *     hit on a renderable actor can only take place in the area that the stencil Actor marks as visible.
+ *     The hit can be in any Stencil Actor in that layer, but must be in the region of one of them.
+ *     Stencil Actor inheritance behaves as with rendering in that any child of a Stencil Actor will
+ *     also be considered a Stencil Actor.
+ *     Non-renderable actors can be hit regardless of whether a stencil actor is hit or not.
+ *
+ * <i>Touch or hover Event Delivery:</i>
+ *
+ * - Delivery
+ *   - The hit actor's touch or hover signal is emitted first; if it is not consumed by any of the listeners,
+ *     the parent's touch or hover signal is emitted, and so on.
+ *   - The following pseudocode shows the delivery mechanism:
+ *     @code
+ *     EMIT-TOUCH-SIGNAL( ACTOR )
+ *     {
+ *       IF ( TOUCH-SIGNAL-NOT-EMPTY )
+ *       {
+ *         // Only do the emission if touch signal of actor has connections.
+ *         CONSUMED = TOUCHED-SIGNAL( TOUCH-EVENT )
+ *       }
+ *
+ *       IF ( NOT-CONSUMED )
+ *       {
+ *         // If event is not consumed then deliver it to the parent unless we reach the root actor
+ *         IF ( ACTOR-PARENT )
+ *         {
+ *           EMIT-TOUCH-SIGNAL( ACTOR-PARENT )
+ *         }
+ *       }
+ *     }
+ *
+ *     EMIT-HOVER-SIGNAL( ACTOR )
+ *     {
+ *       IF ( HOVER-SIGNAL-NOT-EMPTY )
+ *       {
+ *         // Only do the emission if hover signal of actor has connections.
+ *         CONSUMED = HOVERED-SIGNAL( HOVER-EVENT )
+ *       }
+ *
+ *       IF ( NOT-CONSUMED )
+ *       {
+ *         // If event is not consumed then deliver it to the parent unless we reach the root actor
+ *         IF ( ACTOR-PARENT )
+ *         {
+ *           EMIT-HOVER-SIGNAL( ACTOR-PARENT )
+ *         }
+ *       }
+ *     }
+ *     @endcode
+ *   - If there are several touch points, then the delivery is only to the first touch point's hit
+ *     actor (and its parents).  There will be NO touch or hover signal delivery for the hit actors of the
+ *     other touch points.
+ *   - The local coordinates are from the top-left (0.0f, 0.0f, 0.5f) of the hit actor.
+ *
+ * - Leave State
+ *   - A "Leave" state is set when the first point exits the bounds of the previous first point's
+ *     hit actor (primary hit actor).
+ *   - When this happens, the last primary hit actor's touch or hover signal is emitted with a "Leave" state
+ *     (only if it requires leave signals); see SetLeaveRequired().
+ *
+ * - Interrupted State
+ *   - If a system event occurs which interrupts the touch or hover processing, then the last primary hit
+ *     actor's touch or hover signals are emitted with an "Interrupted" state.
+ *   - If the last primary hit actor, or one of its parents, is no longer touchable or hoverable, then its
+ *     touch or hover signals are also emitted with an "Interrupted" state.
+ *   - If the consumed actor on touch-down is not the same as the consumed actor on touch-up, then
+ *     touch signals are also emitted from the touch-down actor with an "Interrupted" state.
+ *   - If the consumed actor on hover-start is not the same as the consumed actor on hover-finished, then
+ *     hover signals are also emitted from the hover-started actor with an "Interrupted" state.
+ * <h3>Key Events:</h3>
+ *
+ * Key events are received by an actor once set to grab key events, only one actor can be set as focused.
+ *
+ * @nosubgrouping
+ *
+ * Signals
+ * | %Signal Name      | Method                       |
+ * |-------------------|------------------------------|
+ * | touched           | @ref TouchedSignal()         |
+ * | hovered           | @ref HoveredSignal()         |
+ * | wheel-event       | @ref WheelEventSignal()      |
+ * | on-stage          | @ref OnStageSignal()         |
+ * | off-stage         | @ref OffStageSignal()        |
+ *
+ * Actions
+ * | %Action Name      | %Actor method called         |
+ * |-------------------|------------------------------|
+ * | show              | %SetVisible( true )          |
+ * | hide              | %SetVisible( false )         |
+ * @since_tizen 2.4
+ */
+
+class DALI_IMPORT_API Actor : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the Actor class.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      PARENT_ORIGIN = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< name "parent-origin",         type Vector3
+      PARENT_ORIGIN_X,                                    ///< name "parent-origin-x",       type float
+      PARENT_ORIGIN_Y,                                    ///< name "parent-origin-y",       type float
+      PARENT_ORIGIN_Z,                                    ///< name "parent-origin-z",       type float
+      ANCHOR_POINT,                                       ///< name "anchor-point",          type Vector3
+      ANCHOR_POINT_X,                                     ///< name "anchor-point-x",        type float
+      ANCHOR_POINT_Y,                                     ///< name "anchor-point-y",        type float
+      ANCHOR_POINT_Z,                                     ///< name "anchor-point-z",        type float
+      SIZE,                                               ///< name "size",                  type Vector3
+      SIZE_WIDTH,                                         ///< name "size-width",            type float
+      SIZE_HEIGHT,                                        ///< name "size-height",           type float
+      SIZE_DEPTH,                                         ///< name "size-depth",            type float
+      POSITION,                                           ///< name "position",              type Vector3
+      POSITION_X,                                         ///< name "position-x",            type float
+      POSITION_Y,                                         ///< name "position-y",            type float
+      POSITION_Z,                                         ///< name "position-z",            type float
+      WORLD_POSITION,                                     ///< name "world-position",        type Vector3    (read-only)
+      WORLD_POSITION_X,                                   ///< name "world-position-x",      type float      (read-only)
+      WORLD_POSITION_Y,                                   ///< name "world-position-y",      type float      (read-only)
+      WORLD_POSITION_Z,                                   ///< name "world-position-z",      type float      (read-only)
+      ORIENTATION,                                        ///< name "orientation",           type Quaternion
+      WORLD_ORIENTATION,                                  ///< name "world-orientation",     type Quaternion (read-only)
+      SCALE,                                              ///< name "scale",                 type Vector3
+      SCALE_X,                                            ///< name "scale-x",               type float
+      SCALE_Y,                                            ///< name "scale-y",               type float
+      SCALE_Z,                                            ///< name "scale-z",               type float
+      WORLD_SCALE,                                        ///< name "world-scale",           type Vector3    (read-only)
+      VISIBLE,                                            ///< name "visible",               type bool
+      COLOR,                                              ///< name "color",                 type Vector4
+      COLOR_RED,                                          ///< name "color-red",             type float
+      COLOR_GREEN,                                        ///< name "color-green",           type float
+      COLOR_BLUE,                                         ///< name "color-blue",            type float
+      COLOR_ALPHA,                                        ///< name "color-alpha",           type float
+      WORLD_COLOR,                                        ///< name "world-color",           type Vector4    (read-only)
+      WORLD_MATRIX,                                       ///< name "world-matrix",          type Matrix     (read-only)
+      NAME,                                               ///< name "name",                  type std::string
+      SENSITIVE,                                          ///< name "sensitive",             type bool
+      LEAVE_REQUIRED,                                     ///< name "leave-required",        type bool
+      INHERIT_ORIENTATION,                                ///< name "inherit-orientation",   type bool
+      INHERIT_SCALE,                                      ///< name "inherit-scale",         type bool
+      COLOR_MODE,                                         ///< name "color-mode",            type std::string
+      POSITION_INHERITANCE,                               ///< name "position-inheritance",  type std::string
+      DRAW_MODE,                                          ///< name "draw-mode",             type std::string
+      SIZE_MODE_FACTOR,                                   ///< name "size-mode-factor",      type Vector3
+      WIDTH_RESIZE_POLICY,                                ///< name "width-resize-policy",   type String
+      HEIGHT_RESIZE_POLICY,                               ///< name "height-resize-policy",  type String
+      SIZE_SCALE_POLICY,                                  ///< name "size-scale-policy",     type String
+      WIDTH_FOR_HEIGHT,                                   ///< name "width-for-height",      type Boolean
+      HEIGHT_FOR_WIDTH,                                   ///< name "height-for-width",      type Boolean
+      PADDING,                                            ///< name "padding",               type Vector4
+      MINIMUM_SIZE,                                       ///< name "minimum-size",          type Vector2
+      MAXIMUM_SIZE,                                       ///< name "maximum-size",          type Vector2
+    };
+  };
+
+  // Typedefs
+
+  typedef Signal< bool (Actor, const TouchEvent&)> TouchSignalType;                 ///< Touch signal type
+  typedef Signal< bool (Actor, const HoverEvent&)> HoverSignalType;                 ///< Hover signal type
+  typedef Signal< bool (Actor, const WheelEvent&) > WheelEventSignalType;           ///< Wheel signal type
+  typedef Signal< void (Actor) > OnStageSignalType;  ///< Stage connection signal type
+  typedef Signal< void (Actor) > OffStageSignalType; ///< Stage disconnection signal type
+  typedef Signal< void (Actor) > OnRelayoutSignalType; ///< Called when the actor is relaid out
+
+  // Creation
+
+  /**
+   * @brief Create an uninitialized Actor; this can be initialized with Actor::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  Actor();
+
+  /**
+   * @brief Create an initialized Actor.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static Actor New();
+
+  /**
+   * @brief Downcast an Object handle to Actor handle.
+   *
+   * If handle points to a Actor object the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Actor object or an uninitialized handle
+   */
+  static Actor DownCast( BaseHandle handle );
+
+  /**
+   * @brief Dali::Actor is intended as a base class
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Actor();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] copy The actor to copy.
+   */
+  Actor(const Actor& copy);
+
+  /**
+   * @brief Assignment operator
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs The actor to copy.
+   */
+  Actor& operator=(const Actor& rhs);
+
+  /**
+   * @brief Retrieve the Actor's name.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's name.
+   * @pre The Actor has been initialized.
+   */
+  const std::string& GetName() const;
+
+  /**
+   * @brief Sets the Actor's name.
+   *
+   * @since_tizen 2.4
+   * @param [in] name The new name.
+   * @pre The Actor has been initialized.
+   */
+  void SetName(const std::string& name);
+
+  /**
+   * @brief Retrieve the unique ID of the actor.
+   *
+   * @since_tizen 2.4
+   * @return The ID.
+   * @pre The Actor has been initialized.
+   */
+  unsigned int GetId() const;
+
+  // Containment
+
+  /**
+   * @brief Query whether an actor is the root actor, which is owned by the Stage.
+   *
+   * @since_tizen 2.4
+   * @return True if the actor is the root actor.
+   * @pre The Actor has been initialized.
+   */
+  bool IsRoot() const;
+
+  /**
+   * @brief Query whether the actor is connected to the Stage.
+   *
+   * When an actor is connected, it will be directly or indirectly parented to the root Actor.
+   * @since_tizen 2.4
+   * @return True if the actor is connected to the Stage.
+   * @pre The Actor has been initialized.
+   * @note The root Actor is provided automatically by Dali::Stage, and is always considered to be connected.
+   */
+  bool OnStage() const;
+
+  /**
+   * @brief Query whether the actor is of class Dali::Layer.
+   *
+   * @since_tizen 2.4
+   * @return True if the actor is a layer.
+   * @pre The Actor has been initialized.
+   */
+  bool IsLayer() const;
+
+  /**
+   * @brief Gets the layer in which the actor is present.
+   *
+   * @since_tizen 2.4
+   * @return The layer, which will be uninitialized if the actor is off-stage.
+   * @pre The Actor has been initialized.
+   */
+  Layer GetLayer();
+
+  /**
+   * @brief Adds a child Actor to this Actor.
+   *
+   * NOTE! if the child already has a parent, it will be removed from old parent
+   * and reparented to this actor. This may change childs position, color,
+   * scale etc as it now inherits them from this actor
+   * @since_tizen 2.4
+   * @param [in] child The child.
+   * @pre This Actor (the parent) has been initialized.
+   * @pre The child actor has been initialized.
+   * @pre The child actor is not the same as the parent actor.
+   * @pre The actor is not the Root actor
+   * @post The child will be referenced by its parent. This means that the child will be kept alive,
+   * even if the handle passed into this method is reset or destroyed.
+   */
+  void Add(Actor child);
+
+  /**
+   * @brief Removes a child Actor from this Actor.
+   *
+   * If the actor was not a child of this actor, this is a no-op.
+   * @since_tizen 2.4
+   * @param [in] child The child.
+   * @pre This Actor (the parent) has been initialized.
+   * @pre The child actor is not the same as the parent actor.
+   */
+  void Remove(Actor child);
+
+  /**
+   * @brief Removes an actor from its parent.
+   *
+   * If the actor has no parent, this method does nothing.
+   * @since_tizen 2.4
+   * @pre The (child) actor has been initialized.
+   */
+  void Unparent();
+
+  /**
+   * @brief Retrieve the number of children held by the actor.
+   *
+   * @since_tizen 2.4
+   * @return The number of children
+   * @pre The Actor has been initialized.
+   */
+  unsigned int GetChildCount() const;
+
+  /**
+   * @brief Retrieve and child actor by index.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The index of the child to retrieve
+   * @return The actor for the given index or empty handle if children not initialised
+   * @pre The Actor has been initialized.
+   */
+  Actor GetChildAt(unsigned int index) const;
+
+  /**
+   * @brief Search through this actor's hierarchy for an actor with the given name.
+   *
+   * The actor itself is also considered in the search
+   * @since_tizen 2.4
+   * @param[in] actorName the name of the actor to find
+   * @return A handle to the actor if found, or an empty handle if not.
+   * @pre The Actor has been initialized.
+   */
+  Actor FindChildByName(const std::string& actorName);
+
+  /**
+   * @brief Search through this actor's hierarchy for an actor with the given unique ID.
+   *
+   * The actor itself is also considered in the search
+   * @since_tizen 2.4
+   * @param[in] id the ID of the actor to find
+   * @return A handle to the actor if found, or an empty handle if not.
+   * @pre The Actor has been initialized.
+   */
+  Actor FindChildById(const unsigned int id);
+
+  /**
+   * @brief Retrieve the actor's parent.
+   *
+   * @since_tizen 2.4
+   * @return A handle to the actor's parent. If the actor has no parent, this handle will be invalid.
+   * @pre The actor has been initialized.
+   */
+  Actor GetParent() const;
+
+  // Positioning
+
+  /**
+   * @brief Set the origin of an actor, within its parent's area.
+   *
+   * This is expressed in unit coordinates, such that (0.0, 0.0, 0.5) is the top-left corner of the parent,
+   * and (1.0, 1.0, 0.5) is the bottom-right corner.
+   * The default parent-origin is Dali::ParentOrigin::TOP_LEFT (0.0, 0.0, 0.5).
+   * An actor position is the distance between this origin, and the actors anchor-point.
+   * @since_tizen 2.4
+   * @param [in] origin The new parent-origin.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentParentOrigin().
+   * @see Dali::ParentOrigin for predefined parent origin values
+   */
+  void SetParentOrigin(const Vector3& origin);
+
+  /**
+   * @brief Retrieve the parent-origin of an actor.
+   *
+   * @since_tizen 2.4
+   * @return The current parent-origin.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetParentOrigin().
+   */
+  Vector3 GetCurrentParentOrigin() const;
+
+  /**
+   * @brief Set the anchor-point of an actor.
+   *
+   * This is expressed in unit coordinates, such that (0.0, 0.0, 0.5)
+   * is the top-left corner of the actor, and (1.0, 1.0, 0.5) is the
+   * bottom-right corner.  The default anchor point is
+   * Dali::AnchorPoint::CENTER (0.5, 0.5, 0.5).
+   * An actor position is the distance between its parent-origin, and this anchor-point.
+   * An actor's orientation is the rotation from its default orientation, the rotation is centered around its anchor-point.
+   * @since_tizen 2.4
+   * @param [in] anchorPoint The new anchor-point.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentAnchorPoint().
+   * @see Dali::AnchorPoint for predefined anchor point values
+   */
+  void SetAnchorPoint(const Vector3& anchorPoint);
+
+  /**
+   * @brief Retrieve the anchor-point of an actor.
+   *
+   * @since_tizen 2.4
+   * @return The current anchor-point.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetAnchorPoint().
+   */
+  Vector3 GetCurrentAnchorPoint() const;
+
+  /**
+   * @brief Sets the size of an actor.
+   *
+   * Geometry can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * The actors default depth is the minimum of width & height.
+   * @since_tizen 2.4
+   * @param [in] width  The new width.
+   * @param [in] height The new height.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentSize().
+   */
+  void SetSize(float width, float height);
+
+  /**
+   * @brief Sets the size of an actor.
+   *
+   * Geometry can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @since_tizen 2.4
+   * @param [in] width  The size of the actor along the x-axis.
+   * @param [in] height The size of the actor along the y-axis.
+   * @param [in] depth The size of the actor along the z-axis.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentSize().
+   */
+  void SetSize(float width, float height, float depth);
+
+  /**
+   * @brief Sets the size of an actor.
+   *
+   * Geometry can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * The actors default depth is the minimum of width & height.
+   * @since_tizen 2.4
+   * @param [in] size The new size.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentSize().
+   */
+  void SetSize(const Vector2& size);
+
+  /**
+   * @brief Sets the size of an actor.
+   *
+   * Geometry can be scaled to fit within this area.
+   * This does not interfere with the actors scale factor.
+   * @since_tizen 2.4
+   * @param [in] size The new size.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentSize().
+   */
+  void SetSize(const Vector3& size);
+
+  /**
+   * @brief Retrieve the actor's size.
+   *
+   * @since_tizen 2.4
+   * @return The actor's current size.
+   * @pre The actor has been initialized.
+   * @note This return is the value that was set using SetSize or the target size of an animation
+   */
+  Vector3 GetTargetSize() const;
+
+  /**
+   * @brief Retrieve the actor's size.
+   *
+   * @since_tizen 2.4
+   * @return The actor's current size.
+   * @pre The actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetSize().
+   */
+  Vector3 GetCurrentSize() const;
+
+  /**
+   * @brief Return the natural size of the actor.
+   *
+   * Deriving classes stipulate the natural size and by default an actor has a ZERO natural size.
+   *
+   * @since_tizen 2.4
+   * @return The actor's natural size
+   */
+  Vector3 GetNaturalSize() const;
+
+  /**
+   * @brief Sets the position of the actor.
+   *
+   * The Actor's z position will be set to 0.0f.
+   * @since_tizen 2.4
+   * @param [in] x The new x position
+   * @param [in] y The new y position
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetPosition(float x, float y);
+
+  /**
+   * @brief Sets the position of the Actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] x The new x position
+   * @param [in] y The new y position
+   * @param [in] z The new z position
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetPosition(float x, float y, float z);
+
+  /**
+   * @brief Sets the position of the Actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] position The new position
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetPosition(const Vector3& position);
+
+  /**
+   * @brief Set the position of an actor along the X-axis.
+   *
+   * @since_tizen 2.4
+   * @param [in] x The new x position
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetX(float x);
+
+  /**
+   * @brief Set the position of an actor along the Y-axis.
+   *
+   * @since_tizen 2.4
+   * @param [in] y The new y position.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetY(float y);
+
+  /**
+   * @brief Set the position of an actor along the Z-axis.
+   *
+   * @since_tizen 2.4
+   * @param [in] z The new z position
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentPosition().
+   */
+  void SetZ(float z);
+
+  /**
+   * @brief Translate an actor relative to its existing position.
+   *
+   * @since_tizen 2.4
+   * @param[in] distance The actor will move by this distance.
+   * @pre The actor has been initialized.
+   */
+  void TranslateBy(const Vector3& distance);
+
+  /**
+   * @brief Retrieve the position of the Actor.
+   *
+   * @since_tizen 2.4
+   * @return the Actor's current position.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetPosition().
+   */
+  Vector3 GetCurrentPosition() const;
+
+  /**
+   * @brief Retrieve the world-position of the Actor.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current position in world coordinates.
+   * @pre The Actor has been initialized.
+   * @note The actor will not have a world-position, unless it has previously been added to the stage.
+   */
+  Vector3 GetCurrentWorldPosition() const;
+
+  /**
+   * @brief Set the actors position inheritance mode.
+   *
+   * The default is to inherit.
+   * Switching this off means that using SetPosition() sets the actor's world position.
+   * @since_tizen 2.4
+   * @param[in] mode to use
+   * @pre The Actor has been initialized.
+   * @see PositionInheritanceMode
+   */
+  void SetPositionInheritanceMode( PositionInheritanceMode mode );
+
+  /**
+   * @brief Returns the actors position inheritance mode.
+   *
+   * @since_tizen 2.4
+   * @return true if the actor inherit's it's parent orientation, false if it uses world orientation.
+   * @pre The Actor has been initialized.
+   */
+  PositionInheritanceMode GetPositionInheritanceMode() const;
+
+  /**
+   * @brief Sets the orientation of the Actor.
+   *
+   * An actor's orientation is the rotation from its default orientation, and the rotation is centered around its anchor-point.
+   * @since_tizen 2.4
+   * @param [in] angle The new orientation angle in degrees.
+   * @param [in] axis The new axis of orientation.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentOrientation().
+   */
+  void SetOrientation( const Degree& angle, const Vector3& axis )
+  {
+    SetOrientation( Radian( angle ), axis );
+  }
+
+  /**
+   * @brief Sets the orientation of the Actor.
+   *
+   * An actor's orientation is the rotation from its default orientation, and the rotation is centered around its anchor-point.
+   * @since_tizen 2.4
+   * @param [in] angle The new orientation angle in radians.
+   * @param [in] axis The new axis of orientation.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentOrientation().
+   */
+  void SetOrientation(const Radian& angle, const Vector3& axis);
+
+  /**
+   * @brief Sets the orientation of the Actor.
+   *
+   * An actor's orientation is the rotation from its default orientation, and the rotation is centered around its anchor-point.
+   * @since_tizen 2.4
+   * @param [in] orientation The new orientation.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentOrientation().
+   */
+  void SetOrientation(const Quaternion& orientation);
+
+  /**
+   * @brief Apply a relative rotation to an actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] angle The angle to the rotation to combine with the existing orientation.
+   * @param[in] axis The axis of the rotation to combine with the existing orientation.
+   * @pre The actor has been initialized.
+   */
+  void RotateBy( const Degree& angle, const Vector3& axis )
+  {
+    RotateBy( Radian( angle ), axis );
+  }
+
+  /**
+   * @brief Apply a relative rotation to an actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] angle The angle to the rotation to combine with the existing orientation.
+   * @param[in] axis The axis of the rotation to combine with the existing orientation.
+   * @pre The actor has been initialized.
+   */
+  void RotateBy(const Radian& angle, const Vector3& axis);
+
+  /**
+   * @brief Apply a relative rotation to an actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] relativeRotation The rotation to combine with the existing orientation.
+   * @pre The actor has been initialized.
+   */
+  void RotateBy(const Quaternion& relativeRotation);
+
+  /**
+   * @brief Retreive the Actor's orientation.
+   *
+   * @since_tizen 2.4
+   * @return The current orientation.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetOrientation().
+   */
+  Quaternion GetCurrentOrientation() const;
+
+  /**
+   * @brief Set whether a child actor inherits it's parent's orientation.
+   *
+   * Default is to inherit.
+   * Switching this off means that using SetOrientation() sets the actor's world orientation.
+   * @since_tizen 2.4
+   * @param[in] inherit - true if the actor should inherit orientation, false otherwise.
+   * @pre The Actor has been initialized.
+   */
+  void SetInheritOrientation(bool inherit);
+
+  /**
+   * @brief Returns whether the actor inherit's it's parent's orientation.
+   *
+   * @since_tizen 2.4
+   * @return true if the actor inherit's it's parent orientation, false if it uses world orientation.
+   * @pre The Actor has been initialized.
+   */
+  bool IsOrientationInherited() const;
+
+  /**
+   * @brief Retrieve the world-orientation of the Actor.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current orientation in the world.
+   * @pre The Actor has been initialized.
+   * @note The actor will not have a world-orientation, unless it has previously been added to the stage.
+   */
+  Quaternion GetCurrentWorldOrientation() const;
+
+  /**
+   * @brief Set the scale factor applied to an actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] scale The scale factor applied on all axes.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentScale().
+   */
+  void SetScale(float scale);
+
+  /**
+   * @brief Set the scale factor applied to an actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] scaleX The scale factor applied along the x-axis.
+   * @param [in] scaleY The scale factor applied along the y-axis.
+   * @param [in] scaleZ The scale factor applied along the z-axis.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentScale().
+   */
+  void SetScale(float scaleX, float scaleY, float scaleZ);
+
+  /**
+   * @brief Set the scale factor applied to an actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] scale A vector representing the scale factor for each axis.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentScale().
+   */
+  void SetScale(const Vector3& scale);
+
+  /**
+   * @brief Apply a relative scale to an actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] relativeScale The scale to combine with the actors existing scale.
+   * @pre The actor has been initialized.
+   */
+  void ScaleBy(const Vector3& relativeScale);
+
+  /**
+   * @brief Retrieve the scale factor applied to an actor.
+   *
+   * @since_tizen 2.4
+   * @return A vector representing the scale factor for each axis.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetScale().
+   */
+  Vector3 GetCurrentScale() const;
+
+  /**
+   * @brief Retrieve the world-scale of the Actor.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current scale in the world.
+   * @pre The Actor has been initialized.
+   * @note The actor will not have a world-scale, unless it has previously been added to the stage.
+   */
+  Vector3 GetCurrentWorldScale() const;
+
+  /**
+   * @brief Set whether a child actor inherits it's parent's scale.
+   *
+   * Default is to inherit.
+   * Switching this off means that using SetScale() sets the actor's world scale.
+   * @since_tizen 2.4
+   * @param[in] inherit - true if the actor should inherit scale, false otherwise.
+   * @pre The Actor has been initialized.
+   */
+  void SetInheritScale( bool inherit );
+
+  /**
+   * @brief Returns whether the actor inherit's it's parent's scale.
+   *
+   * @since_tizen 2.4
+   * @return true if the actor inherit's it's parent scale, false if it uses world scale.
+   * @pre The Actor has been initialized.
+   */
+  bool IsScaleInherited() const;
+
+  /**
+   * @brief Retrieves the world-matrix of the actor.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current world matrix
+   * @pre The Actor has been initialized.
+   * @note The actor will not have a world-matrix, unless it has previously been added to the stage.
+   */
+  Matrix GetCurrentWorldMatrix() const;
+
+  // Visibility & Color
+
+  /**
+   * @brief Sets the visibility flag of an actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] visible The new visibility flag.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with IsVisible().
+   * @note If an actor's visibility flag is set to false, then the actor and its children will not be rendered.
+   *       This is regardless of the individual visibility values of the children i.e. an actor will only be
+   *       rendered if all of its parents have visibility set to true.
+   */
+  void SetVisible(bool visible);
+
+  /**
+   * @brief Retrieve the visibility flag of an actor.
+   *
+   * @since_tizen 2.4
+   * @return The visibility flag.
+   * @pre The actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetVisible().
+   * @note If an actor is not visible, then the actor and its children will not be rendered.
+   *       This is regardless of the individual visibility values of the children i.e. an actor will only be
+   *       rendered if all of its parents have visibility set to true.
+   */
+  bool IsVisible() const;
+
+  /**
+   * @brief Sets the opacity of an actor.
+   *
+   * @since_tizen 2.4
+   * @param [in] opacity The new opacity.
+   * @pre The actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentOpacity().
+   */
+  void SetOpacity(float opacity);
+
+  /**
+   * @brief Retrieve the actor's opacity.
+   *
+   * @since_tizen 2.4
+   * @return The actor's opacity.
+   * @pre The actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetOpacity().
+   */
+  float GetCurrentOpacity() const;
+
+  /**
+   * @brief Sets the actor's color; this is an RGBA value.
+   *
+   * The final color of the actor depends on its color mode.
+   * @since_tizen 2.4
+   * @param [in] color The new color.
+   * @pre The Actor has been initialized.
+   * @note This is an asynchronous method; the value written may not match a value subsequently read with GetCurrentColor().
+   */
+  void SetColor(const Vector4& color);
+
+  /**
+   * @brief Retrieve the actor's color.
+   *
+   * Actor's own color is not clamped.
+   * @since_tizen 2.4
+   * @return The color.
+   * @pre The Actor has been initialized.
+   * @note This property can be animated; the return value may not match the value written with SetColor().
+   */
+  Vector4 GetCurrentColor() const;
+
+  /**
+   * @brief Sets the actor's color mode.
+   *
+   * This specifies whether the Actor uses its own color, or inherits
+   * its parent color. The default is USE_OWN_MULTIPLY_PARENT_ALPHA.
+   * @since_tizen 2.4
+   * @param [in] colorMode to use.
+   * @pre The Actor has been initialized.
+   */
+  void SetColorMode( ColorMode colorMode );
+
+  /**
+   * @brief Returns the actor's color mode.
+   *
+   * @since_tizen 2.4
+   * @return currently used colorMode.
+   * @pre The Actor has been initialized.
+   */
+  ColorMode GetColorMode() const;
+
+  /**
+   * @brief Retrieve the world-color of the Actor, where each component is clamped within the 0->1 range.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current color in the world.
+   * @pre The Actor has been initialized.
+   * @note The actor will not have a world-color, unless it has previously been added to the stage.
+   */
+  Vector4 GetCurrentWorldColor() const;
+
+  /**
+   * @brief Set how the actor and its children should be drawn.
+   *
+   * Not all actors are renderable, but DrawMode can be inherited from any actor.
+   * By default a renderable actor will be drawn as a 3D object. It will be depth-tested against
+   * other objects in the world i.e. it may be obscured if other objects are in front.
+   *
+   * If DrawMode::OVERLAY_2D is used, the actor and its children will be drawn as a 2D overlay.
+   * Overlay actors are drawn in a separate pass, after all non-overlay actors within the Layer.
+   * For overlay actors, the drawing order is with respect to depth-index property of Renderers,
+   * and depth-testing will not be used.
+   *
+   * If DrawMode::STENCIL is used, the actor and its children will be used to stencil-test other actors
+   * within the Layer. Stencil actors are therefore drawn into the stencil buffer before any other
+   * actors within the Layer.
+   *
+   * @since_tizen 2.4
+   * @param[in] drawMode The new draw-mode to use.
+   * @note Setting STENCIL will override OVERLAY_2D, if that would otherwise have been inherited.
+   * @note Layers do not inherit the DrawMode from their parents.
+   */
+  void SetDrawMode( DrawMode::Type drawMode );
+
+  /**
+   * @brief Query how the actor and its children will be drawn.
+   *
+   * @since_tizen 2.4
+   * @return True if the Actor is an overlay.
+   */
+  DrawMode::Type GetDrawMode() const;
+
+  // Input Handling
+
+  /**
+   * @brief Sets whether an actor should emit touch or hover signals; see SignalTouch() and SignalHover().
+   *
+   * An actor is sensitive by default, which means that as soon as an application connects to the SignalTouch(),
+   * the touch event signal will be emitted, and as soon as an application connects to the SignalHover(), the
+   * hover event signal will be emitted.
+   *
+   * If the application wishes to temporarily disable the touch or hover event signal emission, then they can do so by calling:
+   * @code
+   * actor.SetSensitive(false);
+   * @endcode
+   *
+   * Then, to re-enable the touch or hover event signal emission, the application should call:
+   * @code
+   * actor.SetSensitive(true);
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param[in]  sensitive  true to enable emission of the touch or hover event signals, false otherwise.
+   * @pre The Actor has been initialized.
+   * @note If an actor's sensitivity is set to false, then it's children will not be hittable either.
+   *       This is regardless of the individual sensitivity values of the children i.e. an actor will only be
+   *       hittable if all of its parents have sensitivity set to true.
+   * @see @see SignalTouch() and SignalHover().
+   */
+  void SetSensitive(bool sensitive);
+
+  /**
+   * @brief Query whether an actor emits touch or hover event signals.
+   *
+   * @since_tizen 2.4
+   * @return true, if emission of touch or hover event signals is enabled, false otherwise.
+   * @pre The Actor has been initialized.
+   * @note If an actor is not sensitive, then it's children will not be hittable either.
+   *       This is regardless of the individual sensitivity values of the children i.e. an actor will only be
+   *       hittable if all of its parents have sensitivity set to true.
+   */
+  bool IsSensitive() const;
+
+  /**
+   * @brief Converts screen coordinates into the actor's coordinate system using the default camera.
+   *
+   * @since_tizen 2.4
+   * @param[out] localX On return, the X-coordinate relative to the actor.
+   * @param[out] localY On return, the Y-coordinate relative to the actor.
+   * @param[in] screenX The screen X-coordinate.
+   * @param[in] screenY The screen Y-coordinate.
+   * @return True if the conversion succeeded.
+   * @pre The Actor has been initialized.
+   * @note The actor coordinates are relative to the top-left (0.0, 0.0, 0.5)
+   */
+  bool ScreenToLocal(float& localX, float& localY, float screenX, float screenY) const;
+
+  /**
+   * @brief Sets whether the actor should receive a notification when touch or hover motion events leave
+   * the boundary of the actor.
+   *
+   * @since_tizen 2.4
+   * @param[in]  required  Should be set to true if a Leave event is required
+   * @pre The Actor has been initialized.
+   * @note By default, this is set to false as most actors do not require this.
+   * @note Need to connect to the SignalTouch or SignalHover to actually receive this event.
+   *
+   */
+  void SetLeaveRequired(bool required);
+
+  /**
+   * @brief This returns whether the actor requires touch or hover events whenever touch or hover motion events leave
+   * the boundary of the actor.
+   *
+   * @since_tizen 2.4
+   * @return true if a Leave event is required, false otherwise.
+   * @pre The Actor has been initialized.
+   */
+  bool GetLeaveRequired() const;
+
+  /**
+   * @brief Sets whether the actor should be focusable by keyboard navigation.
+   *
+   * The default is false.
+   * @since_tizen 2.4
+   * @param[in] focusable - true if the actor should be focusable by keyboard navigation,
+   * false otherwise.
+   * @pre The Actor has been initialized.
+   */
+  void SetKeyboardFocusable( bool focusable );
+
+  /**
+   * @brief Returns whether the actor is focusable by keyboard navigation.
+   *
+   * @since_tizen 2.4
+   * @return true if the actor is focusable by keyboard navigation, false if not.
+   * @pre The Actor has been initialized.
+   */
+  bool IsKeyboardFocusable() const;
+
+  // SIZE NEGOTIATION
+
+  /**
+   * @brief Set the resize policy to be used for the given dimension(s)
+   *
+   * @since_tizen 2.4
+   * @param[in] policy The resize policy to use
+   * @param[in] dimension The dimension(s) to set policy for. Can be a bitfield of multiple dimensions.
+   */
+  void SetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension );
+
+  /**
+   * @brief Return the resize policy used for a single dimension
+   *
+   * @since_tizen 2.4
+   * @param[in] dimension The dimension to get policy for
+   * @return Return the dimension resize policy
+   */
+  ResizePolicy::Type GetResizePolicy( Dimension::Type dimension ) const;
+
+  /**
+   * @brief Set the policy to use when setting size with size negotiation. Defaults to SizeScalePolicy::USE_SIZE_SET.
+   *
+   * @since_tizen 2.4
+   * @param[in] policy The policy to use for when the size is set
+   */
+  void SetSizeScalePolicy( SizeScalePolicy::Type policy );
+
+  /**
+   * @brief Return the size set policy in use
+   *
+   * @since_tizen 2.4
+   * @return Return the size set policy
+   */
+  SizeScalePolicy::Type GetSizeScalePolicy() const;
+
+  /**
+   * @brief Sets the relative to parent size factor of the actor.
+   *
+   * This factor is only used when ResizePolicy is set to either:
+   * ResizePolicy::SIZE_RELATIVE_TO_PARENT or ResizePolicy::SIZE_FIXED_OFFSET_FROM_PARENT.
+   * This actor's size is set to the actor's size multipled by or added to this factor,
+   * depending on ResizePolicy (See SetResizePolicy).
+   *
+   * @since_tizen 2.4
+   * @param [in] factor A Vector3 representing the relative factor to be applied to each axis.
+   * @pre The Actor has been initialized.
+   */
+  void SetSizeModeFactor( const Vector3& factor );
+
+  /**
+   * @brief Retrieve the relative to parent size factor of the actor.
+   *
+   * @since_tizen 2.4
+   * @return The Actor's current relative size factor.
+   * @pre The Actor has been initialized.
+   */
+  Vector3 GetSizeModeFactor() const;
+
+  /**
+   * @brief Calculate the height of the actor given a width
+   *
+   * The natural size is used for default calculation.
+   * size 0 is treated as aspect ratio 1:1.
+   *
+   * @since_tizen 2.4
+   * @param width Width to use
+   * @return Return the height based on the width
+   */
+  float GetHeightForWidth( float width );
+
+  /**
+   * @brief Calculate the width of the actor given a height
+   *
+   * The natural size is used for default calculation.
+   * size 0 is treated as aspect ratio 1:1.
+   *
+   * @since_tizen 2.4
+   * @param height Height to use
+   * @return Return the width based on the height
+   */
+  float GetWidthForHeight( float height );
+
+  /**
+   * @brief Return the value of negotiated dimension for the given dimension
+   *
+   * @since_tizen 2.4
+   * @param dimension The dimension to retrieve
+   * @return Return the value of the negotiated dimension
+   */
+  float GetRelayoutSize( Dimension::Type dimension ) const;
+
+  /**
+   * @brief Set the padding for use in layout
+   *
+   * @since_tizen 2.4
+   * @param[in] padding Padding for the actor
+   */
+  void SetPadding( const Padding& padding );
+
+  /**
+   * @brief Return the value of the padding
+   *
+   * @since_tizen 2.4
+   * @param paddingOut The returned padding data
+   */
+  void GetPadding( Padding& paddingOut ) const;
+
+  /**
+   * @brief Set the minimum size an actor can be assigned in size negotiation
+   *
+   * @since_tizen 2.4
+   * @param[in] size The minimum size
+   */
+  void SetMinimumSize( const Vector2& size );
+
+  /**
+   * @brief Return the minimum relayout size
+   *
+   * @since_tizen 2.4
+   * @return Return the mininmum size
+   */
+  Vector2 GetMinimumSize();
+
+  /**
+   * @brief Set the maximum size an actor can be assigned in size negotiation
+   *
+   * @since_tizen 2.4
+   * @param[in] size The maximum size
+   */
+  void SetMaximumSize( const Vector2& size );
+
+  /**
+   * @brief Return the maximum relayout size
+   *
+   * @since_tizen 2.4
+   * @return Return the maximum size
+   */
+  Vector2 GetMaximumSize();
+
+  /**
+   * @brief Get depth in the hierarchy for the actor
+   *
+   * @since_tizen 2.4
+   * @return The current depth in the hierarchy of the actor, or -1 if actor is not in the hierarchy
+   */
+  int GetHierarchyDepth();
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when touch input is received.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   bool YourCallbackName(Actor actor, const TouchEvent& event);
+   * @endcode
+   * The return value of True, indicates that the touch event should be consumed.
+   * Otherwise the signal will be emitted on the next sensitive parent of the actor.
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The Actor has been initialized.
+   */
+  TouchSignalType& TouchedSignal();
+
+  /**
+   * @brief This signal is emitted when hover input is received.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   bool YourCallbackName(Actor actor, const HoverEvent& event);
+   * @endcode
+   * The return value of True, indicates that the hover event should be consumed.
+   * Otherwise the signal will be emitted on the next sensitive parent of the actor.
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The Actor has been initialized.
+   */
+  HoverSignalType& HoveredSignal();
+
+  /**
+   * @brief This signal is emitted when wheel event is received.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   bool YourCallbackName(Actor actor, const WheelEvent& event);
+   * @endcode
+   * The return value of True, indicates that the wheel event should be consumed.
+   * Otherwise the signal will be emitted on the next sensitive parent of the actor.
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The Actor has been initialized.
+   */
+  WheelEventSignalType& WheelEventSignal();
+
+  /**
+   * @brief This signal is emitted after the actor has been connected to the stage.
+   *
+   * When an actor is connected, it will be directly or indirectly parented to the root Actor.
+   * @since_tizen 2.4
+   * @return The signal
+   * @note The root Actor is provided automatically by Dali::Stage, and is always considered to be connected.
+   *
+   * @note When the parent of a set of actors is connected to the stage, then all of the children
+   * will received this callback.
+   *
+   * For the following actor tree, the callback order will be A, B, D, E, C, and finally F.
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   *
+   */
+  OnStageSignalType& OnStageSignal();
+
+  /**
+   * @brief This signal is emitted after the actor has been disconnected from the stage.
+   *
+   * If an actor is disconnected it either has no parent, or is parented to a disconnected actor.
+   *
+   * @since_tizen 2.4
+   * @return The signal
+   * @note When the parent of a set of actors is disconnected to the stage, then all of the children
+   * will received this callback, starting with the leaf actors.
+   *
+   * For the following actor tree, the callback order will be D, E, B, F, C, and finally A.
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   *
+   */
+  OffStageSignalType& OffStageSignal();
+
+public: // Renderer
+
+  /**
+   * @brief Add a renderer to this actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] renderer Renderer to add to the actor
+   * @return The index of the Renderer that was added
+   * @pre The renderer must be initialized.
+   *
+   */
+  unsigned int AddRenderer( Renderer& renderer );
+
+  /**
+   * @brief Get the number of renderers on this actor.
+   *
+   * @since_tizen 2.4
+   * @return the number of renderers on this actor
+   */
+  unsigned int GetRendererCount() const;
+
+  /**
+   * @brief Get a Renderer by index.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The index of the renderer to fetch
+   * @return The renderer at the specified index
+   * @pre The index must be between 0 and GetRendererCount()-1
+   *
+   */
+  Renderer GetRendererAt( unsigned int index );
+
+  /**
+   * @brief Remove an renderer from the actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] renderer Handle to the renderer that is to be removed
+   */
+  void RemoveRenderer( Renderer& renderer );
+
+  /**
+   * @brief Remove an renderer from the actor by index.
+   *
+   * @since_tizen 2.4
+   * @param[in] index Index of the renderer that is to be removed
+   * @pre The index must be between 0 and GetRendererCount()-1
+   *
+   */
+  void RemoveRenderer( unsigned int index );
+  /**
+   * @brief This signal is emitted after the size has been set on the actor during relayout
+   *
+   * @since_tizen 2.4
+   * @return Return the signal
+   */
+  OnRelayoutSignalType& OnRelayoutSignal();
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL Actor(Internal::Actor* actor);
+};
+
+/**
+ * @brief Helper for discarding an actor handle.
+ *
+ * If the handle is empty, this method does nothing.  Otherwise
+ * actor.Unparent() will be called, followed by actor.Reset().
+ * @since_tizen 2.4
+ * @param[in,out] actor A handle to an actor, or an empty handle.
+ */
+inline void UnparentAndReset( Actor& actor )
+{
+  if( actor )
+  {
+    actor.Unparent();
+    actor.Reset();
+  }
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ACTOR_H__
diff --git a/dali/public-api/actors/blending.cpp b/dali/public-api/actors/blending.cpp
new file mode 100644 (file)
index 0000000..127514d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/blending.h>
+
+namespace Dali
+{
+
+const BlendingFactor::Type   DEFAULT_BLENDING_SRC_FACTOR_RGB(    BlendingFactor::SRC_ALPHA );
+const BlendingFactor::Type   DEFAULT_BLENDING_DEST_FACTOR_RGB(   BlendingFactor::ONE_MINUS_SRC_ALPHA );
+const BlendingFactor::Type   DEFAULT_BLENDING_SRC_FACTOR_ALPHA(  BlendingFactor::ONE );
+const BlendingFactor::Type   DEFAULT_BLENDING_DEST_FACTOR_ALPHA( BlendingFactor::ONE_MINUS_SRC_ALPHA );
+
+const BlendingEquation::Type DEFAULT_BLENDING_EQUATION_RGB(   BlendingEquation::ADD );
+const BlendingEquation::Type DEFAULT_BLENDING_EQUATION_ALPHA( BlendingEquation::ADD );
+
+} // namespace Dali
diff --git a/dali/public-api/actors/blending.h b/dali/public-api/actors/blending.h
new file mode 100644 (file)
index 0000000..aab2aa1
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_BLENDING_H__
+#define __DALI_BLENDING_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace BlendingMode
+{
+/**
+ * @brief Blending mode.
+ * @since_tizen 2.4
+ * @see Dali::RenderableActor::SetBlendMode() and Dali::RenderableActor::GetBlendMode()
+ */
+enum Type
+{
+  OFF,  ///< Blending is disabled.
+  AUTO, ///< Blending is enabled if there is alpha channel.
+  ON    ///< Blending is enabled.
+};
+
+} //namespace BlendingMode
+
+namespace BlendingFactor
+{
+/**
+ * @brief Blending Factor.
+ *
+ * @since_tizen 2.4
+ * @see Dali::RenderableActor::SetBlendFunc() and Dali::RenderableActor::GetBlendFunc()
+ */
+enum Type
+{
+  ZERO                     = 0,
+  ONE                      = 1,
+  SRC_COLOR                = 0x0300,
+  ONE_MINUS_SRC_COLOR      = 0x0301,
+  SRC_ALPHA                = 0x0302,
+  ONE_MINUS_SRC_ALPHA      = 0x0303,
+  DST_ALPHA                = 0x0304,
+  ONE_MINUS_DST_ALPHA      = 0x0305,
+  DST_COLOR                = 0x0306,
+  ONE_MINUS_DST_COLOR      = 0x0307,
+  SRC_ALPHA_SATURATE       = 0x0308,
+  CONSTANT_COLOR           = 0x8001,
+  ONE_MINUS_CONSTANT_COLOR = 0x8002,
+  CONSTANT_ALPHA           = 0x8003,
+  ONE_MINUS_CONSTANT_ALPHA = 0x8004
+};
+
+} // namespace BlendingFactor
+
+namespace BlendingEquation
+{
+/**
+ * @brief Blending Equation.
+ *
+ * @since_tizen 2.4
+ * @see Dali::RenderableActor::SetBlendEquation() and Dali::RenderableActor::GetBlendEquation()
+ */
+enum Type
+{
+  ADD              = 0x8006,
+  SUBTRACT         = 0x800A,
+  REVERSE_SUBTRACT = 0x800B
+};
+
+} // namespace BlendingEquation
+
+DALI_IMPORT_API extern const BlendingFactor::Type   DEFAULT_BLENDING_SRC_FACTOR_RGB;    ///< BlendingFactor::SRC_ALPHA
+DALI_IMPORT_API extern const BlendingFactor::Type   DEFAULT_BLENDING_DEST_FACTOR_RGB;   ///< BlendingFactor::ONE_MINUS_SRC_ALPHA
+DALI_IMPORT_API extern const BlendingFactor::Type   DEFAULT_BLENDING_SRC_FACTOR_ALPHA;  ///< BlendingFactor::ONE
+DALI_IMPORT_API extern const BlendingFactor::Type   DEFAULT_BLENDING_DEST_FACTOR_ALPHA; ///< BlendingFactor::ONE_MINUS_SRC_ALPHA
+
+DALI_IMPORT_API extern const BlendingEquation::Type DEFAULT_BLENDING_EQUATION_RGB;     ///< BlendingEquation::ADD
+DALI_IMPORT_API extern const BlendingEquation::Type DEFAULT_BLENDING_EQUATION_ALPHA;   ///< BlendingEquation::ADD
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_BLENDING_H__
diff --git a/dali/public-api/actors/camera-actor.cpp b/dali/public-api/actors/camera-actor.cpp
new file mode 100644 (file)
index 0000000..d763bcd
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/camera-actor.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/camera-actor-impl.h>
+
+namespace Dali
+{
+
+CameraActor CameraActor::New()
+{
+  Internal::CameraActorPtr internal = Internal::CameraActor::New( Size::ZERO );
+
+  return CameraActor(internal.Get());
+}
+
+
+CameraActor CameraActor::New( const Size& size )
+{
+  Internal::CameraActorPtr internal = Internal::CameraActor::New( size );
+
+  return CameraActor(internal.Get());
+}
+
+CameraActor::CameraActor(Internal::CameraActor* internal)
+: Actor(internal)
+{
+}
+
+CameraActor CameraActor::DownCast( BaseHandle handle )
+{
+  return CameraActor( dynamic_cast<Dali::Internal::CameraActor*>(handle.GetObjectPtr()) );
+}
+
+CameraActor::CameraActor()
+{
+}
+
+CameraActor::~CameraActor()
+{
+}
+
+CameraActor::CameraActor(const CameraActor& copy)
+: Actor(copy)
+{
+}
+
+CameraActor& CameraActor::operator=(const CameraActor& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void CameraActor::SetType( Dali::Camera::Type type )
+{
+  GetImplementation(*this).SetType(type);
+}
+
+Dali::Camera::Type CameraActor::GetType() const
+{
+  return GetImplementation(*this).GetType();
+}
+
+void CameraActor::SetProjectionMode( Dali::Camera::ProjectionMode mode )
+{
+  GetImplementation(*this).SetProjectionMode( mode );
+}
+
+Dali::Camera::ProjectionMode CameraActor::GetProjectionMode() const
+{
+  return GetImplementation(*this).GetProjectionMode();
+}
+
+void CameraActor::SetFieldOfView( float fieldOfView )
+{
+  GetImplementation(*this).SetFieldOfView(fieldOfView);
+}
+
+float CameraActor::GetFieldOfView( )
+{
+  return GetImplementation(*this).GetFieldOfView();
+}
+
+void CameraActor::SetAspectRatio( float aspectRatio )
+{
+  GetImplementation(*this).SetAspectRatio(aspectRatio);
+}
+
+float CameraActor::GetAspectRatio( )
+{
+  return GetImplementation(*this).GetAspectRatio();
+}
+
+void CameraActor::SetNearClippingPlane( float nearClippingPlane )
+{
+  GetImplementation(*this).SetNearClippingPlane(nearClippingPlane);
+}
+
+float CameraActor::GetNearClippingPlane( )
+{
+  return GetImplementation(*this).GetNearClippingPlane();
+}
+
+void CameraActor::SetFarClippingPlane( float farClippingPlane )
+{
+  GetImplementation(*this).SetFarClippingPlane(farClippingPlane);
+}
+
+float CameraActor::GetFarClippingPlane( )
+{
+  return GetImplementation(*this).GetFarClippingPlane();
+}
+
+void CameraActor::SetTargetPosition( const Vector3& targetPosition )
+{
+  GetImplementation(*this).SetTargetPosition(targetPosition);
+}
+
+Vector3 CameraActor::GetTargetPosition() const
+{
+  return GetImplementation(*this).GetTargetPosition();
+}
+
+void CameraActor::SetInvertYAxis(bool invertYAxis)
+{
+  GetImplementation(*this).SetInvertYAxis(invertYAxis);
+}
+
+bool CameraActor::GetInvertYAxis()
+{
+  return GetImplementation(*this).GetInvertYAxis();
+}
+
+void CameraActor::SetPerspectiveProjection( const Size& size )
+{
+  GetImplementation(*this).SetPerspectiveProjection( size );
+}
+
+void CameraActor::SetOrthographicProjection( const Vector2& size )
+{
+  GetImplementation(*this).SetOrthographicProjection( size );
+}
+
+void CameraActor::SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far )
+{
+  GetImplementation(*this).SetOrthographicProjection( left, right, top, bottom, near, far );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/camera-actor.h b/dali/public-api/actors/camera-actor.h
new file mode 100644 (file)
index 0000000..432b157
--- /dev/null
@@ -0,0 +1,369 @@
+#ifndef __DALI_CAMERA_ACTOR_H__
+#define __DALI_CAMERA_ACTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/actors/actor.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class CameraActor;
+}
+
+namespace Camera
+{
+/**
+ * @brief Type determines how camera operates.
+ * @since_tizen 2.4
+ */
+enum Type
+{
+  FREE_LOOK,      ///< Camera orientation is taken from CameraActor
+  LOOK_AT_TARGET, ///< Camera is oriented to always look at a target
+};
+
+/**
+ * @brief Projection modes.
+ * @since_tizen 2.4
+ */
+enum ProjectionMode
+{
+  PERSPECTIVE_PROJECTION,    ///< Distance causes foreshortening; objects further from the camera appear smaller
+  ORTHOGRAPHIC_PROJECTION,    ///< Relative distance from the camera does not affect the size of objects
+};
+
+} // namespace Camera
+
+/**
+ * @brief Controls a camera.
+ *
+ * Allows the developer to use actor semantics to control a camera.
+ *
+ * There are two types of camera actor, FREE_LOOK and LOOK_AT_TARGET. By default
+ * the camera actor will be FREE_LOOK.
+ *
+ * A FREE_LOOK camera uses actor's orientation to control where the camera is looking.
+ * If no additional rotations are specified, the camera looks in the negative Z direction.
+ *
+ * For LOOK_AT_TARGET the actor's orientation is ignored, instead the camera looks at TARGET_POSITION
+ * in world coordinates.
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API CameraActor : public Actor
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the CameraActor class.
+   * Properties additional to Actor.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      TYPE = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, ///< name "type",                  type std::string
+      PROJECTION_MODE,                                   ///< name "projection-mode",       type std::string
+      FIELD_OF_VIEW,                                     ///< name "field-of-view",         type float
+      ASPECT_RATIO,                                      ///< name "aspect-ratio",          type float
+      NEAR_PLANE_DISTANCE,                               ///< name "near-plane-distance",   type float
+      FAR_PLANE_DISTANCE,                                ///< name "far-plane-distance",    type float
+      LEFT_PLANE_DISTANCE,                               ///< name "left-plane-distance",   type float
+      RIGHT_PLANE_DISTANCE,                              ///< name "right-plane-distance",  type float
+      TOP_PLANE_DISTANCE,                                ///< name "top-plane-distance",    type float
+      BOTTOM_PLANE_DISTANCE,                             ///< name "bottom-plane-distance", type float
+      TARGET_POSITION,                                   ///< name "target-position",       type Vector3
+      PROJECTION_MATRIX,                                 ///< name "projection-matrix",     type Matrix
+      VIEW_MATRIX,                                       ///< name "view-matrix",           type Matrix
+      INVERT_Y_AXIS,                                     ///< name "invert-y-axis",         type bool
+    };
+  };
+
+  /**
+   * @brief Create an uninitialized CameraActor handle.
+   *
+   * Initialise it using CameraActor::New().  Calling member functions
+   * with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  CameraActor();
+
+  /**
+   * @brief Create a CameraActor object.
+   *
+   * Sets the default camera perspective projection for the stage's size. @see SetPerspectiveProjection().
+   * @since_tizen 2.4
+   * @return the newly created camera actor.
+   */
+  static CameraActor New();
+
+  /**
+   * @brief Create a CameraActor object.
+   *
+   * Sets the default camera perspective projection for the given canvas size. @see SetPerspectiveProjection().
+   *
+   * @since_tizen 2.4
+   * @param[in] size The canvas size.
+   * @return the newly created camera actor.
+   */
+  static CameraActor New( const Size& size );
+
+  /**
+   * @brief Downcast an Object handle to CameraActor.
+   *
+   * If handle points to a CameraActor the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a CameraActor or an uninitialized handle
+   */
+  static CameraActor DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~CameraActor();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] copy The actor to copy.
+   */
+  CameraActor(const CameraActor& copy);
+
+  /**
+   * @brief Assignment operator
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs The actor to copy.
+   */
+  CameraActor& operator=(const CameraActor& rhs);
+
+  /**
+   * @brief Set the camera type.
+   * The default type is Dali::Camera::FREE_LOOK
+   * @since_tizen 2.4
+   * @param[in] type The camera type
+   */
+  void SetType( Dali::Camera::Type type );
+
+  /**
+   * @brief Get the type of the camera.
+   *
+   * @since_tizen 2.4
+   * @return the type of camera
+   */
+  Dali::Camera::Type GetType() const;
+
+  /**
+   * @brief Set the projection mode.
+   *
+   * @since_tizen 2.4
+   * @param[in] mode One of PERSPECTIVE_PROJECTION or ORTHOGRAPHIC_PROJECTION
+   */
+  void SetProjectionMode( Dali::Camera::ProjectionMode mode );
+
+  /**
+   * @brief Get the projection mode.
+   *
+   * @since_tizen 2.4
+   * @return One of PERSPECTIVE_PROJECTION or ORTHOGRAPHIC_PROJECTION
+   */
+  Dali::Camera::ProjectionMode GetProjectionMode() const;
+
+  /**
+   * @brief Set the field of view.
+   *
+   * @since_tizen 2.4
+   * @param[in] fieldOfView The field of view in radians
+   */
+  void SetFieldOfView( float fieldOfView );
+
+  /**
+   * @brief Get the field of view in Radians.
+   *
+   * The default field of view is 45 degrees
+   * @since_tizen 2.4
+   * @return The field of view in radians
+   */
+  float GetFieldOfView( );
+
+  /**
+   * @brief Set the aspect ratio.
+   *
+   * @since_tizen 2.4
+   * @param[in] aspectRatio The aspect ratio
+   */
+  void SetAspectRatio( float aspectRatio );
+
+  /**
+   * @brief Get the aspect ratio of the camera.
+   *
+   * The default aspect ratio is 4.0f/3.0f
+   * @since_tizen 2.4
+   * @return the aspect ratio
+   */
+  float GetAspectRatio( );
+
+  /**
+   * @brief Sets the near clipping plane distance.
+   *
+   * @since_tizen 2.4
+   * @param[in] nearClippingPlane distance of the near clipping plane
+   */
+  void SetNearClippingPlane( float nearClippingPlane );
+
+  /**
+   * @brief Get the near clipping plane distance.
+   *
+   * The default near clipping plane is 800.0f, to match the default screen height
+   * Reduce this value to see objects closer to the camera
+   * @since_tizen 2.4
+   * @return the near clipping plane value
+   */
+  float GetNearClippingPlane( );
+
+  /**
+   * @brief Sets the far clipping plane distance.
+   *
+   * @since_tizen 2.4
+   * @param[in] farClippingPlane distance of the far clipping plane
+   */
+  void SetFarClippingPlane( float farClippingPlane );
+
+  /**
+   * @brief Get the far clipping plane distance.
+   *
+   * The default value is the default near clipping plane + (0xFFFF>>4)
+   * @since_tizen 2.4
+   * @return the far clipping plane value
+   */
+  float GetFarClippingPlane( );
+
+  /**
+   * @brief Set the target position of the camera.
+   *
+   * @since_tizen 2.4
+   * @param[in] targetPosition The position of the target to look at
+   * @pre Camera type is LOOK_AT_TARGET
+   */
+  void SetTargetPosition( const Vector3& targetPosition );
+
+  /**
+   * @brief Get Camera Target position.
+   *
+   * The target position is Vector3::ZERO
+   * @since_tizen 2.4
+   * @return The target position of the camera
+   * @pre Camera type is LOOK_AT_TARGET
+   */
+  Vector3 GetTargetPosition() const;
+
+  /**
+   * @brief Request for an inversion on the Y axis on the projection calculation.
+   *
+   * The default value is not inverted.
+   * @since_tizen 2.4
+   * @param[in] invertYAxis True if the Y axis should be inverted
+   */
+  void SetInvertYAxis(bool invertYAxis);
+
+  /**
+   * @brief Get whether the Y axis is inverted.
+   *
+   * @since_tizen 2.4
+   * @return True if the Y axis is inverted, false otherwise
+   */
+  bool GetInvertYAxis();
+
+  /**
+   * @brief Sets the default camera perspective projection for the given canvas size.
+   *
+   * Sets the near and far clipping planes, the field of view, the aspect ratio
+   * and the Z position of the actor based on the canvas size so that 1 unit in
+   * XY (z=0) plane is 1 pixel on screen.
+   *
+   * If the canvas size is ZERO, it sets the default camera perspective
+   * projection for the stage's size.
+   *
+   * @since_tizen 2.4
+   * @param[in] size The canvas size.
+   * @pre If size is non ZERO, \e width and \e height must be greater than zero.
+   *
+   */
+  void SetPerspectiveProjection( const Size& size );
+
+  /**
+   * @brief Sets the camera projection to use orthographic projection.
+   *
+   * The XY plane is centered on the camera axis. The units in the X/Y
+   * plane directly equate to pixels on an equivalently sized
+   * framebuffer.
+   *
+   * The Z position of the actor, and the near and far clip planes of the
+   * bounding box match those that would be created by using
+   * SetPerspectiveProjection with the same size.
+   *
+   * @since_tizen 2.4
+   * @param[in] size Size of XY plane (normal to camera axis)
+   */
+  void SetOrthographicProjection( const Size& size );
+
+  /**
+   * @brief Sets the camera projection to use orthographic projection with the given clip planes.
+   *
+   * This does not change the Z value of the camera actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] left Distance to left clip plane (normal to camera axis)
+   * @param[in] right Distance to right clip plane (normal to camera axis)
+   * @param[in] top Distance to top clip plane (normal to camera axis)
+   * @param[in] bottom Distance to bottom clip plane (normal to camera axis)
+   * @param[in] near Distance to the near clip plane (along camera axis)
+   * @param[in] far Distance to the far clip plane (along camera axis)
+   */
+  void SetOrthographicProjection( float left, float right, float top, float bottom, float near, float far );
+
+public: // Not intended for use by Application developers
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] actor A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL CameraActor(Internal::CameraActor* actor);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CAMERA_ACTOR_H__
diff --git a/dali/public-api/actors/custom-actor-impl.cpp b/dali/public-api/actors/custom-actor-impl.cpp
new file mode 100644 (file)
index 0000000..08022ba
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/custom-actor-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/actors/custom-actor-internal.h>
+
+namespace Dali
+{
+
+CustomActorImpl::~CustomActorImpl()
+{
+}
+
+CustomActor CustomActorImpl::Self() const
+{
+  return CustomActor(mOwner);
+}
+
+void CustomActorImpl::OnPropertySet( Property::Index index, Property::Value propertyValue )
+{
+}
+
+CustomActorImpl::CustomActorImpl( ActorFlags flags )
+: mOwner(NULL),
+  mFlags( flags )
+{
+}
+
+void CustomActorImpl::Initialize(Internal::CustomActor& owner)
+{
+  DALI_ASSERT_DEBUG(mOwner == NULL); // should not already be owned
+
+  mOwner = &owner;
+}
+
+Internal::CustomActor* CustomActorImpl::GetOwner() const
+{
+  return mOwner;
+}
+
+bool CustomActorImpl::RequiresTouchEvents() const
+{
+  return ( mFlags & REQUIRES_TOUCH_EVENTS );
+}
+
+bool CustomActorImpl::RequiresHoverEvents() const
+{
+  return ( mFlags & REQUIRES_HOVER_EVENTS );
+}
+
+bool CustomActorImpl::RequiresWheelEvents() const
+{
+  return ( mFlags & REQUIRES_WHEEL_EVENTS );
+}
+
+bool CustomActorImpl::IsRelayoutEnabled() const
+{
+  return ( mFlags & DISABLE_SIZE_NEGOTIATION ) == 0;
+}
+
+void CustomActorImpl::RelayoutRequest()
+{
+  mOwner->RelayoutRequest();
+}
+
+float CustomActorImpl::GetHeightForWidthBase( float width )
+{
+  return mOwner->GetHeightForWidthBase( width );
+}
+
+float CustomActorImpl::GetWidthForHeightBase( float height )
+{
+  return mOwner->GetWidthForHeightBase( height );
+}
+
+float CustomActorImpl::CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension )
+{
+  return mOwner->CalculateChildSizeBase( child, dimension );
+}
+
+bool CustomActorImpl::RelayoutDependentOnChildrenBase( Dimension::Type dimension )
+{
+  return mOwner->RelayoutDependentOnChildrenBase( dimension );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/custom-actor-impl.h b/dali/public-api/actors/custom-actor-impl.h
new file mode 100644 (file)
index 0000000..ef281fc
--- /dev/null
@@ -0,0 +1,446 @@
+#ifndef __DALI_CUSTOM_ACTOR_IMPL_H__
+#define __DALI_CUSTOM_ACTOR_IMPL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/math/compile-time-math.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class CustomActor;
+}
+
+class Actor;
+class Animation;
+class CustomActor;
+class CustomActorImpl;
+class RelayoutContainer;
+struct KeyEvent;
+struct TouchEvent;
+struct HoverEvent;
+struct WheelEvent;
+struct Vector2;
+struct Vector3;
+
+/**
+ * @brief Pointer to Dali::CustomActorImpl object.
+ * @since_tizen 2.4
+ */
+typedef IntrusivePtr<CustomActorImpl> CustomActorImplPtr;
+
+/**
+ * @brief CustomActorImpl is an abstract base class for custom control implementations.
+ *
+ * This provides a series of pure virtual methods, which are called when actor-specific events occur.
+ * An CustomActorImpl is typically owned by a single CustomActor instance; see also CustomActor::New(CustomActorImplPtr).
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API CustomActorImpl : public Dali::RefObject
+{
+public:
+
+  class Extension; ///< Forward declare future extension interface
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~CustomActorImpl();
+
+  /**
+   * @brief Used by derived CustomActorImpl instances, to access the public Actor interface.
+   *
+   * @since_tizen 2.4
+   * @return A pointer to self, or an uninitialized pointer if the CustomActorImpl is not owned.
+   */
+  CustomActor Self() const;
+
+  /**
+   * @brief Called after the actor has been connected to the stage.
+   *
+   * When an actor is connected, it will be directly or indirectly parented to the root Actor.
+   * @since_tizen 2.4
+   * @note The root Actor is provided automatically by Dali::Stage, and is always considered to be connected.
+   *
+   * @note When the parent of a set of actors is connected to the stage, then all of the children
+   * will received this callback.
+   *
+   * For the following actor tree, the callback order will be A, B, D, E, C, and finally F.
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   *
+   *   @param[in] depth The depth in the hierarchy for the actor
+   */
+  virtual void OnStageConnection( int depth ) = 0;
+
+  /**
+   * @brief Called after the actor has been disconnected from the stage.
+   *
+   * If an actor is disconnected it either has no parent, or is parented to a disconnected actor.
+   *
+   * @since_tizen 2.4
+   * @note When the parent of a set of actors is disconnected to the stage, then all of the children
+   * will received this callback, starting with the leaf actors.
+   *
+   * For the following actor tree, the callback order will be D, E, B, F, C, and finally A.
+   *
+   *       A (parent)
+   *      / \
+   *     B   C
+   *    / \   \
+   *   D   E   F
+   */
+  virtual void OnStageDisconnection() = 0;
+
+  /**
+   * @brief Called after a child has been added to the owning actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] child The child which has been added.
+   */
+  virtual void OnChildAdd(Actor& child) = 0;
+
+  /**
+   * @brief Called after a child has been removed from the owning actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] child The child being removed.
+   */
+  virtual void OnChildRemove(Actor& child) = 0;
+
+  /**
+   * @brief Called when the owning actor property is set.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The Property index that was set.
+   * @param[in] propertyValue The value to set.
+   */
+  virtual void OnPropertySet( Property::Index index, Property::Value propertyValue );
+
+  /**
+   * @brief Called when the owning actor's size is set e.g. using Actor::SetSize().
+   *
+   * @since_tizen 2.4
+   * @param[in] targetSize The target size. Note that this target size may not match the size returned via Actor::GetSize().
+   */
+  virtual void OnSizeSet(const Vector3& targetSize) = 0;
+
+  /**
+   * @brief Called when the owning actor's size is animated e.g. using Animation::AnimateTo( Property( actor, Actor::Property::SIZE ), ... ).
+   *
+   * @since_tizen 2.4
+   * @param[in] animation The object which is animating the owning actor.
+   * @param[in] targetSize The target size. Note that this target size may not match the size returned via Actor::GetSize().
+   */
+  virtual void OnSizeAnimation(Animation& animation, const Vector3& targetSize) = 0;
+
+  /**
+   * @brief Called after a touch-event is received by the owning actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] event The touch event.
+   * @return True if the event should be consumed.
+   * @note This must be enabled during construction; see CustomActorImpl::CustomActorImpl(bool)
+   */
+  virtual bool OnTouchEvent(const TouchEvent& event) = 0;
+
+  /**
+   * @brief Called after a hover-event is received by the owning actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] event The hover event.
+   * @return True if the event should be consumed.
+   * @note This must be enabled during construction; see CustomActorImpl::SetRequiresHoverEvents(bool)
+   */
+  virtual bool OnHoverEvent(const HoverEvent& event) = 0;
+
+  /**
+   * @brief Called after a key-event is received by the actor that has had its focus set.
+   *
+   * @since_tizen 2.4
+   * @param[in] event the Key Event
+   * @return True if the event should be consumed.
+   */
+  virtual bool OnKeyEvent(const KeyEvent& event) = 0;
+
+  /**
+   * @brief Called after a wheel-event is received by the owning actor.
+   *
+   * @since_tizen 2.4
+   * @param[in] event The wheel event.
+   * @return True if the event should be consumed.
+   * @note This must be enabled during construction; see CustomActorImpl::SetRequiresWheelEvents(bool)
+   */
+  virtual bool OnWheelEvent(const WheelEvent& event) = 0;
+
+  /**
+   * @brief Called after the size negotiation has been finished for this control.
+   *
+   * The control is expected to assign this given size to itself/its children.
+   *
+   * Should be overridden by derived classes if they need to layout
+   * actors differently after certain operations like add or remove
+   * actors, resize or after changing specific properties.
+   *
+   * Note! As this function is called from inside the size negotiation algorithm, you cannot
+   * call RequestRelayout (the call would just be ignored)
+   *
+   * @since_tizen 2.4
+   * @param[in]      size       The allocated size.
+   * @param[in,out]  container  The control should add actors to this container that it is not able
+   *                            to allocate a size for.
+   */
+  virtual void OnRelayout( const Vector2& size, RelayoutContainer& container ) = 0;
+
+  /**
+   * @brief Notification for deriving classes
+   *
+   * @since_tizen 2.4
+   * @param[in] policy The policy being set
+   * @param[in] dimension The dimension the policy is being set for
+   */
+  virtual void OnSetResizePolicy( ResizePolicy::Type policy, Dimension::Type dimension ) = 0;
+
+  /**
+   * @brief Return the natural size of the actor
+   *
+   * @since_tizen 2.4
+   * @return The actor's natural size
+   */
+  virtual Vector3 GetNaturalSize() = 0;
+
+  /**
+   * @brief Calculate the size for a child
+   *
+   * @since_tizen 2.4
+   * @param[in] child The child actor to calculate the size for
+   * @param[in] dimension The dimension to calculate the size for. E.g. width or height.
+   * @return Return the calculated size for the given dimension
+   */
+  virtual float CalculateChildSize( const Dali::Actor& child, Dimension::Type dimension ) = 0;
+
+  /**
+   * @brief This method is called during size negotiation when a height is required for a given width.
+   *
+   * Derived classes should override this if they wish to customize the height returned.
+   *
+   * @since_tizen 2.4
+   * @param width to use.
+   * @return the height based on the width.
+   */
+  virtual float GetHeightForWidth( float width ) = 0;
+
+  /**
+   * @brief This method is called during size negotiation when a width is required for a given height.
+   *
+   * Derived classes should override this if they wish to customize the width returned.
+   *
+   * @since_tizen 2.4
+   * @param height to use.
+   * @return the width based on the width.
+   */
+  virtual float GetWidthForHeight( float height ) = 0;
+
+  /**
+   * @brief Determine if this actor is dependent on it's children for relayout
+   *
+   * @since_tizen 2.4
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's children
+   */
+  virtual bool RelayoutDependentOnChildren( Dimension::Type dimension = Dimension::ALL_DIMENSIONS ) = 0;
+
+  /**
+   * @brief Virtual method to notify deriving classes that relayout dependencies have been
+   * met and the size for this object is about to be calculated for the given dimension
+   *
+   * @since_tizen 2.4
+   * @param dimension The dimension that is about to be calculated
+   */
+  virtual void OnCalculateRelayoutSize( Dimension::Type dimension ) = 0;
+
+  /**
+   * @brief Virtual method to notify deriving classes that the size for a dimension
+   * has just been negotiated
+   *
+   * @since_tizen 2.4
+   * @param[in] size The new size for the given dimension
+   * @param[in] dimension The dimension that was just negotiated
+   */
+  virtual void OnLayoutNegotiated( float size, Dimension::Type dimension ) = 0;
+
+  /**
+   * @brief Retrieve the extension for this control
+   *
+   * @since_tizen 2.4
+   * @return The extension if available, NULL otherwise
+   */
+  virtual Extension* GetExtension()
+  {
+    return NULL;
+  }
+
+protected: // For derived classes
+
+  // Flags for the constructor
+  enum ActorFlags
+  {
+    ACTOR_BEHAVIOUR_NONE          = 0,
+    DISABLE_SIZE_NEGOTIATION      = 1 << 0,     ///< True if control does not need size negotiation, i.e. it can be skipped in the algorithm
+    REQUIRES_TOUCH_EVENTS         = 1 << 1,     ///< True if the OnTouchEvent() callback is required.
+    REQUIRES_HOVER_EVENTS         = 1 << 2,     ///< True if the OnHoverEvent() callback is required.
+    REQUIRES_WHEEL_EVENTS   = 1 << 3,     ///< True if the OnWheelEvent() callback is required.
+
+    LAST_ACTOR_FLAG                             ///< Special marker for last actor flag
+  };
+
+  static const int ACTOR_FLAG_COUNT = Log< LAST_ACTOR_FLAG - 1 >::value + 1;      ///< Value for deriving classes to continue on the flag enum
+
+  /**
+   * @brief Create a CustomActorImpl.
+   * @since_tizen 2.4
+   * @param[in] flags Bitfield of ActorFlags to define behaviour
+   */
+  CustomActorImpl( ActorFlags flags );
+
+  // Size negotiation helpers
+
+  /**
+   * @brief Request a relayout, which means performing a size negotiation on this actor, its parent and children (and potentially whole scene)
+   *
+   * This method can also be called from a derived class every time it needs a different size.
+   * At the end of event processing, the relayout process starts and
+   * all controls which requested Relayout will have their sizes (re)negotiated.
+   *
+   * @since_tizen 2.4
+   * @note RelayoutRequest() can be called multiple times; the size negotiation is still
+   * only performed once, i.e. there is no need to keep track of this in the calling side.
+   */
+  void RelayoutRequest();
+
+  /**
+   * @brief provides the Actor implementation of GetHeightForWidth
+   * @since_tizen 2.4
+   * @param width to use.
+   * @return the height based on the width.
+   */
+  float GetHeightForWidthBase( float width );
+
+  /**
+   * @brief provides the Actor implementation of GetWidthForHeight
+   * @since_tizen 2.4
+   * @param height to use.
+   * @return the width based on the height.
+   */
+  float GetWidthForHeightBase( float height );
+
+  /**
+   * @brief Calculate the size for a child using the base actor object
+   *
+   * @since_tizen 2.4
+   * @param[in] child The child actor to calculate the size for
+   * @param[in] dimension The dimension to calculate the size for. E.g. width or height.
+   * @return Return the calculated size for the given dimension
+   */
+  float CalculateChildSizeBase( const Dali::Actor& child, Dimension::Type dimension );
+
+  /**
+   * @brief Determine if this actor is dependent on it's children for relayout from the base class
+   *
+   * @since_tizen 2.4
+   * @param dimension The dimension(s) to check for
+   * @return Return if the actor is dependent on it's children
+   */
+  bool RelayoutDependentOnChildrenBase( Dimension::Type dimension = Dimension::ALL_DIMENSIONS );
+
+public: // Not intended for application developers
+
+  /**
+   * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+   * @since_tizen 2.4
+   * @param[in] owner The owning object.
+   * @pre The CustomActorImpl is not already owned.
+   */
+  void Initialize(Internal::CustomActor& owner);
+
+  /**
+   * @brief Get the owner.
+   *
+   * This method is needed when creating additional handle objects to existing objects.
+   * Owner is the Dali::Internal::CustomActor that owns the implementation of the custom actor
+   * inside core. Creation of a handle to Dali public API Actor requires this pointer.
+   * @since_tizen 2.4
+   * @return a pointer to the Actor implementation that owns this custom actor implementation
+   */
+  Internal::CustomActor* GetOwner() const;
+
+  /**
+   * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+   * @since_tizen 2.4
+   * @return True if the OnTouchEvent() callback is required.
+   */
+  bool RequiresTouchEvents() const;
+
+  /**
+   * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+   * @since_tizen 2.4
+   * @return True if the OnHoverEvent() callback is required.
+   */
+  bool RequiresHoverEvents() const;
+
+  /**
+   * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+   * @since_tizen 2.4
+   * @return True if the OnWheelEvent() callback is required.
+   */
+  bool RequiresWheelEvents() const;
+
+  /**
+   * @brief Called when ownership of the CustomActorImpl is passed to a CustomActor.
+   * @since_tizen 2.4
+   * @return Return true if relayout is enabled on the custom actor
+   */
+  bool IsRelayoutEnabled() const;
+
+private:
+
+  Internal::CustomActor* mOwner;        ///< Internal owner of this custom actor implementation
+  ActorFlags mFlags :ACTOR_FLAG_COUNT;  ///< ActorFlags flags to determine behaviour
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CUSTOM_ACTOR_IMPL_H__
diff --git a/dali/public-api/actors/custom-actor.cpp b/dali/public-api/actors/custom-actor.cpp
new file mode 100644 (file)
index 0000000..816db29
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/custom-actor.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/custom-actor-internal.h>
+#include <dali/public-api/object/type-registry.h>
+
+namespace Dali
+{
+
+namespace
+{
+
+using namespace Dali;
+
+BaseHandle Create()
+{
+  // not directly creatable
+  return BaseHandle();
+}
+
+TypeRegistration mType( typeid(Dali::CustomActor), typeid(Dali::Actor), Create );
+
+}
+
+CustomActor::CustomActor()
+{
+}
+
+CustomActor CustomActor::DownCast( BaseHandle handle )
+{
+  return CustomActor( dynamic_cast<Dali::Internal::CustomActor*>(handle.GetObjectPtr()) );
+}
+
+CustomActor::~CustomActor()
+{
+}
+
+CustomActor::CustomActor(const CustomActor& copy)
+: Actor(copy)
+{
+}
+
+CustomActor& CustomActor::operator=(const CustomActor& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+CustomActorImpl& CustomActor::GetImplementation()
+{
+  Internal::CustomActor& internal = GetImpl(*this);
+
+  return internal.GetImplementation();
+}
+
+const CustomActorImpl& CustomActor::GetImplementation() const
+{
+  const Internal::CustomActor& internal = GetImpl(*this);
+
+  return internal.GetImplementation();
+}
+
+CustomActor::CustomActor(CustomActorImpl& implementation)
+: Actor(Internal::CustomActor::New(implementation).Get())
+{
+}
+
+CustomActor::CustomActor(Internal::CustomActor* internal)
+: Actor(internal)
+{
+  // Check we haven't just constructed a new handle, while in the internal custom actors destructor.
+  // This can happen if the user defined CustomActorImpl destructor calls Self(), to create a new handle
+  // to the CustomActor.
+  //
+  // If it's in the destructor then the ref count is zero, so once we've created a new handle it will be 1
+  // Without this check, the actor will be deleted a second time, when the handle is disposed of
+  // causing a crash.
+
+  if (internal)
+  {
+    DALI_ASSERT_ALWAYS(internal->ReferenceCount() != 1 && "Are you trying to use CustomActorImpl::Self() inside a CustomActorImpl destructor?");
+  }
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/custom-actor.h b/dali/public-api/actors/custom-actor.h
new file mode 100644 (file)
index 0000000..6276b3b
--- /dev/null
@@ -0,0 +1,133 @@
+#ifndef __DALI_CUSTOM_ACTOR_H__
+#define __DALI_CUSTOM_ACTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/actors/custom-actor-impl.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class CustomActor;
+}
+
+/**
+ * @brief CustomActor is a base class for custom UI controls.
+ *
+ * The implementation of the control must be supplied; see CustomActorImpl for more details.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API CustomActor : public Actor
+{
+public:
+
+  /**
+   * @brief Create an uninitialized CustomActor handle.
+   *
+   * Only derived versions can be instantiated.
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  CustomActor();
+
+  /**
+   * @brief Downcast an Object handle to CustomActor.
+   *
+   * If handle points to a CustomActor the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a CustomActor or an uninitialized handle
+   */
+  static CustomActor DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~CustomActor();
+
+  /**
+   * @brief Retrieve the custom actor implementation.
+   *
+   * @since_tizen 2.4
+   * @return The implementation.
+   */
+  CustomActorImpl& GetImplementation();
+
+  /**
+   * @brief Retrieve the custom actor implementation.
+   *
+   * @since_tizen 2.4
+   * @return The implementation.
+   */
+  const CustomActorImpl& GetImplementation() const;
+
+  /**
+   * @brief Create an initialised CustomActor.
+   *
+   * @since_tizen 2.4
+   * @param[in] implementation The implementation for this custom actor.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  CustomActor(CustomActorImpl& implementation);
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] copy The actor to copy.
+   */
+  CustomActor(const CustomActor& copy);
+
+  /**
+   * @brief Assignment operator
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs The actor to copy.
+   */
+  CustomActor& operator=(const CustomActor& rhs);
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used internally to create additional CustomActor handles.
+   *
+   * @since_tizen 2.4
+   * @param [in] actor A pointer to a newly allocated Dali resource
+   */
+  CustomActor(Internal::CustomActor* actor);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CUSTOM_ACTOR_H__
diff --git a/dali/public-api/actors/draw-mode.h b/dali/public-api/actors/draw-mode.h
new file mode 100644 (file)
index 0000000..d4b489d
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __DALI_DRAW_MODE_H__
+#define __DALI_DRAW_MODE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace DrawMode
+{
+
+/**
+ * @brief How the actor and it's children will be drawn.
+ *
+ * @since_tizen 2.4
+ * @see Dali::Actor::SetDrawMode()
+ */
+enum Type
+{
+  NORMAL     = 0, ///< binary 00. The default draw-mode
+  OVERLAY_2D = 1, ///< binary 01. Draw the actor and its children as an overlay
+  STENCIL    = 3  ///< binary 11. Draw the actor and its children into the stencil buffer
+};
+
+} // namespace DrawMode
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_DRAW_MODE_H__
diff --git a/dali/public-api/actors/image-actor.cpp b/dali/public-api/actors/image-actor.cpp
new file mode 100644 (file)
index 0000000..d93f0ba
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/image-actor.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/image-actor-impl.h>
+#include <dali/internal/event/images/image-impl.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+const BlendingMode::Type ImageActor::DEFAULT_BLENDING_MODE = BlendingMode::AUTO;
+
+ImageActor::ImageActor()
+{
+}
+
+ImageActor ImageActor::New()
+{
+  Internal::ImageActorPtr internal = Internal::ImageActor::New();
+  return ImageActor( internal.Get() );
+}
+
+ImageActor ImageActor::New(Image image)
+{
+  ImageActor actor = ImageActor::New();
+  actor.SetImage( image );
+
+  return actor;
+}
+
+ImageActor ImageActor::New(Image image, PixelArea pixelArea)
+{
+  ImageActor actor = ImageActor::New();
+  actor.SetImage( image );
+  actor.SetPixelArea( pixelArea );
+
+  return actor;
+}
+
+ImageActor ImageActor::DownCast( BaseHandle handle )
+{
+  return ImageActor( dynamic_cast<Dali::Internal::ImageActor*>(handle.GetObjectPtr()) );
+}
+
+ImageActor::~ImageActor()
+{
+}
+
+ImageActor::ImageActor(const ImageActor& copy)
+: Actor(copy)
+{
+}
+
+ImageActor& ImageActor::operator=(const ImageActor& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void ImageActor::SetImage(Image image)
+{
+  Internal::ImagePtr imagePtr;
+  if( image )
+  {
+    imagePtr = &GetImplementation(image);
+  }
+  GetImplementation(*this).SetImage( imagePtr );
+}
+
+Image ImageActor::GetImage()
+{
+  Internal::ImagePtr imagePtr( GetImplementation(*this).GetImage() );
+  return Dali::Image( imagePtr.Get() );
+}
+
+void ImageActor::SetPixelArea(const PixelArea& pixelArea)
+{
+  GetImplementation(*this).SetPixelArea(pixelArea);
+}
+
+ImageActor::PixelArea ImageActor::GetPixelArea() const
+{
+  return GetImplementation(*this).GetPixelArea();
+}
+
+void ImageActor::SetStyle(Style style)
+{
+  GetImplementation(*this).SetStyle(style);
+}
+
+ImageActor::Style ImageActor::GetStyle() const
+{
+  return GetImplementation(*this).GetStyle();
+}
+
+void ImageActor::SetNinePatchBorder(const Vector4& border)
+{
+  GetImplementation(*this).SetNinePatchBorder(border, true/*in pixels*/);
+}
+
+Vector4 ImageActor::GetNinePatchBorder() const
+{
+  return GetImplementation(*this).GetNinePatchBorder();
+}
+
+void ImageActor::SetSortModifier(float modifier)
+{
+  GetImplementation(*this).SetSortModifier(modifier);
+}
+
+float ImageActor::GetSortModifier() const
+{
+  return GetImplementation(*this).GetSortModifier();
+}
+
+void ImageActor::SetBlendMode( BlendingMode::Type mode )
+{
+  GetImplementation(*this).SetBlendMode( mode );
+}
+
+BlendingMode::Type ImageActor::GetBlendMode() const
+{
+  return GetImplementation(*this).GetBlendMode();
+}
+
+void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba )
+{
+  GetImplementation(*this).SetBlendFunc( srcFactorRgba, destFactorRgba );
+}
+
+void ImageActor::SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                                    BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha )
+{
+  GetImplementation(*this).SetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void ImageActor::GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                                    BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const
+{
+  GetImplementation(*this).GetBlendFunc( srcFactorRgb, destFactorRgb, srcFactorAlpha, destFactorAlpha );
+}
+
+void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgba )
+{
+  GetImplementation(*this).SetBlendEquation( equationRgba );
+}
+
+void ImageActor::SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha )
+{
+  GetImplementation(*this).SetBlendEquation( equationRgb, equationAlpha );
+}
+
+void ImageActor::GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const
+{
+  GetImplementation(*this).GetBlendEquation( equationRgb, equationAlpha );
+}
+
+void ImageActor::SetBlendColor( const Vector4& color )
+{
+  GetImplementation(*this).SetBlendColor( color );
+}
+
+const Vector4& ImageActor::GetBlendColor() const
+{
+  return GetImplementation(*this).GetBlendColor();
+}
+
+void ImageActor::SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter )
+{
+  GetImplementation(*this).SetFilterMode( minFilter, magFilter );
+}
+
+void ImageActor::GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter ) const
+{
+  GetImplementation(*this).GetFilterMode( minFilter, magFilter );
+}
+
+void ImageActor::SetShaderEffect(ShaderEffect effect)
+{
+  GetImplementation(*this).SetShaderEffect(GetImplementation(effect));
+}
+
+ShaderEffect ImageActor::GetShaderEffect() const
+{
+  Internal::ShaderEffectPtr internal = GetImplementation(*this).GetShaderEffect();
+
+  return ShaderEffect(internal.Get());
+}
+
+void ImageActor::RemoveShaderEffect()
+{
+  GetImplementation(*this).RemoveShaderEffect();
+}
+
+
+ImageActor::ImageActor(Internal::ImageActor* internal)
+: Actor(internal)
+{
+}
+
+void SetShaderEffectRecursively( Actor actor, ShaderEffect effect )
+{
+  // only do something if the actor and effect are valid
+  if( actor && effect )
+  {
+    // first remove from this actor
+    ImageActor imageActor = ImageActor::DownCast( actor );
+    if( imageActor )
+    {
+      imageActor.SetShaderEffect( effect );
+    }
+    // then all children recursively
+    const unsigned int count = actor.GetChildCount();
+    for( unsigned int index = 0; index < count; ++index )
+    {
+      Actor child( actor.GetChildAt( index ) );
+      SetShaderEffectRecursively( child, effect );
+    }
+  }
+}
+
+void RemoveShaderEffectRecursively( Actor actor )
+{
+  // only do something if the actor is valid
+  if( actor )
+  {
+    // first remove from this actor
+    ImageActor imageActor = ImageActor::DownCast( actor );
+    if( imageActor )
+    {
+      imageActor.RemoveShaderEffect();
+    }
+    // then all children recursively
+    const unsigned int count = actor.GetChildCount();
+    for( unsigned int index = 0; index < count; ++index )
+    {
+      Actor child( actor.GetChildAt( index ) );
+      RemoveShaderEffectRecursively( child );
+    }
+  }
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/image-actor.h b/dali/public-api/actors/image-actor.h
new file mode 100644 (file)
index 0000000..b0ad736
--- /dev/null
@@ -0,0 +1,562 @@
+#ifndef __DALI_IMAGE_ACTOR_H__
+#define __DALI_IMAGE_ACTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/shader-effects/shader-effect.h>
+#include <dali/public-api/actors/blending.h>
+#include <dali/public-api/actors/sampling.h>
+
+namespace Dali
+{
+/**
+ * @internal
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class ImageActor;
+}
+
+/**
+ * @deprecated Use ImageView instead.
+ * @brief An actor for displaying images.
+ *
+ * Allows the developer to add an actor to stage which displays the content of an Image object.
+ *
+ * By default ImageActor can be viewed from all angles.
+ *
+ * If an ImageActor is created without setting size, then the actor takes the size of the image -
+ * this is the natural size.
+ * Setting a size on the ImageActor, e.g through the SetSize api or through an animation will
+ * stop the natural size being used.
+ *
+ * If a pixel area is set on an ImageActor with natural size, the actor size will change
+ * to match the pixel area. If a pixel area is set on an ImageActor that has had it's size set,
+ * then the size doesn't change, and the partial image will be stretched to fill the set size.
+ *
+ * Clearing the pixel area on an Image actor with natural size will cause the actor to show the
+ * whole image again, and will change size back to that of the image.
+ *
+ * Clearing the pixel area on an Image actor with a set size will cause the actor to show the
+ * whole image again, but will not change the image size.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ImageActor : public Actor
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the ImageActor class.
+   * Properties additional to RenderableActor.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      PIXEL_AREA = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, ///< name "pixel-area",  type Rect<int>
+      STYLE,                                                   ///< name "style",       type std::string
+      BORDER,                                                  ///< name "border",      type Vector4
+      IMAGE,                                                   ///< name "image",       type Map {"filename":"", "load-policy":...}
+    };
+  };
+
+  /**
+   * @brief Style determines how the Image is rendered.
+   *
+   * @code
+   * STYLE_QUAD:
+   *
+   *  0---------2           0-----------------2
+   *  |        /|           |                /|
+   *  |  A    / |           |      A       /  |
+   *  |      /  |           |            /    |
+   *  |     /   | SCALE (X) |          /      |
+   *  |    /    | --------> |        /        |
+   *  |   /     |           |      /          |
+   *  |  /      |           |    /            |
+   *  | /    B  |           |  /        B     |
+   *  |/        |           |/                |
+   *  1---------3           1-----------------3
+   *
+   * Image is rendered as a textured rectangle. The texture
+   * is scaled uniformly as the quad is resized.
+   *
+   * STYLE_NINE_PATCH:
+   *
+   *  |---|---------------|---|       |---|-----------------------------|---|
+   *  | 1 |       2       | 3 |       | 1 |              2              | 3 |
+   *  |---|---------------|---|       |---|-----------------------------|---|
+   *  |   |               |   |       |   |                             |   |
+   *  |   |               |   |       |   |                             |   |
+   *  | 4 |       5       | 6 | SCALE |   |                             |   |
+   *  |   |               |   | ----> |   |                             |   |
+   *  |   |               |   |       | 4 |              5              | 6 |
+   *  |-------------------|---|       |   |                             |   |
+   *  | 7 |       8       | 9 |       |   |                             |   |
+   *  |---|---------------|---|       |   |                             |   |
+   *                                  |---------------------------------|---|
+   *                                  | 7 |              8              | 9 |
+   *                                  |---|-----------------------------|---|
+   *
+   * Image is rendered as a textured rectangle. The texture
+   * is scaled differently over each of the 9 sections.
+   *
+   * STYLE_NINE_PATCH_NO_CENTER:
+   *
+   * Image is rendered in the same way as STYLE_NINE_PATCH,
+   * but the Center Section (5) is not rendered.
+   * @endcode
+   *
+   * Visualise a Picture Frame:
+   *
+   * - Corner sections (1,3,7,9) are not scaled, regardless
+   * of how big the Image is.
+   * - Horizontal edge sections (2,8) are scaled only in the
+   * X axis as the image increases in width.
+   * - Vertical edge sections (4,6) are scaled only in the
+   * Y axis as the image increases in height.
+   * - Center section (5) is scaled in both X and Y axes as
+   * the image increases in width and/or height.
+   *
+   * Note: If GRID hints are enabled (via a Shader that requires it),
+   * the above geometry will be further subdivided into rectangles of
+   * approx. 40x40 in size. STYLE_NINE_PATCH_NO_CENTER is not supported
+   * yet when GRID hints are enabled.
+   * @since_tizen 2.4
+   */
+  enum Style
+  {
+    STYLE_QUAD,                 ///< As a simple quad.
+    STYLE_NINE_PATCH,           ///< As a nine-patch.
+    STYLE_NINE_PATCH_NO_CENTER  ///< As a nine-patch without center section being rendered.
+  };
+
+  /**
+   * @brief Pixel area is relative to the top-left (0,0) of the image.
+   * @since_tizen 2.4
+   */
+  typedef Rect<int> PixelArea;
+
+  static const BlendingMode::Type DEFAULT_BLENDING_MODE; ///< default value is BlendingMode::AUTO
+
+  /**
+   * @brief Create an uninitialized ImageActor handle.
+   *
+   * This can be initialized with ImageActor::New(...)
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  ImageActor();
+
+  /**
+   * @brief Create an empty image actor object.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated actor.
+   */
+  static ImageActor New();
+
+  /**
+   * @brief Create a image actor object.
+   *
+   * The actor will take the image's natural size unless a custom size
+   * is chosen, e.g. via Actor:SetSize().
+   * If the handle is empty, ImageActor will display nothing
+   * @since_tizen 2.4
+   * @param[in] image The image to display.
+   * @return A handle to a newly allocated actor.
+   * @pre ImageActor must be initialized.
+   */
+  static ImageActor New(Image image);
+
+  /**
+   * @brief Create a image actor object.
+   *
+   * The actor will take the image's natural size unless a custom size
+   * is chosen, e.g. via Actor:SetSize()
+   * If the handle is empty, ImageActor will display nothing
+   * @since_tizen 2.4
+   * @param [in] image The image to display.
+   * @param [in] pixelArea The area of the image to display.
+   * This in pixels, relative to the top-left (0,0) of the image.
+   * @return A handle to a newly allocated actor.
+   * @pre ImageActor must be initialized.
+   */
+  static ImageActor New(Image image, PixelArea pixelArea);
+
+  /**
+   * @brief Downcast an Object handle to ImageActor.
+   *
+   *
+   * If handle points to a ImageActor the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a ImageActor or an uninitialized handle
+   */
+  static ImageActor DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~ImageActor();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] copy The actor to copy.
+   */
+  ImageActor(const ImageActor& copy);
+
+  /**
+   * @brief Assignment operator
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs The actor to copy.
+   */
+  ImageActor& operator=(const ImageActor& rhs);
+
+  /**
+   * @brief Set the image rendered by the actor.
+   * Set the image rendered by the actor.
+   * If actor was already displaying a different image, the old image is dropped and actor may
+   * temporarily display nothing. Setting an empty image (handle) causes the current image to be
+   * dropped and actor displays nothing.
+   * The actor will take the image's natural size unless a custom size
+   * is chosen, e.g. via Actor:SetSize()
+   *
+   * @since_tizen 2.4
+   * @param [in] image The image to display.
+   * @pre ImageActor must be initialized.
+   */
+  void SetImage(Image image);
+
+  /**
+   * @brief Retrieve the image rendered by the actor.
+   *
+   * If no image is assigned, an empty handle is returned
+   * @since_tizen 2.4
+   * @return The image.
+   */
+  Image GetImage();
+
+  /**
+   * @brief Set a region of the image to display, in pixels.
+   *
+   * When the image is loaded the actor's size will be reset to the pixelArea,
+   * unless a custom size was chosen, e.g. via Actor:SetSize().
+   * Note! PixelArea should be inside the image data size. It gets clamped by GL
+   * @since_tizen 2.4
+   * @param [in] pixelArea The area of the image to display.
+   * This in pixels, relative to the top-left (0,0) of the image.
+   * @pre image must be initialized.
+   */
+  void SetPixelArea(const PixelArea& pixelArea);
+
+  /**
+   * @brief Retrieve the region of the image to display, in pixels.
+   *
+   * @since_tizen 2.4
+   * @return The pixel area, or a default-constructed area if none was set.
+   * @pre image must be initialized.
+   */
+  PixelArea GetPixelArea() const;
+
+  /**
+   * @brief Set how the image is rendered; the default is STYLE_QUAD.
+   *
+   * @since_tizen 2.4
+   * @param [in] style The new style.
+   * @pre image must be initialized.
+   */
+  void SetStyle(Style style);
+
+  /**
+   * @brief Query how the image is rendered.
+   *
+   * @since_tizen 2.4
+   * @return The rendering style.
+   * @pre image must be initialized.
+   */
+  Style GetStyle() const;
+
+  /**
+   * @brief Set the border used with STYLE_NINE_PATCH.
+   *
+   * The values are in pixels from the left, top, right, and bottom of the image respectively.
+   * i.e. SetNinePatchBorder( Vector4(1,2,3,4) ) sets the left-border to 1, top-border to 2, right-border to 3, and bottom-border to 4 pixels.
+   * @since_tizen 2.4
+   * @param [in] border The new nine-patch border.
+   */
+  void SetNinePatchBorder(const Vector4& border);
+
+  /**
+   * @brief Retrieve the border used with STYLE_NINE_PATCH.
+   *
+   * @since_tizen 2.4
+   * @return The nine-patch border.
+   */
+  Vector4 GetNinePatchBorder() const;
+
+
+  /**
+   * @brief Allows modification of an actors position in the depth sort algorithm.
+   *
+   * The offset can be altered for each coplanar actor hence allowing an order of painting.
+   * @since_tizen 2.4
+   * @param [in] depthOffset the offset to be given to the actor. Positive values pushing it further back.
+   * @pre The Actor has been initialized.
+   */
+  void SetSortModifier(float depthOffset);
+
+  /**
+   * @brief Retrieves the offset used to modify an actors position in the depth sort algorithm.
+   *
+   * The offset can be altered for each coplanar actor hence allowing an order of painting.
+   * @since_tizen 2.4
+   * @return  the offset that has been given to the actor. Positive values pushing it further back.
+   * @pre The Actor has been initialized.
+   */
+  float GetSortModifier() const;
+
+  /**
+   * @brief Sets the blending mode.
+   *
+   * Possible values are: BlendingMode::OFF, BlendingMode::AUTO and BlendingMode::ON. Default is BlendingMode::AUTO.
+   *
+   * If blending is disabled (BlendingMode::OFF) fade in and fade out animations do not work.
+   *
+   * <ul>
+   *   <li> \e OFF Blending is disabled.
+   *   <li> \e AUTO Blending is enabled only if the renderable actor has alpha channel.
+   *   <li> \e ON Blending is enabled.
+   * </ul>
+   *
+   * @since_tizen 2.4
+   * @param[in] mode The blending mode.
+   */
+  void SetBlendMode( BlendingMode::Type mode );
+
+  /**
+   * @brief Retrieves the blending mode.
+   *
+   * @since_tizen 2.4
+   * @return The blending mode, one of BlendingMode::OFF, BlendingMode::AUTO or BlendingMode::ON.
+   */
+  BlendingMode::Type GetBlendMode() const;
+
+  /**
+   * @brief Specify the pixel arithmetic used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @param[in] srcFactorRgba Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE.
+   *
+   * @param[in] destFactorRgba Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA.
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgba, BlendingFactor::Type destFactorRgba );
+
+  /**
+   * @brief Specify the pixel arithmetic used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @param[in] srcFactorRgb Specifies how the red, green, and blue source blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, and GL_SRC_ALPHA_SATURATE.
+   *
+   * @param[in] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * The options are BlendingFactor::ZERO, ONE, SRC_COLOR, ONE_MINUS_SRC_COLOR, DST_COLOR, ONE_MINUS_DST_COLOR,
+   * SRC_ALPHA, ONE_MINUS_SRC_ALPHA, DST_ALPHA, ONE_MINUS_DST_ALPHA, CONSTANT_COLOR, ONE_MINUS_CONSTANT_COLOR,
+   * GL_CONSTANT_ALPHA, and GL_ONE_MINUS_CONSTANT_ALPHA.
+   *
+   * @param[in] srcFactorAlpha Specifies how the alpha source blending factor is computed.
+   * The options are the same as for srcFactorRgb.
+   *
+   * @param[in] destFactorAlpha Specifies how the alpha source blending factor is computed.
+   * The options are the same as for destFactorRgb.
+   */
+  void SetBlendFunc( BlendingFactor::Type srcFactorRgb,   BlendingFactor::Type destFactorRgb,
+                     BlendingFactor::Type srcFactorAlpha, BlendingFactor::Type destFactorAlpha );
+
+  /**
+   * @brief Query the pixel arithmetic used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @param[out] srcFactorRgb Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * @param[out] destFactorRgb Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   * @param[out] srcFactorAlpha Specifies how the red, green, blue, and alpha source blending factors are computed.
+   * @param[out] destFactorAlpha Specifies how the red, green, blue, and alpha destination blending factors are computed.
+   */
+  void GetBlendFunc( BlendingFactor::Type& srcFactorRgb,   BlendingFactor::Type& destFactorRgb,
+                     BlendingFactor::Type& srcFactorAlpha, BlendingFactor::Type& destFactorAlpha ) const;
+
+  /**
+   * @brief Specify the equation used when the actor is blended.
+   *
+   * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT.
+   * @since_tizen 2.4
+   * @param[in] equationRgba The equation used for combining red, green, blue, and alpha components.
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgba );
+
+  /**
+   * @brief Specify the equation used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @param[in] equationRgb The equation used for combining red, green, and blue components.
+   * @param[in] equationAlpha The equation used for combining the alpha component.
+   * The options are BlendingEquation::ADD, SUBTRACT, or REVERSE_SUBTRACT.
+   */
+  void SetBlendEquation( BlendingEquation::Type equationRgb, BlendingEquation::Type equationAlpha );
+
+  /**
+   * @brief Query the equation used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @param[out] equationRgb The equation used for combining red, green, and blue components.
+   * @param[out] equationAlpha The equation used for combining the alpha component.
+   */
+  void GetBlendEquation( BlendingEquation::Type& equationRgb, BlendingEquation::Type& equationAlpha ) const;
+
+  /**
+   * @brief Specify the color used when the actor is blended; the default is Vector4::ZERO.
+   *
+   * @since_tizen 2.4
+   * @param[in] color The blend color.
+   */
+  void SetBlendColor( const Vector4& color );
+
+  /**
+   * @brief Query the color used when the actor is blended.
+   *
+   * @since_tizen 2.4
+   * @return The blend color.
+   */
+  const Vector4& GetBlendColor() const;
+
+  /**
+   * @brief Sets the filtering mode.
+   *
+   * Possible values are: FilterMode::NEAREST and FilterMode::LINEAR. Default is FilterMode::LINEAR.
+   *
+   * <ul>
+   *   <li> \e NEAREST Use nearest filtering
+   *   <li> \e LINEAR Use linear filtering
+   * </ul>
+   *
+   * @since_tizen 2.4
+   * @param[in] minFilter The minification filtering mode.
+   * @param[in] magFilter The magnification filtering mode.
+   */
+  void SetFilterMode( FilterMode::Type minFilter, FilterMode::Type magFilter );
+
+  /**
+   * @brief Retrieves the filtering mode.
+   *
+   * @since_tizen 2.4
+   * @param[out] minFilter The return minification value
+   * @param[out] magFilter The return magnification value
+   */
+  void GetFilterMode( FilterMode::Type& minFilter, FilterMode::Type& magFilter) const;
+
+  /**
+   * @brief Sets the shader effect for the RenderableActor.
+   *
+   * Shader effects provide special effects like ripple and bend.
+   * Setting a shader effect removes any shader effect previously set by SetShaderEffect.
+   * @since_tizen 2.4
+   * @param [in] effect The shader effect.
+   * @pre The actor has been initialized.
+   * @pre effect has been initialized.
+   */
+  void SetShaderEffect( ShaderEffect effect );
+
+  /**
+   * @brief Retrieve the custom shader effect for the RenderableActor.
+   * If default shader is used an empty handle is returned.
+   *
+   * @since_tizen 2.4
+   * @return The shader effect
+   * @pre The Actor has been initialized.
+   */
+  ShaderEffect GetShaderEffect() const;
+
+  /**
+   * @brief Removes the current shader effect.
+   *
+   * @since_tizen 2.4
+   * @pre The Actor has been initialized.
+   */
+  void RemoveShaderEffect();
+
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL ImageActor(Internal::ImageActor*);
+};
+
+
+/**
+ * @brief Sets the shader effect for all ImageActors in a tree of Actors.
+ *
+ * @since_tizen 2.4
+ * @param [in] actor root of a tree of actors.
+ * @param [in] effect The shader effect.
+ * @see ImageActor::SetShaderEffect
+ *
+ */
+DALI_IMPORT_API void SetShaderEffectRecursively( Actor actor, ShaderEffect effect );
+
+/**
+ * @brief Removes the shader effect from all ImageActors in a tree of Actors.
+ *
+ * @since_tizen 2.4
+ * @param [in] actor root of a tree of actors.
+ * @see ImageActor::RemoveShaderEffect
+ *
+ */
+DALI_IMPORT_API void RemoveShaderEffectRecursively( Actor actor );
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_IMAGE_ACTOR_H__
diff --git a/dali/public-api/actors/layer.cpp b/dali/public-api/actors/layer.cpp
new file mode 100644 (file)
index 0000000..029ee45
--- /dev/null
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/actors/layer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/actors/layer-impl.h>
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+
+namespace Dali
+{
+
+using Dali::Layer;
+
+Layer::Layer()
+{
+}
+
+Layer Layer::New()
+{
+  Internal::LayerPtr internal = Internal::Layer::New();
+
+  return Layer(internal.Get());
+}
+
+Layer Layer::DownCast( BaseHandle handle )
+{
+  return Layer( dynamic_cast<Dali::Internal::Layer*>(handle.GetObjectPtr()) );
+}
+
+Layer::~Layer()
+{
+}
+
+Layer::Layer(const Layer& copy)
+: Actor(copy)
+{
+}
+
+Layer& Layer::operator=(const Layer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+unsigned int Layer::GetDepth() const
+{
+  return GetImplementation(*this).GetDepth();
+}
+
+void Layer::Raise()
+{
+  GetImplementation(*this).Raise();
+}
+
+void Layer::Lower()
+{
+  GetImplementation(*this).Lower();
+}
+
+void Layer::RaiseAbove( Layer target )
+{
+  GetImplementation(*this).RaiseAbove( GetImplementation( target ) );
+}
+
+void Layer::LowerBelow( Layer target )
+{
+  GetImplementation(*this).LowerBelow( GetImplementation( target ) );
+}
+
+void Layer::RaiseToTop()
+{
+  GetImplementation(*this).RaiseToTop();
+}
+
+void Layer::LowerToBottom()
+{
+  GetImplementation(*this).LowerToBottom();
+}
+
+void Layer::MoveAbove( Layer target )
+{
+  GetImplementation(*this).MoveAbove( GetImplementation( target ) );
+}
+
+void Layer::MoveBelow( Layer target )
+{
+  GetImplementation(*this).MoveBelow( GetImplementation( target ) );
+}
+
+void Layer::SetBehavior( Behavior behavior )
+{
+  GetImplementation(*this).SetBehavior( behavior );
+}
+
+Layer::Behavior Layer::GetBehavior() const
+{
+  return GetImplementation(*this).GetBehavior();
+}
+
+void Layer::SetClipping(bool enabled)
+{
+  GetImplementation(*this).SetClipping(enabled);
+}
+
+bool Layer::IsClipping() const
+{
+  return GetImplementation(*this).IsClipping();
+}
+
+void Layer::SetClippingBox(int x, int y, int width, int height)
+{
+  GetImplementation(*this).SetClippingBox(x, y, width, height);
+}
+
+void Layer::SetClippingBox(ClippingBox box)
+{
+  GetImplementation(*this).SetClippingBox(box.x, box.y, box.width, box.height);
+}
+
+ClippingBox Layer::GetClippingBox() const
+{
+  return GetImplementation(*this).GetClippingBox();
+}
+
+void Layer::SetDepthTestDisabled( bool disable )
+{
+  GetImplementation(*this).SetDepthTestDisabled( disable );
+}
+
+bool Layer::IsDepthTestDisabled() const
+{
+  return GetImplementation(*this).IsDepthTestDisabled();
+}
+
+void Layer::SetSortFunction(SortFunctionType function)
+{
+  GetImplementation(*this).SetSortFunction(function);
+}
+
+void Layer::SetTouchConsumed( bool consume )
+{
+  GetImplementation( *this ).SetTouchConsumed( consume );
+}
+
+bool Layer::IsTouchConsumed() const
+{
+  return GetImplementation( *this ).IsTouchConsumed();
+}
+
+void Layer::SetHoverConsumed( bool consume )
+{
+  GetImplementation( *this ).SetHoverConsumed( consume );
+}
+
+bool Layer::IsHoverConsumed() const
+{
+  return GetImplementation( *this ).IsHoverConsumed();
+}
+
+Layer::Layer(Internal::Layer* internal)
+: Actor(internal)
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/actors/layer.h b/dali/public-api/actors/layer.h
new file mode 100644 (file)
index 0000000..b0795ae
--- /dev/null
@@ -0,0 +1,438 @@
+#ifndef __DALI_LAYER_H__
+#define __DALI_LAYER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class Layer;
+}
+
+/**
+ * @brief Rectangle describing area on screen that a layer can draw to.
+ *
+ * @since_tizen 2.4
+ * @see Dali::Layer::SetClippingBox()
+ */
+typedef Rect<int> ClippingBox;
+
+/**
+ * @brief Layers provide a mechanism for overlaying groups of actors on top of each other.
+ *
+ * When added to the stage, a layer can be ordered relative to other layers. The bottom
+ * layer is at depth zero. The stage provides a default layer for it's children.
+ *
+ * Layered actors inherit position etc. as normal, but are drawn in an order determined
+ * by the layers. The depth buffer is cleared before each layer is rendered unless depth
+ * test is disabled or there's no need for it based on the layers contents;
+ * actors in lower layers cannot obscure actors in higher layers.
+ *
+ * If depth test is disabled, there is no performance overhead from clearing the depth buffer.
+ *
+ * Actions
+ * | %Action Name    | %Layer method called |
+ * |-----------------|----------------------|
+ * | raise           | @ref Raise()         |
+ * | lower           | @ref Lower()         |
+ * | raise-to-top    | @ref RaiseToTop()    |
+ * | lower-to-bottom | @ref LowerToBottom() |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Layer : public Actor
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the Layer class.
+   * Properties additional to Actor.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      CLIPPING_ENABLE = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX, ///< name "clipping-enable",  type bool
+      CLIPPING_BOX,                                                 ///< name "clipping-box",     type Rect<int>
+      BEHAVIOR,                                                     ///< name "behavior",         type String
+    };
+  };
+
+  /**
+   * @brief Enumeration for the behavior of the layer.
+   *
+   * Check each value to see how it affects the layer.
+   * @since_tizen 2.4
+   */
+  enum Behavior
+  {
+    /**
+     * @brief Layer doesn't make use of the depth test.
+     *
+     * This mode is expected to have better performance than the 3D mode.
+     * When using this mode any ordering would be with respect to depth-index property of Renderers.
+     */
+    LAYER_2D,
+
+    /**
+     * @brief Layer will use depth test and do several clears.
+     *
+     * When using this mode depth depth test will be used. A depth clear will happen for each distinct
+     * depth-index value in the layer, opaque renderers are drawn first and write to the depth buffer.
+     * Then transparent renderers are drawn with depth test enabled but depth write switched off.
+     */
+    LAYER_3D,
+  };
+
+  /*
+   * TREE_DEPTH_MULTIPLIER is used by the rendering sorting algorithm to decide which actors to render first.
+   * For 2D layers, this value will be multiplied to the actor depth in the tree and added to the depth index
+   * to obtain the value which will be used for ordering
+   */
+  enum TreeDepthMultiplier
+  {
+    TREE_DEPTH_MULTIPLIER = 10000,
+  };
+  /**
+   * @brief The sort function type.
+   *
+   * @since_tizen 2.4
+   * @param[in] position this is the actor translation from camera.
+   */
+  typedef float (*SortFunctionType)( const Vector3& position );
+
+  /**
+   * @brief Create an empty Layer handle.
+   *
+   * This can be initialised with Layer::New(...)
+   * @since_tizen 2.4
+   */
+  Layer();
+
+  /**
+   * @brief Create a Layer object.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Layer
+   */
+  static Layer New();
+
+  /**
+   * @brief Downcast an Object handle to Layer.
+   *
+   * If handle points to a Layer the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Layer or an uninitialized handle
+   */
+  static Layer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Layer();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] copy The actor to copy.
+   */
+  Layer(const Layer& copy);
+
+  /**
+   * @brief Assignment operator
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs The actor to copy.
+   */
+  Layer& operator=(const Layer& rhs);
+
+  /**
+   * @brief Query the depth of the layer
+   *
+   * 0 is bottom most layer, higher number is on top
+   * @since_tizen 2.4
+   * @return the current depth of the layer.
+   * @pre layer is on the stage
+   * If layer is not added to the stage, returns 0.
+   */
+  unsigned int GetDepth() const;
+
+  /**
+   * @brief Increment the depth of the layer.
+   *
+   * @since_tizen 2.4
+   * @pre layer is on the stage
+   */
+  void Raise();
+
+  /**
+   * @brief Decrement the depth of the layer.
+   *
+   * @since_tizen 2.4
+   * @pre layer is on the stage
+   */
+  void Lower();
+
+  /**
+   * @brief Ensures the layers depth is greater than the target layer.
+   *
+   * If the layer already is above target layer its depth is not changed
+   * If the layer was below target, its new depth will be immediately above target
+   * Note! All layers between this layer and target get new depth values
+   * @since_tizen 2.4
+   * @param target layer to get above of
+   * @pre layer is on the stage
+   * @pre target layer is on the stage
+   */
+  void RaiseAbove( Layer target );
+
+  /**
+   * @brief Ensures the layers depth is less than the target layer.
+   *
+   * If the layer already is below the layer its depth is not changed
+   * If the layer was above target, its new depth will be immediately below target
+   * Note! All layers between this layer and target get new depth values
+   * @since_tizen 2.4
+   * @param target layer to get below of
+   * @pre layer is on the stage
+   * @pre target layer is on the stage
+   */
+  void LowerBelow( Layer target );
+
+  /**
+   * @brief Raises the layer to the top.
+   * @since_tizen 2.4
+   * @pre layer is on the stage
+   */
+  void RaiseToTop();
+
+  /**
+   * @brief Lowers the layer to the bottom.
+   * @since_tizen 2.4
+   * @pre layer is on the stage
+   */
+  void LowerToBottom();
+
+  /**
+   * @brief Moves the layer directly above the given layer.
+   *
+   * After the call this layers depth will be immediately above target
+   * Note! All layers between this layer and target get new depth values
+   * @since_tizen 2.4
+   * @param target layer to get on top of
+   * @pre layer is on the stage
+   * @pre target layer is on the stage
+   */
+  void MoveAbove( Layer target );
+
+  /**
+   * @brief Moves the layer directly below the given layer.
+   *
+   * After the call this layers depth will be immediately below target
+   * Note! All layers between this layer and target get new depth values
+   * @since_tizen 2.4
+   * @param target layer to get below of
+   * @pre layer is on the stage
+   * @pre target layer is on the stage
+   */
+  void MoveBelow( Layer target );
+
+  /**
+   * @brief Set the behavior of the layer
+   *
+   * @since_tizen 2.4
+   * @param[in] behavior The desired behavior
+   */
+  void SetBehavior( Behavior behavior );
+
+  /**
+   * @brief Get the behavior of the layer
+   *
+   * @since_tizen 2.4
+   * @return The behavior of the layer
+   */
+  Behavior GetBehavior() const;
+
+  /**
+   * @brief Sets whether clipping is enabled for a layer.
+   *
+   * Clipping is initially disabled; see also SetClippingBox().
+   * @since_tizen 2.4
+   * @param [in] enabled True if clipping is enabled.
+   *
+   * @note When clipping is enabled, the default clipping box is empty (0,0,0,0) which means everything is clipped.
+   */
+  void SetClipping(bool enabled);
+
+  /**
+   * @brief Query whether clipping is enabled for a layer.
+   * @since_tizen 2.4
+   * @return True if clipping is enabled.
+   */
+  bool IsClipping() const;
+
+  /**
+   * @brief Sets the clipping box of a layer, in window coordinates.
+   *
+   * The contents of the layer will not be visible outside this box, when clipping is
+   * enabled. The default clipping box is empty (0,0,0,0) which means everything is clipped.
+   * You can only do rectangular clipping using this API in window coordinates.
+   * For other kinds of clipping, @see Dali::Actor::SetDrawMode().
+   * @since_tizen 2.4
+   * @param [in] x The X-coordinate of the top-left corner of the box.
+   * @param [in] y The Y-coordinate of the top-left corner of the box.
+   * @param [in] width  The width of the box.
+   * @param [in] height The height of the box.
+   */
+  void SetClippingBox(int x, int y, int width, int height);
+
+  /**
+   * @brief Sets the clipping box of a layer, in window coordinates.
+   *
+   * The contents of the layer will not be visible outside this box, when clipping is
+   * enabled. The default clipping box is empty (0,0,0,0).
+   * @since_tizen 2.4
+   * @param [in] box The clipping box
+   */
+  void SetClippingBox(ClippingBox box);
+
+  /**
+   * @brief Retrieves the clipping box of a layer, in window coordinates.
+   *
+   * @since_tizen 2.4
+   * @return The clipping box
+   */
+  ClippingBox GetClippingBox() const;
+
+  // Depth test
+
+  /**
+   * @brief Whether to disable the depth test.
+   *
+   * By default a layer enables depth test if there is more than one opaque actor or if there is one opaque actor and one, or more, transparent actors.
+   * However, it's possible to disable the depth test by calling this method.
+   *
+   * @since_tizen 2.4
+   * @param[in] disable \e true disables depth test. \e false sets the default behavior.
+   */
+  void SetDepthTestDisabled( bool disable );
+
+  /**
+   * @brief Retrieves whether depth test is disabled.
+   *
+   * @since_tizen 2.4
+   * @return \e true if depth test is disabled.
+   */
+  bool IsDepthTestDisabled() const;
+
+  // Sorting
+
+  /**
+   * @brief This allows the user to specify the sort function that the layer should use.
+   *
+   * The sort function is used to determine the order in which the actors are drawn
+   * and input is processed on the actors in the layer.
+   *
+   * A function of the following type should be used:
+   * @code
+   *  float YourSortFunction(const Vector3& position);
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param[in]  function  The sort function pointer
+   * @note If the sort function returns a low number, the actor the data applies to will be
+   * drawn in front of an actor whose data yields a high value from the sort function.
+   *
+   * @note All child layers use the same sort function.  If a child layer is added to this
+   * layer then the sort function used by the child layer will also be the same.
+   *
+  */
+  void SetSortFunction( SortFunctionType function );
+
+  /**
+   * @brief This allows the user to specify whether this layer should consume touch (including gestures).
+   *
+   * If set, any layers behind this layer will not be hit-test.
+   *
+   * @since_tizen 2.4
+   * @param[in]  consume  Whether the layer should consume touch (including gestures).
+   */
+  void SetTouchConsumed( bool consume );
+
+  /**
+   * @brief Retrieves whether the layer consumes touch (including gestures).
+   *
+   * @since_tizen 2.4
+   * @return true if consuming touch, false otherwise.
+   */
+  bool IsTouchConsumed() const;
+
+  /**
+   * @brief This allows the user to specify whether this layer should consume hover.
+   *
+   * If set, any layers behind this layer will not be hit-test.
+   *
+   * @since_tizen 2.4
+   * @param[in]  consume  Whether the layer should consume hover.
+   */
+  void SetHoverConsumed( bool consume );
+
+  /**
+   * @brief Retrieves whether the layer consumes hover.
+   *
+   * @since_tizen 2.4
+   * @return true if consuming hover, false otherwise.
+   */
+  bool IsHoverConsumed() const;
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] Layer A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL Layer(Internal::Layer* Layer);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif //__DALI_LAYER_H__
diff --git a/dali/public-api/actors/sampling.h b/dali/public-api/actors/sampling.h
new file mode 100644 (file)
index 0000000..65e8051
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef __DALI_SAMPLING_H__
+#define __DALI_SAMPLING_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_actors
+ * @{
+ */
+
+namespace FilterMode
+{
+/**
+ * @brief Texture filtering mode.
+ * @since_tizen 2.4
+ * @see Dali::RenderableActor::SetFilterMode() and Dali::RenderableActor::GetFilterMode()
+ */
+enum Type
+{
+  NONE,       ///< Use GL system defaults (minification NEAREST_MIPMAP_LINEAR, magnification LINEAR)
+  DEFAULT,    ///< Use dali defaults (minification LINEAR, magnification LINEAR)
+  NEAREST,    ///< Filter nearest
+  LINEAR      ///< Filter linear
+};
+
+} //namespace FilterMode
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SAMPLING_H__
diff --git a/dali/public-api/animation/alpha-function.cpp b/dali/public-api/animation/alpha-function.cpp
new file mode 100644 (file)
index 0000000..7ce7db5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/alpha-function.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+AlphaFunction::AlphaFunction()
+:mBezierControlPoints(Vector4::ZERO),
+ mCustom(0),
+ mBuiltin(DEFAULT),
+ mMode(BUILTIN_FUNCTION)
+{}
+
+AlphaFunction::AlphaFunction( BuiltinFunction function)
+:mBezierControlPoints(Vector4::ZERO),
+ mCustom(0),
+ mBuiltin(function),
+ mMode(BUILTIN_FUNCTION)
+{}
+
+AlphaFunction::AlphaFunction( AlphaFunctionPrototype function)
+:mBezierControlPoints(Vector4::ZERO),
+ mCustom(function),
+ mBuiltin(DEFAULT),
+ mMode(CUSTOM_FUNCTION)
+{}
+
+AlphaFunction::AlphaFunction( const Vector2& controlPoint0, const Vector2& controlPoint1 )
+:mBezierControlPoints(Vector4(Clamp(controlPoint0.x,0.0f,1.0f),controlPoint0.y,
+                              Clamp(controlPoint1.x,0.0f,1.0f),controlPoint1.y)),
+ mCustom(0),
+ mBuiltin(DEFAULT),
+ mMode(BEZIER)
+{
+}
+
+Vector4 AlphaFunction::GetBezierControlPoints() const
+{
+  return mBezierControlPoints;
+}
+
+AlphaFunctionPrototype AlphaFunction::GetCustomFunction() const
+{
+  return mCustom;
+}
+
+AlphaFunction::BuiltinFunction AlphaFunction::GetBuiltinFunction() const
+{
+  return mBuiltin;
+}
+
+AlphaFunction::Mode AlphaFunction::GetMode() const
+{
+  return mMode;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/animation/alpha-function.h b/dali/public-api/animation/alpha-function.h
new file mode 100644 (file)
index 0000000..f9097c3
--- /dev/null
@@ -0,0 +1,172 @@
+#ifndef __DALI_ALPHA_FUNCTION_H__
+#define __DALI_ALPHA_FUNCTION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/compile-time-math.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+typedef float (*AlphaFunctionPrototype)(float progress); ///< Prototype of an alpha function
+
+  /**
+   * @brief Alpha functions are used in animations to specify the rate of change of the animation parameter over time.
+   *
+   * Understanding an animation as a parametric function over time, the alpha function is applied to the parameter of
+   * the animation before computing the final animation value.
+   * @since_tizen 2.4
+   */
+class DALI_IMPORT_API AlphaFunction
+{
+public:
+
+  /**
+   * @brief Built-in alpha functions
+   * @since_tizen 2.4
+   */
+  enum BuiltinFunction
+  {
+    DEFAULT,            ///< Linear
+    LINEAR,             ///< No transformation
+    REVERSE,            ///< Reverse linear
+
+    EASE_IN_SQUARE,     ///< Speeds up and comes to a sudden stop (Square)
+    EASE_OUT_SQUARE,    ///< Sudden start and slows to a gradual stop (Square)
+
+    EASE_IN,            ///< Speeds up and comes to a sudden stop (Cubic)
+    EASE_OUT,           ///< Sudden start and slows to a gradual stop (Cubic)
+    EASE_IN_OUT,        ///< Speeds up and slows to a gradual stop (Cubic)
+
+    EASE_IN_SINE,       ///< Speeds up and comes to a sudden stop (sinusoidal)
+    EASE_OUT_SINE,      ///< Sudden start and slows to a gradual stop (sinusoidal)
+    EASE_IN_OUT_SINE,   ///< Speeds up and slows to a gradual stop (sinusoidal)
+
+    BOUNCE,             ///< Sudden start, loses momentum and returns to start position
+    SIN,                ///< Single revolution
+    EASE_OUT_BACK,      ///< Sudden start, exceed end position and return to a gradual stop
+
+    COUNT
+  };
+
+  /**
+   * @brief All possible functioning modes for the alpha function
+   * @since_tizen 2.4
+   */
+  enum Mode
+  {
+    BUILTIN_FUNCTION,  //< The user has specified a built-in function
+    CUSTOM_FUNCTION,   //< The user has provided a custom function
+    BEZIER             //< The user has provided the control points of a bezier curve
+  };
+
+  /**
+   * @brief Default constructor.
+   * Creates an alpha function object with the default built-in alpha function
+   * @since_tizen 2.4
+   * @return The alpha function
+   */
+  AlphaFunction();
+
+  /**
+   * @brief Constructor.
+   * Creates an alpha function object with the built-in alpha function passed as a parameter
+   * to the constructor
+   * @since_tizen 2.4
+   * @param[in] function One of the built-in alpha functions
+   * @return The alpha function
+   */
+  AlphaFunction( BuiltinFunction function);
+
+  /**
+   * @brief Constructor.
+   * Creates an alpha function object using a pointer to an alpha function passed as a paramter
+   * to the constructor
+   * @since_tizen 2.4
+   * @param[in] function A pointer to an alpha function
+   * @return The alpha function
+   */
+  AlphaFunction( AlphaFunctionPrototype function);
+
+  /**
+   * @brief Constructor.
+   * Creates a bezier alpha function. The bezier will have the first point at (0,0) and
+   * the end point at (1,1).
+   * @since_tizen 2.4
+   * @param[in] controlPoint0 A Vector2 which will be used as the first control point of the curve
+   * @param[in] controlPoint1 A Vector2 which will be used as the second control point of the curve
+   * @return The alpha function
+   * @note The x components of the control points will be clamped to the range [0,1] to prevent
+   * non monotonic curves.
+   */
+  AlphaFunction( const Dali::Vector2& controlPoint0, const Dali::Vector2& controlPoint1 );
+
+  /**
+   * @brief Return the control points of the alpha function
+   * @since_tizen 2.4
+   * @return Vector4 containing the two control points of the curve.
+   * (xy for the first point and zw for the second)
+   */
+  Vector4 GetBezierControlPoints() const;
+
+  /**
+   * @brief Returns the pointer to the custom function
+   * @since_tizen 2.4
+   * @return A pointer to a custom alpha function or 0 if not defined
+   */
+  AlphaFunctionPrototype GetCustomFunction() const;
+
+  /**
+   * @brief Returns the built0in function used by the alpha function
+   * @since_tizen 2.4
+   * @return One of the built-in alpha functions. In case no built-in function
+   * has been specified, it will return AlphaFunction::DEfAULT
+   */
+  BuiltinFunction GetBuiltinFunction() const;
+
+  /**
+   * @brief Returns the functioning mode of the alpha function
+   * @since_tizen 2.4
+   * @return The functioning mode of the alpha function
+   */
+  Mode GetMode() const;
+
+private:
+
+  Vector4                 mBezierControlPoints;   //< Control points for the bezier alpha function
+  AlphaFunctionPrototype  mCustom;                //< Pointer to an alpha function
+  BuiltinFunction         mBuiltin : Log<COUNT>::value+1; //< Enum indicating the built-in alpha function
+  Mode                    mMode    : 2;                   //< Enum indicating the functioning mode of the AlphaFunction
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ALPHA_FUNCTION_H__
diff --git a/dali/public-api/animation/animation.cpp b/dali/public-api/animation/animation.cpp
new file mode 100644 (file)
index 0000000..32c8ebe
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/animation.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/time-period.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/animation/animation-impl.h>
+#include <dali/internal/event/effects/shader-effect-impl.h>
+
+namespace Dali
+{
+
+Animation::Animation()
+{
+}
+
+Animation::Animation(Internal::Animation* animation)
+: BaseHandle(animation)
+{
+}
+
+Animation Animation::New(float durationSeconds)
+{
+  Internal::AnimationPtr internal = Dali::Internal::Animation::New(durationSeconds);
+
+  return Animation(internal.Get());
+}
+
+Animation Animation::DownCast( BaseHandle handle )
+{
+  return Animation( dynamic_cast<Dali::Internal::Animation*>(handle.GetObjectPtr()) );
+}
+
+Animation::~Animation()
+{
+}
+
+Animation::Animation(const Animation& handle)
+: BaseHandle(handle)
+{
+}
+
+Animation& Animation::operator=(const Animation& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void Animation::SetDuration(float durationSeconds)
+{
+  GetImplementation(*this).SetDuration(durationSeconds);
+}
+
+float Animation::GetDuration() const
+{
+  return GetImplementation(*this).GetDuration();
+}
+
+void Animation::SetLooping(bool looping)
+{
+  GetImplementation(*this).SetLooping(looping);
+}
+
+bool Animation::IsLooping() const
+{
+  return GetImplementation(*this).IsLooping();
+}
+
+void Animation::SetEndAction(Dali::Animation::EndAction endAction)
+{
+  GetImplementation(*this).SetEndAction(endAction);
+}
+
+Dali::Animation::EndAction Animation::GetEndAction() const
+{
+  return GetImplementation(*this).GetEndAction();
+}
+
+void Animation::SetDisconnectAction( Animation::EndAction disconnectAction )
+{
+  GetImplementation(*this).SetDisconnectAction( disconnectAction );
+}
+
+Animation::EndAction Animation::GetDisconnectAction() const
+{
+  return GetImplementation(*this).GetDisconnectAction();
+}
+
+void Animation::SetDefaultAlphaFunction(AlphaFunction alpha)
+{
+  GetImplementation(*this).SetDefaultAlphaFunction(alpha);
+}
+
+AlphaFunction Animation::GetDefaultAlphaFunction() const
+{
+  return GetImplementation(*this).GetDefaultAlphaFunction();
+}
+
+void Animation::Play()
+{
+  GetImplementation(*this).Play();
+}
+
+void Animation::PlayFrom(float progress)
+{
+  GetImplementation(*this).PlayFrom(progress);
+}
+
+
+void Animation::Pause()
+{
+  GetImplementation(*this).Pause();
+}
+
+void Animation::Stop()
+{
+  GetImplementation(*this).Stop();
+}
+
+void Animation::Clear()
+{
+  GetImplementation(*this).Clear();
+}
+
+Animation::AnimationSignalType& Animation::FinishedSignal()
+{
+  return GetImplementation(*this).FinishedSignal();
+}
+
+void Animation::AnimateBy(Property target, Property::Value relativeValue)
+{
+  GetImplementation(*this).AnimateBy(target, relativeValue);
+}
+
+void Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha)
+{
+  GetImplementation(*this).AnimateBy(target, relativeValue, alpha);
+}
+
+void Animation::AnimateBy(Property target, Property::Value relativeValue, TimePeriod period)
+{
+  GetImplementation(*this).AnimateBy(target, relativeValue, period);
+}
+
+void Animation::AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period)
+{
+  GetImplementation(*this).AnimateBy(target, relativeValue, alpha, period);
+}
+
+void Animation::AnimateTo(Property target, Property::Value destinationValue)
+{
+  GetImplementation(*this).AnimateTo(target, destinationValue);
+}
+
+void Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha)
+{
+  GetImplementation(*this).AnimateTo(target, destinationValue, alpha);
+}
+
+void Animation::AnimateTo(Property target, Property::Value destinationValue, TimePeriod period)
+{
+  GetImplementation(*this).AnimateTo(target, destinationValue, period);
+}
+
+void Animation::AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period)
+{
+  GetImplementation(*this).AnimateTo(target, destinationValue, alpha, period);
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames )
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames) );
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), interpolation );
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), period);
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), period, interpolation );
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha);
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, interpolation);
+}
+
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, period);
+}
+
+void Animation::AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation)
+{
+  GetImplementation(*this).AnimateBetween(target, GetImplementation(keyFrames), alpha, period, interpolation);
+}
+
+
+// Actor specific animations
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward );
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, alpha );
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period )
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, period);
+}
+
+void Animation::Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period)
+{
+  GetImplementation(*this).Animate(GetImplementation(actor), GetImplementation( path ), forward, alpha, period );
+}
+
+void Animation::Show(Actor actor, float delaySeconds)
+{
+  GetImplementation(*this).Show(GetImplementation(actor), delaySeconds);
+}
+
+void Animation::Hide(Actor actor, float delaySeconds)
+{
+  GetImplementation(*this).Hide(GetImplementation(actor), delaySeconds);
+}
+
+void Animation::SetCurrentProgress( float progress )
+{
+  return GetImplementation(*this).SetCurrentProgress( progress );
+}
+
+float Animation::GetCurrentProgress()
+{
+  return GetImplementation(*this).GetCurrentProgress();
+}
+
+void Animation::SetSpeedFactor( float factor )
+{
+  GetImplementation(*this).SetSpeedFactor( factor );
+}
+
+float Animation::GetSpeedFactor() const
+{
+  return GetImplementation(*this).GetSpeedFactor();
+}
+
+void Animation::SetPlayRange( const Vector2& range )
+{
+  GetImplementation(*this).SetPlayRange(range);
+}
+
+Vector2 Animation::GetPlayRange() const
+{
+  return GetImplementation(*this).GetPlayRange();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/animation/animation.h b/dali/public-api/animation/animation.h
new file mode 100644 (file)
index 0000000..a480ef2
--- /dev/null
@@ -0,0 +1,646 @@
+#ifndef __DALI_ANIMATION_H__
+#define __DALI_ANIMATION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/animation/path.h>
+#include <dali/public-api/animation/time-period.h>
+#include <dali/public-api/object/any.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+class Actor;
+struct Property;
+struct Vector2;
+struct Vector3;
+
+namespace Internal DALI_INTERNAL
+{
+class Animation;
+}
+
+/**
+ * @brief Dali::Animation can be used to animate the properties of any number of objects, typically Actors.
+ *
+ * An example animation setup is shown below:
+ *
+ * @code
+ *
+ * struct MyProgram
+ * {
+ *   Actor mActor; // The object we wish to animate
+ *   Animation mAnimation; // Keep this to control the animation
+ * }
+ *
+ * // ...To play the animation
+ *
+ * mAnimation = Animation::New(3.0f); // duration 3 seconds
+ * mAnimation.AnimateTo(Property(mActor, Actor::Property::POSITION), Vector3(10.0f, 50.0f, 0.0f));
+ * mAnimation.Play();
+ *
+ * @endcode
+ *
+ * Dali::Animation supports "fire and forget" behaviour i.e. an animation continues to play if the handle is discarded.
+ * Note that in the following example, the "Finish" signal will be emitted:
+ *
+ * @code
+ *
+ * void ExampleCallback( Animation& source )
+ * {
+ *   std::cout << "Animation has finished" << std::endl;
+ * }
+ *
+ * void ExampleAnimation( Actor actor )
+ * {
+ *   Animation animation = Animation::New(2.0f); // duration 2 seconds
+ *   animation.AnimateTo(Property(actor, Actor::Property::POSITION), 10.0f, 50.0f, 0.0f);
+ *   animation.FinishedSignal().Connect( ExampleCallback );
+ *   animation.Play();
+ * } // At this point the animation handle has gone out of scope
+ *
+ * Actor actor = Actor::New();
+ * Stage::GetCurrent().Add( actor );
+ *
+ * // Fire animation and forget about it
+ * ExampleAnimation( actor );
+ *
+ * // However the animation will continue, and "Animation has finished" will be printed after 2 seconds.
+ *
+ * @endcode
+ *
+ * If the "Finish" signal is connected to a member function of an object, it must be disconnected before the object is destroyed.
+ * This is typically done in the object destructor, and requires either the Dali::Connection object or Dali::Animation handle to be stored.
+ *
+ * Signals
+ * | %Signal Name | Method                   |
+ * |--------------|--------------------------|
+ * | finished     | @ref FinishedSignal()    |
+ *
+ * Actions
+ * | %Action Name | %Animation method called |
+ * |--------------|--------------------------|
+ * | play         | Play()                   |
+ * | stop         | Stop()                   |
+ * | pause        | Pause()                  |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Animation : public BaseHandle
+{
+public:
+
+  typedef Signal< void (Animation&) > AnimationSignalType; ///< Animation finished signal type
+
+  typedef Any AnyFunction; ///< Interpolation function
+
+  /**
+   * @brief What to do when the animation ends, is stopped or is destroyed
+   * @since_tizen 2.4
+   */
+  enum EndAction
+  {
+    Bake,     ///< When the animation ends, the animated property values are saved.
+    Discard,  ///< When the animation ends, the animated property values are forgotten.
+    BakeFinal ///< If the animation is stopped, the animated property values are saved as if the animation had run to completion, otherwise behaves like Bake.
+  };
+
+  /**
+   * @brief What interpolation method to use on key-frame animations
+   * @since_tizen 2.4
+   */
+  enum Interpolation
+  {
+    Linear,   ///< Values in between key frames are interpolated using a linear polynomial. (Default)
+    Cubic     ///< Values in between key frames are interpolated using a cubic polynomial.
+  };
+
+  /**
+   * @brief Create an uninitialized Animation; this can be initialized with Animation::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  Animation();
+
+  /**
+   * @brief Create an initialized Animation.
+   *
+   * The animation will not loop.
+   * The default end action is "Bake".
+   * The default alpha function is linear.
+   * @since_tizen 2.4
+   * @param [in] durationSeconds The duration in seconds.
+   * @return A handle to a newly allocated Dali resource.
+   * @pre durationSeconds must be greater than zero.
+   */
+  static Animation New(float durationSeconds);
+
+  /**
+   * @brief Downcast an Object handle to Animation.
+   *
+   * If handle points to an Animation object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Animation object or an uninitialized handle
+   */
+  static Animation DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Animation();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  Animation(const Animation& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Animation& operator=(const Animation& rhs);
+
+  /**
+   * @brief Set the duration of an animation.
+   *
+   * @since_tizen 2.4
+   * @param[in] seconds The duration in seconds.
+   * @pre durationSeconds must be greater than zero.
+   */
+  void SetDuration(float seconds);
+
+  /**
+   * @brief Retrieve the duration of an animation.
+   *
+   * @since_tizen 2.4
+   * @return The duration in seconds.
+   */
+  float GetDuration() const;
+
+  /**
+   * @brief Set whether the animation will loop.
+   *
+   * @since_tizen 2.4
+   * @param[in] looping True if the animation will loop.
+   */
+  void SetLooping(bool looping);
+
+  /**
+   * @brief Query whether the animation will loop.
+   *
+   * @since_tizen 2.4
+   * @return True if the animation will loop.
+   */
+  bool IsLooping() const;
+
+  /**
+   * @brief Set the end action of the animation.
+   *
+   * This action is performed when the animation ends or if it is stopped.
+   * Default end action is bake
+   * @since_tizen 2.4
+   * @param[in] action The end action.
+   */
+  void SetEndAction(EndAction action);
+
+  /**
+   * @brief Returns the end action of the animation.
+   *
+   * @since_tizen 2.4
+   * @return The end action.
+   */
+  EndAction GetEndAction() const;
+
+  /**
+   * @brief Set the disconnect action.
+   *
+   * If any of the animated property owners are disconnected from the stage while the animation is being played, then this action is performed.
+   * Default action is to BakeFinal.
+   * @since_tizen 2.4
+   * @param[in] disconnectAction The disconnect action.
+   */
+  void SetDisconnectAction( EndAction disconnectAction );
+
+  /**
+   * @brief Returns the disconnect action.
+   *
+   * @since_tizen 2.4
+   * @return The disconnect action.
+   */
+  EndAction GetDisconnectAction() const;
+
+  /**
+   * @brief Set the default alpha function for an animation.
+   *
+   * This is applied to individual property animations, if no further alpha functions are supplied.
+   * @since_tizen 2.4
+   * @param[in] alpha The default alpha function.
+   */
+  void SetDefaultAlphaFunction(AlphaFunction alpha);
+
+  /**
+   * @brief Retrieve the default alpha function for an animation.
+   *
+   * @since_tizen 2.4
+   * @return The default alpha function.
+   */
+  AlphaFunction GetDefaultAlphaFunction() const;
+
+  /**
+   * @brief Sets the progress of the animation.
+   * The animation will play (or continue playing) from this point. The progress
+   * must be in the 0-1 interval or in the play range interval if defined ( See SetPlayRange ),
+   * otherwise, it will be ignored.
+   *
+   * @since_tizen 2.4
+   * @param[in] progress The new progress as a normalized value between [0,1] or between the
+   * play range if specified.
+   */
+  void SetCurrentProgress( float progress );
+
+  /**
+  * @brief Retrieve the current progress of the animation.
+  *
+  * @since_tizen 2.4
+  * @return The current progress as a normalized value between [0,1].
+  */
+  float GetCurrentProgress();
+
+  /**
+   * @brief Specifies an speed factor for the animation.
+   *
+   * The speed factor is a multiplier of the normal velocity of the animation. Values between [0,1] will
+   * slow down the animation and values above one will speed up the animation. It is also possible to specify a negative multiplier
+   * to play the animation in reverse.
+   *
+   * @since_tizen 2.4
+   * @param[in] factor A value which will multiply the velocity.
+   */
+  void SetSpeedFactor( float factor );
+
+  /**
+   * @brief Retrieve the speed factor of the animation
+   *
+   * @since_tizen 2.4
+   * @return speed factor
+   */
+  float GetSpeedFactor() const;
+
+  /**
+   * @brief Set the playing range.
+   * Animation will play between the values specified. Both values ( range.x and range.y ) should be between 0-1,
+   * otherwise they will be ignored. If the range provided is not in proper order ( minimum,maximum ), it will be reordered.
+   *
+   * @since_tizen 2.4
+   * @param[in] range Two values between [0,1] to specify minimum and maximum progress. The
+   * animation will play between those values.
+   */
+  void SetPlayRange( const Vector2& range );
+
+  /**
+   * @brief Get the playing range
+   *
+   * @since_tizen 2.4
+   * @return The play range defined for the animation.
+   */
+  Vector2 GetPlayRange() const;
+
+  /**
+   * @brief Play the animation.
+   * @since_tizen 2.4
+   */
+  void Play();
+
+  /**
+   * @brief Play the animation from a given point.
+   * The progress must be in the 0-1 interval or in the play range interval if defined ( See SetPlayRange ),
+   * otherwise, it will be ignored.
+   *
+   * @since_tizen 2.4
+   * @param[in] progress A value between [0,1], or between the play range if specified, form where the animation should start playing
+   */
+  void PlayFrom( float progress );
+
+  /**
+   * @brief Pause the animation.
+   * @since_tizen 2.4
+   */
+  void Pause();
+
+  /**
+   * @brief Stop the animation.
+   * @since_tizen 2.4
+   */
+  void Stop();
+
+  /**
+   * @brief Clear the animation.
+   *
+   * This disconnects any objects that were being animated, effectively stopping the animation.
+   * @since_tizen 2.4
+   */
+  void Clear();
+
+  /**
+   * @brief Connect to this signal to be notified when an Animation's animations have finished.
+   *
+   * @since_tizen 2.4
+   * @return A signal object to Connect() with.
+   */
+  AnimationSignalType& FinishedSignal();
+
+  /**
+   * @brief Animate a property value by a relative amount.
+   *
+   * The default alpha function will be used.
+   * The effect will start & end when the animation begins & ends.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] relativeValue The property value will change by this amount.
+   */
+  void AnimateBy(Property target, Property::Value relativeValue);
+
+  /**
+   * @brief Animate a property value by a relative amount.
+   *
+   * The effect will start & end when the animation begins & ends.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] relativeValue The property value will change by this amount.
+   * @param [in] alpha The alpha function to apply.
+   */
+  void AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha);
+
+  /**
+   * @brief Animate a property value by a relative amount.
+   *
+   * The default alpha function will be used.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] relativeValue The property value will increase/decrease by this amount.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateBy(Property target, Property::Value relativeValue, TimePeriod period);
+
+  /**
+   * @brief Animate a property value by a relative amount.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] relativeValue The property value will increase/decrease by this amount.
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateBy(Property target, Property::Value relativeValue, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @brief Animate a property to a destination value.
+   *
+   * The default alpha function will be used.
+   * The effect will start & end when the animation begins & ends.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] destinationValue The destination value.
+   */
+  void AnimateTo(Property target, Property::Value destinationValue);
+
+  /**
+   * @brief Animate a property to a destination value.
+   *
+   * The effect will start & end when the animation begins & ends.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] destinationValue The destination value.
+   * @param [in] alpha The alpha function to apply.
+   */
+  void AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha);
+
+  /**
+   * @brief Animate a property to a destination value.
+   *
+   * The default alpha function will be used.
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] destinationValue The destination value.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateTo(Property target, Property::Value destinationValue, TimePeriod period);
+
+  /**
+   * @brief Animate a property to a destination value.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] destinationValue The destination value.
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateTo(Property target, Property::Value destinationValue, AlphaFunction alpha, TimePeriod period);
+
+   /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] keyFrames The key frames
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object + property to animate
+   * @param [in] keyFrames The set of time / value pairs between which to animate.
+   * @param [in] interpolation The method used to interpolate between values.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, Interpolation interpolation);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] keyFrames The key frames
+   * @param [in] alpha The alpha function to apply.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object + property to animate
+   * @param [in] keyFrames The set of time / value pairs between which to animate.
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] interpolation The method used to interpolate between values.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, Interpolation interpolation);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] keyFrames The key frames
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object + property to animate
+   * @param [in] keyFrames The set of time / value pairs between which to animate.
+   * @param [in] period The effect will occur duing this time period.
+   * @param [in] interpolation The method used to interpolate between values.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, TimePeriod period, Interpolation interpolation);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object/property to animate.
+   * @param [in] keyFrames The key frames
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @brief Animate a property between keyframes.
+   *
+   * @since_tizen 2.4
+   * @param [in] target The target object + property to animate
+   * @param [in] keyFrames The set of time / value pairs between which to animate.
+   * @param [in] alpha The alpha function to apply to the overall progress.
+   * @param [in] period The effect will occur duing this time period.
+   * @param [in] interpolation The method used to interpolate between values.
+   */
+  void AnimateBetween(Property target, KeyFrames& keyFrames, AlphaFunction alpha, TimePeriod period, Interpolation interpolation);
+
+
+  // Actor-specific convenience methods
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @since_tizen 2.4
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @since_tizen 2.4
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] alpha The alpha function to apply.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @since_tizen 2.4
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] period The effect will occur during this time period.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, TimePeriod period );
+
+  /**
+   * @brief Animate an actor's position and orientation through a predefined path. The actor will rotate to orient the supplied
+   * forward vector with the path's tangent. If forward is the zero vector then no rotation will happen.
+   *
+   * @since_tizen 2.4
+   * @param[in] actor The actor to animate
+   * @param[in] path The path. It defines position and orientation
+   * @param[in] forward The vector (in local space coordinate system) that will be oriented with the path's tangent direction
+   * @param [in] alpha The alpha function to apply.
+   * @param [in] period The effect will occur during this time period.
+   */
+  void Animate( Actor actor, Path path, const Vector3& forward, AlphaFunction alpha, TimePeriod period);
+
+  /**
+   * @brief Show an actor during the animation.
+   *
+   * @since_tizen 2.4
+   * @param [in] actor The actor to animate.
+   * @param [in] delaySeconds The initial delay from the start of the animation.
+   */
+  void Show(Actor actor, float delaySeconds);
+
+  /**
+   * @brief Hide an actor during the animation.
+   *
+   * @since_tizen 2.4
+   * @param [in] actor The actor to animate.
+   * @param [in] delaySeconds The initial delay from the start of the animation.
+   */
+  void Hide(Actor actor, float delaySeconds);
+
+public: // Not intended for use by Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods
+   * @since_tizen 2.4
+   * @param [in] animation A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL Animation(Internal::Animation* animation);
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ANIMATION_H__
diff --git a/dali/public-api/animation/constraint-source.cpp b/dali/public-api/animation/constraint-source.cpp
new file mode 100644 (file)
index 0000000..c7fd48f
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/constraint-source.h>
+
+namespace Dali
+{
+
+LocalSource::LocalSource( Property::Index index )
+: propertyIndex( index )
+{
+}
+
+ParentSource::ParentSource( Property::Index index )
+: propertyIndex( index )
+{
+}
+
+Source::Source( Handle& obj, Property::Index index )
+: propertyIndex( index ),
+  object( obj )
+{
+}
+
+ConstraintSource::ConstraintSource( Source source )
+: sourceType( OBJECT_PROPERTY ),
+  propertyIndex( source.propertyIndex ),
+  object( source.object )
+{
+}
+
+ConstraintSource::ConstraintSource( LocalSource local )
+: sourceType( LOCAL_PROPERTY ),
+  propertyIndex( local.propertyIndex )
+{
+}
+
+ConstraintSource::ConstraintSource( ParentSource parent )
+: sourceType( PARENT_PROPERTY ),
+  propertyIndex( parent.propertyIndex )
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/animation/constraint-source.h b/dali/public-api/animation/constraint-source.h
new file mode 100644 (file)
index 0000000..c9c70fb
--- /dev/null
@@ -0,0 +1,142 @@
+#ifndef __DALI_CONSTRAINT_SOURCE_H__
+#define __DALI_CONSTRAINT_SOURCE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+/**
+ * @brief Constraint source types.
+ *
+ * This specifies the location of a property, which is used as an input for a constraint function.
+ * @since_tizen 2.4
+ */
+enum SourceType
+{
+  OBJECT_PROPERTY, ///< The property comes from an arbitrary object.
+  LOCAL_PROPERTY,  ///< The property comes from the object which the constraint is applied to.
+  PARENT_PROPERTY  ///< The property comes from the parent of the object, which the constraint is applied to.
+};
+
+
+/**
+ * @brief Identifies a property from an object.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API LocalSource
+{
+  /**
+   * @brief Create a local constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of a property provided by the constrained object.
+   */
+  LocalSource( Property::Index index );
+
+  Property::Index propertyIndex; ///< The index of a property provided by the constrained object.
+};
+
+/**
+ * @brief Identifies a property from the parent of an object.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API ParentSource
+{
+  /**
+   * @brief Create a local constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of a property, provided by the parent of the constrained object.
+   */
+  ParentSource( Property::Index index );
+
+  Property::Index propertyIndex; ///< The index of a property provided by the parent of the constrained object.
+};
+
+/**
+ * @brief Identifies a property from any object.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API Source
+{
+  /**
+   * @brief Create a constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] object The object providing the property.
+   * @param [in] index The index of a property provided by object.
+   */
+  Source( Handle& object, Property::Index index );
+
+  Property::Index propertyIndex; ///< The index of a property provided by object.
+
+  Handle object; ///< The target object
+};
+
+/**
+ * @brief The source of an input property for a constraint.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API ConstraintSource
+{
+  /**
+   * @brief Create a constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] source A constraint source from an arbitrary object.
+   */
+  ConstraintSource( Source source );
+
+  /**
+   * @brief Create a constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] local A local constraint source.
+   */
+  ConstraintSource( LocalSource local );
+
+  /**
+   * @brief Create a constraint source.
+   *
+   * @since_tizen 2.4
+   * @param [in] parent A parent constraint source.
+   */
+  ConstraintSource( ParentSource parent );
+
+  SourceType sourceType; ///< The source type
+
+  Property::Index propertyIndex; ///< The index of the source property
+
+  Handle object; ///< The target object; only valid if sourceType == OBJECT_PROPERTY
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONSTRAINT_SOURCE_H__
diff --git a/dali/public-api/animation/constraint.cpp b/dali/public-api/animation/constraint.cpp
new file mode 100644 (file)
index 0000000..87e3347
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/constraint.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/animation/constraint-source-impl.h>
+#include <dali/internal/event/animation/property-constraint-ptr.h>
+#include <dali/internal/event/animation/property-constraint.h>
+
+namespace Dali
+{
+
+namespace // unnamed namespace
+{
+
+template < class P >
+Internal::PropertyConstraint< P >* CreatePropertyConstraint( CallbackBase* func )
+{
+  return new Internal::PropertyConstraint< P >( reinterpret_cast< Dali::Constraint::Function< P >* >( func ) );
+}
+
+} // unnamed namespace
+
+const Constraint::RemoveAction Constraint::DEFAULT_REMOVE_ACTION  = Constraint::Bake;
+
+Constraint::Constraint()
+{
+}
+
+Constraint Constraint::Clone( Handle object )
+{
+  return Constraint( GetImplementation( *this ).Clone( GetImplementation( object ) ) );
+}
+
+Constraint::~Constraint()
+{
+}
+
+Constraint::Constraint( const Constraint& constraint )
+: BaseHandle( constraint )
+{
+}
+
+Constraint& Constraint::operator=( const Constraint& rhs )
+{
+  BaseHandle::operator=( rhs );
+  return *this;
+}
+
+Constraint Constraint::DownCast( BaseHandle baseHandle )
+{
+  return Constraint( dynamic_cast< Dali::Internal::ConstraintBase* >( baseHandle.GetObjectPtr() ) );
+}
+
+void Constraint::AddSource( ConstraintSource source )
+{
+  GetImplementation( *this ).AddSource( Internal::Source( source ) );
+}
+
+void Constraint::Apply()
+{
+  GetImplementation( *this ).Apply();
+}
+
+void Constraint::Remove()
+{
+  GetImplementation( *this ).Remove();
+}
+
+Handle Constraint::GetTargetObject()
+{
+  return GetImplementation(*this).GetTargetObject();
+}
+
+Property::Index Constraint::GetTargetProperty()
+{
+  return GetImplementation(*this).GetTargetProperty();
+}
+
+void Constraint::SetRemoveAction(Constraint::RemoveAction action)
+{
+  GetImplementation(*this).SetRemoveAction(action);
+}
+
+Constraint::RemoveAction Constraint::GetRemoveAction() const
+{
+  return GetImplementation(*this).GetRemoveAction();
+}
+
+void Constraint::SetTag( const unsigned int tag )
+{
+  GetImplementation(*this).SetTag( tag );
+}
+
+unsigned int Constraint::GetTag() const
+{
+  return GetImplementation(*this).GetTag();
+}
+
+Constraint::Constraint( Internal::ConstraintBase* constraint )
+: BaseHandle( constraint )
+{
+}
+
+Constraint Constraint::New( Handle handle, Property::Index targetIndex, Property::Type targetType, CallbackBase* function )
+{
+  Constraint constraint;
+  Internal::SourceContainer sources;
+  Internal::Object& object = GetImplementation( handle );
+
+  switch ( targetType )
+  {
+    case Property::BOOLEAN:
+    {
+      Internal::PropertyConstraintPtr< bool >::Type funcPtr( CreatePropertyConstraint< bool >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< bool >::New( object,
+                                                                        targetIndex,
+                                                                        sources,
+                                                                        funcPtr ) );
+      break;
+    }
+
+    case Property::FLOAT:
+    {
+      Internal::PropertyConstraintPtr< float >::Type funcPtr( CreatePropertyConstraint< float >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< float >::New( object,
+                                                                         targetIndex,
+                                                                         sources,
+                                                                         funcPtr ) );
+      break;
+    }
+
+    case Property::INTEGER:
+    {
+      Internal::PropertyConstraintPtr< int >::Type funcPtr( CreatePropertyConstraint< int >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< int >::New( object,
+                                                                       targetIndex,
+                                                                       sources,
+                                                                       funcPtr ) );
+      break;
+    }
+
+    case Property::VECTOR2:
+    {
+      Internal::PropertyConstraintPtr< Vector2 >::Type funcPtr( CreatePropertyConstraint< Vector2 >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Vector2 >::New( object,
+                                                                           targetIndex,
+                                                                           sources,
+                                                                           funcPtr ) );
+      break;
+    }
+
+    case Property::VECTOR3:
+    {
+      Internal::PropertyConstraintPtr< Vector3 >::Type funcPtr( CreatePropertyConstraint< Vector3 >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Vector3 >::New( object,
+                                                                           targetIndex,
+                                                                           sources,
+                                                                           funcPtr ) );
+      break;
+    }
+
+    case Property::VECTOR4:
+    {
+      Internal::PropertyConstraintPtr< Vector4 >::Type funcPtr( CreatePropertyConstraint< Vector4 >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Vector4 >::New( object,
+                                                                           targetIndex,
+                                                                           sources,
+                                                                           funcPtr ) );
+      break;
+    }
+
+    case Property::ROTATION:
+    {
+      Internal::PropertyConstraintPtr< Quaternion >::Type funcPtr( CreatePropertyConstraint< Quaternion >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Quaternion >::New( object,
+                                                                              targetIndex,
+                                                                              sources,
+                                                                              funcPtr ) );
+      break;
+    }
+
+    case Property::MATRIX:
+    {
+      Internal::PropertyConstraintPtr< Matrix >::Type funcPtr( CreatePropertyConstraint< Matrix >( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Matrix >::New( object,
+                                                                          targetIndex,
+                                                                          sources,
+                                                                          funcPtr ) );
+      break;
+    }
+
+    case Property::MATRIX3:
+    {
+      Internal::PropertyConstraintPtr<Matrix3>::Type funcPtr( CreatePropertyConstraint<Matrix3>( function ) );
+
+      constraint = Dali::Constraint( Internal::Constraint< Matrix3 >::New( object,
+                                                                           targetIndex,
+                                                                           sources,
+                                                                           funcPtr ) );
+      break;
+    }
+
+    default:
+    {
+      DALI_ASSERT_ALWAYS( false && "Property type enumeration out of bounds" ); // should never come here
+      break;
+    }
+  }
+
+  return constraint;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/animation/constraint.h b/dali/public-api/animation/constraint.h
new file mode 100644 (file)
index 0000000..9310f07
--- /dev/null
@@ -0,0 +1,543 @@
+#ifndef __DALI_CONSTRAINT_H__
+#define __DALI_CONSTRAINT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint-source.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/signals/callback.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+class Handle;
+
+namespace Internal DALI_INTERNAL
+{
+class ConstraintBase;
+}
+
+typedef Vector< PropertyInput* > PropertyInputContainer;
+
+/**
+ * @brief An abstract base class for Constraints.
+ *
+ * This can be used to constrain a property of an object, after animations have been applied.
+ * Constraints are applied in the following order:
+ *   - Constraints are applied to on-stage actors in a depth-first traversal.
+ *   - For each actor, the constraints are applied in the same order as the calls to Apply().
+ *   - Constraints are not applied to off-stage actors.
+ *
+ * Create a constraint using one of the New methods depending on the type of callback function used.
+ * Try to use a C function unless some data needs to be stored, otherwise functors and class methods
+ * are also supported.
+ *
+ * A constraint can be applied to an object in the following manner:
+ *
+ * @code
+ * Handle handle = CreateMyObject();
+ * Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, &MyFunction );
+ * constraint.AddSource( LocalSource( INPUT_PROPERTY_INDEX ) );
+ * constraint.Apply();
+ * @endcode
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Constraint : public BaseHandle
+{
+public:
+
+  /**
+   * @brief Template for the Function that is called by the Constraint system.
+   *
+   * Supports:
+   *  - C style functions
+   *  - Static member methods of an object
+   *  - Member functions of a particular class
+   *  - Functors of a particular class
+   *  - If a functor or method is provided, then a copy of the object is made.
+   *
+   * The expected signature of the callback should be:
+   * @code
+   *   void Function( P&, const PropertyInputContainer& );
+   * @endcode
+   *
+   * The P& parameter is an in,out parameter which stores the current value of the property. The callback
+   * should change this value to the desired one. The PropertyInputContainer is a const reference to the property inputs
+   * added to the Constraint in the order they were added via AddSource().
+   *
+   * @tparam  P  The property type to constrain.
+   * @since_tizen 2.4
+   */
+  template< typename P >
+  class DALI_INTERNAL Function : public CallbackBase
+  {
+  public:
+
+    /**
+     * @brief Constructor which connects to the provided C function (or a static member function).
+     *
+     * The expected signature of the function is:
+     * @code
+     *   void MyFunction( P&, const PropertyInputContainer& );
+     * @endcode
+     *
+     * @since_tizen 2.4
+     * @param[in]  function  The function to call.
+     */
+    Function( void( *function )( P&, const PropertyInputContainer& ) )
+    : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) ),
+      mCopyConstructorDispatcher( NULL )
+    {
+    }
+
+    /**
+     * @brief Constructor which copies a function object and connects to the functor of that object.
+     *
+     * The function object should have a functor with the following signature:
+     * @code
+     *   void operator()( P&, const PropertyInputContainer& );
+     * @endcode
+     *
+     * @since_tizen 2.4
+     * @param[in]  object  The object to copy.
+     *
+     * @tparam  T  The type of the object.
+     */
+    template< class T >
+    Function( const T& object )
+    : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                    NULL, // uses operator() instead of member function
+                    reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcher2< T, P&, const PropertyInputContainer& >::Dispatch ),
+                    reinterpret_cast< CallbackBase::Destructor >( &Destroyer< T >::Delete ) ),
+      mCopyConstructorDispatcher( reinterpret_cast< CopyConstructorDispatcher >( &ObjectCopyConstructorDispatcher< T >::Copy ) )
+    {
+    }
+
+    /**
+     * @brief Constructor which copies a function object and allows a connection to a member method.
+     *
+     * The object should have a method with the signature:
+     * @code
+     *   void MyObject::MyMethod( P&, const PropertyInputContainer& );
+     * @endcode
+     *
+     * @since_tizen 2.4
+     * @param[in]  object          The object to copy.
+     * @param[in]  memberFunction  The member function to call. This has to be a member of the same class.
+     *
+     * @tparam  T  The type of the object.
+     */
+    template< class T >
+    Function( const T& object, void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) )
+    : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                    reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                    reinterpret_cast< CallbackBase::Dispatcher >( &Dispatcher2< T, P&, const PropertyInputContainer& >::Dispatch ),
+                    reinterpret_cast< CallbackBase::Destructor >( &Destroyer< T >::Delete ) ),
+      mCopyConstructorDispatcher( reinterpret_cast< CopyConstructorDispatcher >( &ObjectCopyConstructorDispatcher< T >::Copy ) )
+    {
+    }
+
+    /**
+     * @brief Clones the Function object.
+     *
+     * The object, if held by this object, is also copied.
+     *
+     * @since_tizen 2.4
+     * @return A pointer to a newly-allocation Function.
+     */
+    CallbackBase* Clone()
+    {
+      CallbackBase* callback = NULL;
+      if ( mImpl && mImpl->mObjectPointer && mCopyConstructorDispatcher )
+      {
+        callback = new Function( mCopyConstructorDispatcher( reinterpret_cast< UndefinedClass* >( mImpl->mObjectPointer ) ) /* Copy the object */,
+                                 mMemberFunction,
+                                 mImpl->mMemberFunctionDispatcher,
+                                 mImpl->mDestructorDispatcher,
+                                 mCopyConstructorDispatcher );
+      }
+      else
+      {
+        callback = new Function( mFunction );
+      }
+      return callback;
+    }
+
+  private:
+
+    /**
+     * @brief Must not be declared.
+     *
+     * This is used so that no optimisations are done by the compiler when using void*.
+     */
+    class UndefinedClass;
+
+    /**
+     * @brief Used to call the function to copy the stored object
+     * @since_tizen 2.4
+     */
+    typedef UndefinedClass* (*CopyConstructorDispatcher) ( UndefinedClass* object );
+
+    /**
+     * @brief Copies the actual object in Constraint::Function.
+     *
+     * @tparam  T  The type of the object.
+     * @since_tizen 2.4
+     */
+    template< class T >
+    struct ObjectCopyConstructorDispatcher
+    {
+      /**
+       * @brief Copy the object stored in Constraint::Function.
+       *
+       * @since_tizen 2.4
+       * @param[in]  object  The object to copy.
+       *
+       * @return Newly allocated clone of the object.
+       */
+      static UndefinedClass* Copy( const UndefinedClass* object )
+      {
+        T* copy = new T( *( reinterpret_cast< const T* >( object ) ) );
+        return reinterpret_cast< UndefinedClass* >( copy );
+      }
+    };
+
+    /**
+     * @brief Undefined copy constructor
+     * @since_tizen 2.4
+     */
+    Function( const Function& );
+
+    /**
+     * @brief Undefined assignment operator
+     * @since_tizen 2.4
+     */
+    Function& operator=( const Function& );
+
+    /**
+     * @brief Constructor used when copying the stored object.
+     *
+     * @since_tizen 2.4
+     * @param[in]  object                     A newly copied object
+     * @param[in]  memberFunction             The member function of the object.
+     * @param[in]  dispatcher                 Used to call the actual object.
+     * @param[in]  destructor                 Used to delete the owned object.
+     * @param[in]  copyConstructorDispatcher  Used to create a copy of the owned object.
+     */
+    Function( void* object,
+              CallbackBase::MemberFunction memberFunction,
+              CallbackBase::Dispatcher dispatcher,
+              CallbackBase::Destructor destructor,
+              CopyConstructorDispatcher copyConstructorDispatcher )
+    : CallbackBase( object, memberFunction, dispatcher, destructor ),
+      mCopyConstructorDispatcher( copyConstructorDispatcher )
+    {
+    }
+
+    /**
+     * @brief Constructor used when copying a simple stored function.
+     *
+     * @since_tizen 2.4
+     * @param[in]  function   The function to call.
+     */
+    Function( CallbackBase::Function function )
+    : CallbackBase( function ),
+      mCopyConstructorDispatcher( NULL )
+    {
+    }
+
+    // Data
+
+    CopyConstructorDispatcher mCopyConstructorDispatcher; ///< Function to call to copy the stored object
+  };
+
+  /**
+   * @brief The action that will happen when the constraint is removed.
+   *
+   * The final value may be "baked" i.e. saved permanently.
+   * Alternatively the constrained value may be discarded when the constraint is removed.
+   * @since_tizen 2.4
+   */
+  enum RemoveAction
+  {
+    Bake,   ///< When the constraint is fully-applied, the constrained value is saved.
+    Discard ///< When the constraint is removed, the constrained value is discarded.
+  };
+
+  static const RemoveAction  DEFAULT_REMOVE_ACTION;  ///< Bake
+
+  /**
+   * @brief Create an uninitialized Constraint; this can be initialized with Constraint::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  Constraint();
+
+  /**
+   * @brief Create a constraint which targets a property using a function or a static class member.
+   *
+   * The expected signature, for a Vector3 type for example, of the function is:
+   * @code
+   *   void MyFunction( Vector3&, const PropertyInputContainer& );
+   * @endcode
+   *
+   * Create the constraint with this function as follows:
+   * @code
+   *   Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, &MyFunction );
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param[in]  handle       The handle to the property-owning object.
+   * @param[in]  targetIndex  The index of the property to constrain.
+   * @param[in]  function     The function to call to set the constrained property value.
+   * @return The new constraint.
+   *
+   * @tparam P The type of the property to constrain.
+   */
+  template< class P >
+  static Constraint New( Handle handle, Property::Index targetIndex, void( *function )( P&, const PropertyInputContainer& ) )
+  {
+    CallbackBase* callback = new Constraint::Function< P >( function );
+    return New( handle, targetIndex, PropertyTypes::Get< P >(), callback );
+  }
+
+  /**
+   * @brief Create a constraint which targets a property using a functor object.
+   *
+   * The expected structure, for a Vector3 type for example, of the functor object is:
+   * @code
+   *   struct MyObject
+   *   {
+   *     void operator() ( Vector3&, const PropertyInputContainer& );
+   *   };
+   * @endcode
+   *
+   * Create the constraint with this object as follows:
+   * @code
+   *   Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, MyObject() );
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param[in]  handle       The handle to the property-owning object.
+   * @param[in]  targetIndex  The index of the property to constrain.
+   * @param[in]  object       The functor object whose functor is called to set the constrained property value.
+   * @return The new constraint.
+   *
+   * @tparam P The type of the property to constrain.
+   * @tparam T The type of the object.
+   */
+  template< class P, class T >
+  static Constraint New( Handle handle, Property::Index targetIndex, const T& object )
+  {
+    CallbackBase* function = new Constraint::Function< P >( object );
+    return New( handle, targetIndex, PropertyTypes::Get< P >(), function );
+  }
+
+  /**
+   * @brief Create a constraint which targets a property using an object method.
+   *
+   * The expected structure, for a Vector3 type for example, of the object is:
+   * @code
+   *   struct MyObject
+   *   {
+   *     void MyMethod( Vector3&, const PropertyInputContainer& );
+   *   };
+   * @endcode
+   *
+   * Create the constraint with this object as follows:
+   * @code
+   *   Constraint constraint = Constraint::New< Vector3 >( handle, CONSTRAINING_PROPERTY_INDEX, MyObject(), &MyObject::MyMethod );
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param[in]  handle          The handle to the property-owning object.
+   * @param[in]  targetIndex     The index of the property to constrain.
+   * @param[in]  object          The object whose member function is called to set the constrained property value.
+   * @param[in]  memberFunction  The member function to call to set the constrained property value.
+   * @return The new constraint.
+   *
+   * @tparam P The type of the property to constrain.
+   * @tparam T The type of the object.
+   */
+  template< class P, class T >
+  static Constraint New( Handle handle, Property::Index targetIndex, const T& object, void ( T::*memberFunction ) ( P&, const PropertyInputContainer& ) )
+  {
+    CallbackBase* function = new Constraint::Function< P >( object, memberFunction );
+    return New( handle, targetIndex, PropertyTypes::Get< P >(), function );
+  }
+
+  /**
+   * @brief Creates a clones of this constraint for another object.
+   *
+   * @since_tizen 2.4
+   * @param[in]  handle  The handle to the property-owning object this constraint is to be cloned for.
+   *
+   * @return The new constraint.
+   */
+  Constraint Clone( Handle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Constraint();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in]  constraint  A reference to the copied handle
+   */
+  Constraint( const Constraint& constraint );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Constraint& operator=( const Constraint& rhs );
+
+  /**
+   * @brief Downcast an Object handle to Constraint handle.
+   *
+   * If handle points to a Constraint object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in]  baseHandle  to An object
+   * @return handle to a Constraint object or an uninitialized handle
+   */
+  static Constraint DownCast( BaseHandle baseHandle );
+
+  /**
+   * @brief Adds a constraint source to the constraint
+   *
+   * @since_tizen 2.4
+   * @param[in] source The constraint source input to add
+   */
+  void AddSource( ConstraintSource source );
+
+  /**
+   * @brief Applies this constraint.
+   *
+   * @since_tizen 2.4
+   * @pre The constraint must be initialized
+   * @pre The target object must still be alive
+   * @pre The source inputs should not have been destroyed
+   */
+  void Apply();
+
+  /**
+   * @brief Removes this constraint.
+   * @since_tizen 2.4
+   */
+  void Remove();
+
+  /**
+   * @brief Retrieve the object which this constraint is targeting.
+   *
+   * @since_tizen 2.4
+   * @return The target object.
+   */
+  Handle GetTargetObject();
+
+  /**
+   * @brief Retrieve the property which this constraint is targeting.
+   *
+   * @since_tizen 2.4
+   * @return The target property.
+   */
+  Dali::Property::Index GetTargetProperty();
+
+  /**
+   * @brief Set whether the constraint will "bake" a value when fully-applied.
+   *
+   * Otherwise the constrained value will be discarded, when the constraint is removed.
+   * The default value is Constraint::Bake.
+   * @since_tizen 2.4
+   * @param[in] action The remove-action.
+   */
+  void SetRemoveAction( RemoveAction action );
+
+  /**
+   * @brief Query whether the constraint will "bake" a value when fully-applied.
+   *
+   * Otherwise the constrained value will be discarded, when the constraint is removed.
+   * @since_tizen 2.4
+   * @return The apply-action.
+   */
+  RemoveAction GetRemoveAction() const;
+
+  /**
+   * @brief Set a tag for the constraint so it can be identified later
+   *
+   * @since_tizen 2.4
+   * @param[in] tag An integer to identify the constraint
+   */
+  void SetTag( const unsigned int tag );
+
+  /**
+   * @brief Get the tag
+   *
+   * @since_tizen 2.4
+   * @return The tag
+   */
+  unsigned int GetTag() const;
+
+public: // Not intended for use by Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods
+   * @since_tizen 2.4
+   * @param [in] constraint A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL Constraint( Internal::ConstraintBase* constraint );
+
+private: // Not intended for use by Application developers
+
+  /**
+   * @brief Construct a new constraint which targets a property.
+   *
+   * @since_tizen 2.4
+   * @param[in]  handle       The handle to the property-owning object.
+   * @param[in]  targetIndex  The index of the property to constrain.
+   * @param[in]  targetType   Type The type of the constrained property.
+   * @param[in]  function     The constraint function.
+   * @return The new constraint.
+   */
+  static Constraint New( Handle handle, Property::Index targetIndex, Property::Type targetType, CallbackBase* function );
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONSTRAINT_H__
diff --git a/dali/public-api/animation/constraints.h b/dali/public-api/animation/constraints.h
new file mode 100644 (file)
index 0000000..9953a34
--- /dev/null
@@ -0,0 +1,247 @@
+#ifndef __DALI_CONSTRAINTS_H__
+#define __DALI_CONSTRAINTS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/object/property-input.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+/**
+ * @brief EqualToConstraint
+ *
+ * f(current, property) = property
+ * @since_tizen 2.4
+ */
+struct EqualToConstraint
+{
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  EqualToConstraint()
+  { }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in, out] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( float& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetFloat();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Vector2& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetVector2();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in,out] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Vector3& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetVector3();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in,out] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Vector4& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetVector4();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in,out] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Quaternion& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetQuaternion();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in,out] current The current property value
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Matrix3& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetMatrix3();
+  }
+
+  /**
+   * @brief override functor for float properties
+   *
+   * @since_tizen 2.4
+   * @param[in,out] current The current property value, the constrained value is set
+   * @param[in] inputs Contains the property to copy
+   * @return The copy of the input property
+   */
+  void operator()( Matrix& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetMatrix();
+  }
+
+};
+
+/**
+ * @brief RelativeToConstraint for Vector3 properties
+ *
+ * current = property * scale
+ * @since_tizen 2.4
+ */
+struct RelativeToConstraint
+{
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  RelativeToConstraint( float scale )
+  : mScale( scale, scale, scale ) { }
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  RelativeToConstraint( const Vector3& scale )
+  : mScale( scale ) { }
+
+  /**
+   * @brief Functor.
+   * @since_tizen 2.4
+   */
+  void operator()( Vector3& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetVector3() * mScale;
+  }
+
+  Vector3 mScale; ///< Component-wise scale factor
+};
+
+/**
+ * @brief RelativeToConstraint for float properties
+ * @since_tizen 2.4
+ */
+struct RelativeToConstraintFloat
+{
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  RelativeToConstraintFloat( float scale )
+  : mScale( scale ) { }
+
+  /**
+   * @brief Functor.
+   * @since_tizen 2.4
+   */
+  void operator()( float& current, const PropertyInputContainer& inputs )
+  {
+    current = inputs[0]->GetFloat() * mScale;
+  }
+
+  float mScale; ///< Scale factor
+};
+
+/**
+ * @brief Constraint function to aim a camera at a target.
+ *
+ * Constraint which sets camera's orientation given camera world position
+ * and a target world position.  Uses target's up vector to orient the
+ * constrained actor along the vector between camera position and
+ * target position.
+ *
+ * @since_tizen 2.4
+ * @param[in,out] current The current orientation property value, the constrained value is set.
+ * @param[in] inputs Contains the World position of the target, the World position of the camera, and the world orientation of the target
+ * @return The orientation of the camera
+ */
+inline void LookAt( Quaternion& current, const PropertyInputContainer& inputs )
+{
+  const PropertyInput& targetPosition( *inputs[0] );
+  const PropertyInput& cameraPosition( *inputs[1] );
+  const PropertyInput& targetOrientation( *inputs[2] );
+
+  Vector3 vForward = targetPosition.GetVector3() - cameraPosition.GetVector3();
+  vForward.Normalize();
+
+  const Quaternion& targetOrientationQ = targetOrientation.GetQuaternion();
+
+  Vector3 targetY(targetOrientationQ.Rotate(Vector3::YAXIS));
+  targetY.Normalize();
+
+  // Camera Right vector is perpendicular to forward & target up
+  Vector3 vX = targetY.Cross(vForward);
+  vX.Normalize();
+
+  // Camera Up vector is perpendicular to forward and right
+  Vector3 vY = vForward.Cross(vX);
+  vY.Normalize();
+
+  current = Quaternion( vX, vY, vForward );
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONSTRAINTS_H__
diff --git a/dali/public-api/animation/key-frames.cpp b/dali/public-api/animation/key-frames.cpp
new file mode 100644 (file)
index 0000000..34148e9
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/key-frames.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/internal/event/animation/key-frames-impl.h>
+
+namespace Dali
+{
+
+KeyFrames KeyFrames::New()
+{
+  Internal::KeyFrames* internal = Internal::KeyFrames::New();
+  return KeyFrames(internal);
+}
+
+KeyFrames KeyFrames::DownCast( BaseHandle handle )
+{
+  return KeyFrames( dynamic_cast<Dali::Internal::KeyFrames*>(handle.GetObjectPtr()) );
+}
+
+KeyFrames::KeyFrames()
+{
+}
+
+KeyFrames::~KeyFrames()
+{
+}
+
+KeyFrames::KeyFrames(const KeyFrames& handle)
+: BaseHandle(handle)
+{
+}
+
+KeyFrames& KeyFrames::operator=(const KeyFrames& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+Property::Type KeyFrames::GetType() const
+{
+  return GetImplementation(*this).GetType();
+}
+
+void KeyFrames::Add(float time, Property::Value value)
+{
+  Add(time, value, AlphaFunction::DEFAULT);
+}
+
+void KeyFrames::Add(float time, Property::Value value, AlphaFunction alpha)
+{
+  GetImplementation(*this).Add(time, value, alpha);
+}
+
+KeyFrames::KeyFrames(Internal::KeyFrames* internal)
+  : BaseHandle(internal)
+{
+}
+
+
+
+} // Dali
diff --git a/dali/public-api/animation/key-frames.h b/dali/public-api/animation/key-frames.h
new file mode 100644 (file)
index 0000000..b5592b2
--- /dev/null
@@ -0,0 +1,150 @@
+#ifndef __DALI_KEY_FRAMES_H__
+#define __DALI_KEY_FRAMES_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property-types.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class KeyFrames;
+}
+
+/**
+ * @brief A set of key frames for a property that can be animated using Dali::Animation::AnimateBetween().
+ *
+ * This allows the generation of key frame objects from individual
+ * Property::Values. The type of the key frame is specified by the
+ * type of the first value to be added. Adding key frames with a
+ * different Property::Value type will result in a run time assert.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API KeyFrames : public BaseHandle
+{
+public:
+  /**
+   * @brief Create an initialized KeyFrame handle.
+   *
+   * @since_tizen 2.4
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static KeyFrames New();
+
+  /**
+   * @brief Downcast an Object handle to KeyFrames handle.
+   *
+   * If handle points to a KeyFrames object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a KeyFrames object or an uninitialized handle
+   */
+  static KeyFrames DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized KeyFrame handle.
+   *
+   * This can be initialized with KeyFrame::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  KeyFrames();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~KeyFrames();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  KeyFrames(const KeyFrames& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  KeyFrames& operator=(const KeyFrames& rhs);
+
+  /**
+   * @brief Gets the type of the key frame.
+   *
+   * If no key frames have been added, this returns Property::NONE.
+   * @since_tizen 2.4
+   * @return The key frame property type.
+   */
+  Property::Type GetType() const;
+
+  /**
+   * @brief Add a key frame.
+   *
+   * The key frames should be added in time order.
+   * @since_tizen 2.4
+   * @param[in] progress A value between 0.0 and 1.0.
+   * @param[in] value A value.
+   */
+  void Add(float progress, Property::Value value);
+
+  /**
+   * @brief Add a key frame.
+   *
+   * The key frames should be added in time order.
+   * @since_tizen 2.4
+   * @param[in] progress A value between 0.0 and 1.0.
+   * @param[in] value A value.
+   * @param[in] alpha The alpha function used to blend to the next keyframe
+   */
+  void Add(float progress, Property::Value value, AlphaFunction alpha);
+
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @since_tizen 2.4
+   * @param[in] keyFrames A pointer to an internal KeyFrame resource
+   */
+  explicit DALI_INTERNAL KeyFrames(Internal::KeyFrames* keyFrames);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_KEY_FRAMES_H__
diff --git a/dali/public-api/animation/linear-constrainer.cpp b/dali/public-api/animation/linear-constrainer.cpp
new file mode 100644 (file)
index 0000000..8d81f9e
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/linear-constrainer.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/animation/linear-constrainer-impl.h>
+
+
+namespace Dali
+{
+
+LinearConstrainer LinearConstrainer::New()
+{
+  Internal::LinearConstrainer* internal = Internal::LinearConstrainer::New();
+  return LinearConstrainer(internal);
+}
+
+LinearConstrainer LinearConstrainer::DownCast( BaseHandle handle )
+{
+  return LinearConstrainer( dynamic_cast<Dali::Internal::LinearConstrainer*>(handle.GetObjectPtr()) );
+}
+
+LinearConstrainer::LinearConstrainer()
+{
+}
+
+LinearConstrainer::~LinearConstrainer()
+{
+}
+
+LinearConstrainer::LinearConstrainer(const LinearConstrainer& handle)
+:Handle(handle)
+{
+}
+
+LinearConstrainer::LinearConstrainer(Internal::LinearConstrainer* internal)
+: Handle(internal)
+{
+}
+
+LinearConstrainer& LinearConstrainer::operator=(const LinearConstrainer& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void LinearConstrainer::Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap )
+{
+  GetImplementation(*this).Apply( target, source, range, wrap );
+}
+
+void LinearConstrainer::Remove( Dali::Handle& target )
+{
+  GetImplementation(*this).Remove( target );
+}
+
+
+} // Dali
diff --git a/dali/public-api/animation/linear-constrainer.h b/dali/public-api/animation/linear-constrainer.h
new file mode 100644 (file)
index 0000000..a68becd
--- /dev/null
@@ -0,0 +1,153 @@
+#ifndef __DALI_LINEAR_CONSTRAINER_H__
+#define __DALI_LINEAR_CONSTRAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+//EXTERNAL INCLUDES
+#include <cfloat> //For FLT_MAX
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+  class LinearConstrainer;
+}
+
+/**
+ * @brief
+ *
+ * LinearConstrainer applies constraints to objects given a linear map.
+ * A linear map is defined by a set of value-progress pairs.
+ * Progress must be normalized between [0,1]. If no progress is defined, the values
+ * are considered to be equally spaced along the x axis.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API LinearConstrainer : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the LinearConstrainer class.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      VALUE     = DEFAULT_OBJECT_PROPERTY_START_INDEX,  ///< name "value" type Array of float
+      PROGRESS,                                         ///< name "progress" type Array of float
+    };
+  };
+
+  /**
+   * @brief Create an initialized LinearConstrainer handle.
+   *
+   * @since_tizen 2.4
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static LinearConstrainer New();
+
+  /**
+   * @brief Downcast an Object handle to LinearConstrainer handle.
+   *
+   * If handle points to a LinearConstrainer object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a LinearConstrainer object or an uninitialized handle
+   */
+  static LinearConstrainer DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized LinearConstrainer handle.
+   *
+   * This can be initialized with PathConstrainer::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  LinearConstrainer();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~LinearConstrainer();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  LinearConstrainer(const LinearConstrainer& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  LinearConstrainer& operator=(const LinearConstrainer& rhs);
+
+  /**
+   * @brief Applies the linear constraint to the target property
+   *
+   * @since_tizen 2.4
+   * @param[in] target Property to be constrained
+   * @param[in] source Property used as parameter for the path
+   * @param[in] range The range of values in the source property which will be mapped to [0,1]
+   * @param[in] wrap Wrapping domain. Source property will be wrapped in the domain [wrap.x,wrap.y] before mapping to [0,1]
+   */
+  void Apply( Dali::Property target, Dali::Property source, const Vector2& range, const Vector2& wrap = Vector2(-FLT_MAX, FLT_MAX) );
+
+  /**
+   * @brief Removes the linear constraint in the target object
+   *
+   * @since_tizen 2.4
+   * @param[in] target A handle to an object constrained by the LinearConstrainer
+   */
+  void Remove( Dali::Handle& target );
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @since_tizen 2.4
+   * @param[in] pathConstrainer A pointer to an internal PathConstrainer resource
+   */
+  explicit DALI_INTERNAL LinearConstrainer(Internal::LinearConstrainer* pathConstrainer);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_LINEAR_CONSTRAINER_H__
diff --git a/dali/public-api/animation/path.cpp b/dali/public-api/animation/path.cpp
new file mode 100644 (file)
index 0000000..da34a19
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/path.h>
+#include <dali/internal/event/animation/path-impl.h>
+
+// INTERNAL INCLUDES
+
+namespace Dali
+{
+
+Path Path::New()
+{
+  Internal::Path* internal = Internal::Path::New();
+  return Path(internal);
+}
+
+Path Path::DownCast( BaseHandle handle )
+{
+  return Path( dynamic_cast<Dali::Internal::Path*>(handle.GetObjectPtr()) );
+}
+
+Path::Path()
+{
+}
+
+Path::~Path()
+{
+}
+
+Path::Path(const Path& handle)
+:Handle(handle)
+{
+}
+
+Path::Path(Internal::Path* internal)
+: Handle(internal)
+{
+}
+
+Path& Path::operator=(const Path& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void Path::AddPoint(const Vector3& point )
+{
+  GetImplementation(*this).AddPoint( point );
+}
+
+void Path::AddControlPoint(const Vector3& point )
+{
+  GetImplementation(*this).AddControlPoint( point );
+}
+
+void Path::GenerateControlPoints( float curvature )
+{
+  GetImplementation(*this).GenerateControlPoints( curvature );
+}
+
+
+void Path::Sample( float progress, Vector3& position, Vector3& tangent ) const
+{
+  GetImplementation(*this).Sample( progress, position, tangent );
+}
+
+Vector3& Path::GetPoint( size_t index )
+{
+  return GetImplementation(*this).GetPoint(index);
+}
+
+Vector3& Path::GetControlPoint( size_t index )
+{
+  return GetImplementation(*this).GetControlPoint(index);
+}
+
+size_t Path::GetPointCount() const
+{
+  return GetImplementation(*this).GetPointCount();
+}
+
+} // Dali
diff --git a/dali/public-api/animation/path.h b/dali/public-api/animation/path.h
new file mode 100644 (file)
index 0000000..66e63d3
--- /dev/null
@@ -0,0 +1,201 @@
+#ifndef __DALI_PATH_H__
+#define __DALI_PATH_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class Path;
+}
+
+/**
+ * @brief A 3D parametric curve
+ *
+ * Paths can be used to animate position and orientation of actors using Dali::Animate( Actor, Path, ... )
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Path : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the Path class.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      POINTS         = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "points",         type Vector3
+      CONTROL_POINTS,                                       ///< name "control-points", type Vector3
+    };
+  };
+
+  /**
+   * @brief Create an initialized Path handle.
+   *
+   * @since_tizen 2.4
+   * @return a handle to a newly allocated Dali resource.
+   */
+  static Path New();
+
+  /**
+   * @brief Downcast an Object handle to Path handle.
+   *
+   * If handle points to a KeyFrames object the downcast produces
+   * valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Path object or an uninitialized handle
+   */
+  static Path DownCast( BaseHandle handle );
+
+  /**
+   * @brief Create an uninitialized Path handle.
+   *
+   * This can be initialized with Path::New(). Calling member
+   * functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  Path();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Path();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  Path(const Path& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Path& operator=(const Path& rhs);
+
+  /**
+   * @brief Add an interpolation point.
+   *
+   * @since_tizen 2.4
+   * @param[in] point The new interpolation point to be added
+   */
+  void AddPoint(const Vector3& point );
+
+  /**
+   * @brief Add a control point.
+   *
+   * @since_tizen 2.4
+   * @param[in] point The new control point to be added
+   */
+  void AddControlPoint(const Vector3& point );
+
+  /**
+   * @brief Automatic generation of control points. Generated control points which result in a smooth join between the splines of each segment.
+   *
+   * The generating algorithm is as follows:
+   * For a given knot point K[N], find the vector that bisects K[N-1],[N] and [N],[N+1].
+   * Calculate the tangent vector by taking the normal of this bisector.
+   * The in control point is the length of the preceding segment back along this bisector multiplied by the curvature
+   * The out control point is the length of the succeeding segment forward along this bisector multiplied by the curvature
+   *
+   * @since_tizen 2.4
+   * @param[in] curvature The curvature of the spline. 0 gives straight lines between the knots,
+   *                      negative values means the spline contains loops, positive values up to
+   *                      0.5 result in a smooth curve, positive values between 0.5 and 1 result
+   *                      in looped curves where the loops are not distinct (i.e. the curve appears
+   *                      to be non-continuous), positive values higher than 1 result in looped curves.
+   * @pre There are at least two points in the path ( one segment ).
+   *
+   */
+  void GenerateControlPoints( float curvature );
+
+  /**
+   * @brief Sample path at a given progress. Calculates position and tangent at that point of the curve
+   *
+   * @since_tizen 2.4
+   * @param[in]  progress  A floating point value between 0.0 and 1.0.
+   * @param[out] position The interpolated position at that progress.
+   * @param[out] tangent The interpolated tangent at that progress.
+   */
+  void Sample( float progress, Vector3& position, Vector3& tangent ) const;
+
+  /**
+   * @brief Accessor for the interpolation points.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The index of the interpolation point.
+   * @return A reference to the interpolation point.
+   */
+  Vector3& GetPoint( size_t index );
+
+  /**
+   * @brief Accessor for the control points.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The index of the control point.
+   * @return A reference to the control point.
+   */
+  Vector3& GetControlPoint( size_t index );
+
+  /**
+   * @brief Get the number of interpolation points in the path
+   *
+   * @since_tizen 2.4
+   * @return The number of interpolation points in the path
+   */
+  size_t GetPointCount() const;
+
+public: // Not intended for application developers
+  /**
+   * @brief This constructor is used by Dali::New() methods.
+   *
+   * @since_tizen 2.4
+   * @param[in] path A pointer to an internal path resource
+   */
+  explicit DALI_INTERNAL Path(Internal::Path* path);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_KEY_FRAMES_H__
diff --git a/dali/public-api/animation/time-period.cpp b/dali/public-api/animation/time-period.cpp
new file mode 100644 (file)
index 0000000..1006764
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/animation/time-period.h>
+
+namespace Dali
+{
+
+TimePeriod::TimePeriod(float duration)
+: delaySeconds(0.0f),
+  durationSeconds(duration)
+{
+}
+
+TimePeriod::TimePeriod(float delay, float duration)
+: delaySeconds(delay),
+  durationSeconds(duration)
+{
+}
+
+TimePeriod::~TimePeriod()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/animation/time-period.h b/dali/public-api/animation/time-period.h
new file mode 100644 (file)
index 0000000..66b7a80
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef __DALI_TIME_PERIOD_H__
+#define __DALI_TIME_PERIOD_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_animation
+ * @{
+ */
+
+/**
+ * @brief A value-type representing a period of time within an animation.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API TimePeriod
+{
+  /**
+   * @brief Create a time period.
+   *
+   * @since_tizen 2.4
+   * @param [in] durationSeconds The duration of the time period in seconds.
+   */
+  explicit TimePeriod(float durationSeconds);
+
+  /**
+   * @brief Create a time period.
+   *
+   * @since_tizen 2.4
+   * @param [in] delaySeconds A delay before the time period in seconds.
+   * @param [in] durationSeconds The duration of the time period in seconds.
+   */
+  TimePeriod(float delaySeconds, float durationSeconds);
+
+  /**
+   * @brief Non-virtual destructor; TimePeriod is not intended as a base class.
+   * @since_tizen 2.4
+   */
+  ~TimePeriod();
+
+  float delaySeconds;    ///< A delay before the time period in seconds
+  float durationSeconds; ///< The duration of the time period in seconds
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_TIME_PERIOD_H__
diff --git a/dali/public-api/common/compile-time-assert.h b/dali/public-api/common/compile-time-assert.h
new file mode 100644 (file)
index 0000000..e2f9c7b
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __DALI_COMPILE_TIME_ASSERT_H__
+#define __DALI_COMPILE_TIME_ASSERT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+template <bool x> struct CompileTimeAssertBool;    ///< Bool Template to test condition
+template <> struct CompileTimeAssertBool<true> {}; ///< Specialize for true, but not for false
+
+template<int x> struct CompileTimeAssertInt {};    ///< Template to wrap conditional template CompileTimeAsserBool
+
+/**
+ * @brief Use DALI_COMPILE_TIME_ASSERT to test expressions at compile time.
+ *
+ * If x is false, then 'sizeof' will be attempted with incomplete type.
+ * @since_tizen 2.4
+ */
+#define DALI_COMPILE_TIME_ASSERT( x ) typedef CompileTimeAssertInt< sizeof( CompileTimeAssertBool< ( x ) > ) > CompileTimeAssertType __attribute__((__unused__))
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_COMPILE_TIME_ASSERT_H__
diff --git a/dali/public-api/common/constants.cpp b/dali/public-api/common/constants.cpp
new file mode 100644 (file)
index 0000000..ca1d222
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/common/constants.h>
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/compile-time-math.h>
+#include <dali/public-api/math/degree.h>
+
+namespace Dali
+{
+
+const Vector3 ParentOrigin::TOP_LEFT     (0.0f, 0.0f, 0.5f);
+const Vector3 ParentOrigin::TOP_CENTER   (0.5f, 0.0f, 0.5f);
+const Vector3 ParentOrigin::TOP_RIGHT    (1.0f, 0.0f, 0.5f);
+const Vector3 ParentOrigin::CENTER_LEFT  (0.0f, 0.5f, 0.5f);
+const Vector3 ParentOrigin::CENTER       (0.5f, 0.5f, 0.5f);
+const Vector3 ParentOrigin::CENTER_RIGHT (1.0f, 0.5f, 0.5f);
+const Vector3 ParentOrigin::BOTTOM_LEFT  (0.0f, 1.0f, 0.5f);
+const Vector3 ParentOrigin::BOTTOM_CENTER(0.5f, 1.0f, 0.5f);
+const Vector3 ParentOrigin::BOTTOM_RIGHT (1.0f, 1.0f, 0.5f);
+
+const Vector3 ParentOrigin::DEFAULT( ParentOrigin::TOP_LEFT );
+
+const Vector3 AnchorPoint::TOP_LEFT     (0.0f, 0.0f, 0.5f);
+const Vector3 AnchorPoint::TOP_CENTER   (0.5f, 0.0f, 0.5f);
+const Vector3 AnchorPoint::TOP_RIGHT    (1.0f, 0.0f, 0.5f);
+const Vector3 AnchorPoint::CENTER_LEFT  (0.0f, 0.5f, 0.5f);
+const Vector3 AnchorPoint::CENTER       (0.5f, 0.5f, 0.5f);
+const Vector3 AnchorPoint::CENTER_RIGHT (1.0f, 0.5f, 0.5f);
+const Vector3 AnchorPoint::BOTTOM_LEFT  (0.0f, 1.0f, 0.5f);
+const Vector3 AnchorPoint::BOTTOM_CENTER(0.5f, 1.0f, 0.5f);
+const Vector3 AnchorPoint::BOTTOM_RIGHT (1.0f, 1.0f, 0.5f);
+
+const Vector3 AnchorPoint::DEFAULT( AnchorPoint::CENTER );
+
+const Vector4 Color::BLACK( 0.0f, 0.0f, 0.0f, 1.0f );
+const Vector4 Color::WHITE( 1.0f, 1.0f, 1.0f, 1.0f );
+
+const Vector4 Color::RED(   1.0f, 0.0f, 0.0f, 1.0f );
+const Vector4 Color::GREEN( 0.0f, 1.0f, 0.0f, 1.0f );
+const Vector4 Color::BLUE(  0.0f, 0.0f, 1.0f, 1.0f );
+
+const Vector4 Color::YELLOW(  1.0f, 1.0f, 0.0f, 1.0f );
+const Vector4 Color::MAGENTA( 1.0f, 0.0f, 1.0f, 1.0f );
+const Vector4 Color::CYAN(    0.0f, 1.0f, 1.0f, 1.0f );
+
+const Vector4 Color::TRANSPARENT( 0.0f, 0.0f, 0.0f, 0.0f );
+
+// epsilon constants
+const float Math::MACHINE_EPSILON_0     = Epsilon<0>::value;
+const float Math::MACHINE_EPSILON_1     = Epsilon<1>::value;
+const float Math::MACHINE_EPSILON_10    = Epsilon<10>::value;
+const float Math::MACHINE_EPSILON_100   = Epsilon<100>::value;
+const float Math::MACHINE_EPSILON_1000  = Epsilon<1000>::value;
+const float Math::MACHINE_EPSILON_10000 = Epsilon<10000>::value;
+
+} // namespace Dali
diff --git a/dali/public-api/common/constants.h b/dali/public-api/common/constants.h
new file mode 100644 (file)
index 0000000..77d788b
--- /dev/null
@@ -0,0 +1,140 @@
+#ifndef __DALI_CONSTANTS_H__
+#define __DALI_CONSTANTS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <math.h> // M_PI
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief ParentOrigin constants
+ *
+ * Note that for 2D layouting, the typical Z position is 0.5f (not 0.0f)
+ * @since_tizen 2.4
+ */
+namespace ParentOrigin
+{
+extern const Vector3 DEFAULT; ///< TOP_LEFT
+static const float TOP = 0.0f;
+static const float BOTTOM = 1.0f;
+static const float LEFT = 0.0f;
+static const float RIGHT = 1.0f;
+static const float MIDDLE = 0.5f;
+
+DALI_IMPORT_API extern const Vector3 TOP_LEFT;           ///< 0.0f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 TOP_CENTER;         ///< 0.5f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 TOP_RIGHT;          ///< 1.0f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER_LEFT;        ///< 0.0f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER;             ///< 0.5f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER_RIGHT;       ///< 1.0f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_LEFT;        ///< 0.0f, 1.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_CENTER;      ///< 0.5f, 1.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_RIGHT;       ///< 1.0f, 1.0f, 0.5f
+
+}
+
+/**
+ * @brief AnchorPoint constants
+ *
+ * Note that for 2D layouting, the typical Z position is 0.5f (not 0.0f)
+ * @since_tizen 2.4
+ */
+namespace AnchorPoint
+{
+static const float TOP = 0.0f;
+static const float BOTTOM = 1.0f;
+static const float LEFT = 0.0f;
+static const float RIGHT = 1.0f;
+static const float MIDDLE = 0.5f;
+
+extern const Vector3 DEFAULT; ///< CENTER
+DALI_IMPORT_API extern const Vector3 TOP_LEFT;           ///< 0.0f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 TOP_CENTER;         ///< 0.5f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 TOP_RIGHT;          ///< 1.0f, 0.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER_LEFT;        ///< 0.0f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER;             ///< 0.5f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 CENTER_RIGHT;       ///< 1.0f, 0.5f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_LEFT;        ///< 0.0f, 1.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_CENTER;      ///< 0.5f, 1.0f, 0.5f
+DALI_IMPORT_API extern const Vector3 BOTTOM_RIGHT;       ///< 1.0f, 1.0f, 0.5f
+
+}
+
+
+/**
+ * @brief Color Constants.
+ *
+ * Color is represented by the Vector4 class (see vector4.h).
+ * @since_tizen 2.4
+ */
+namespace Color
+{
+DALI_IMPORT_API extern const Vector4 BLACK;       ///< Pure black (0.0f, 0.0f, 0.0f, 1.0f);
+DALI_IMPORT_API extern const Vector4 WHITE;       ///< Pure white (1.0f, 1.0f, 1.0f, 1.0f);
+
+DALI_IMPORT_API extern const Vector4 RED;         ///< Pure red   (1.0f, 0.0f, 0.0f, 1.0f);
+DALI_IMPORT_API extern const Vector4 GREEN;       ///< Pure green (0.0f, 1.0f, 0.0f, 1.0f);
+DALI_IMPORT_API extern const Vector4 BLUE;        ///< Pure blue  (0.0f, 0.0f, 1.0f, 1.0f);
+
+DALI_IMPORT_API extern const Vector4 YELLOW;      ///< Pure yellow  (1.0f, 1.0f, 0.0f, 1.0f);
+DALI_IMPORT_API extern const Vector4 MAGENTA;     ///< Pure magenta (1.0f, 0.0f, 1.0f, 1.0f);
+DALI_IMPORT_API extern const Vector4 CYAN;        ///< Pure cyan    (0.0f, 1.0f, 1.0f, 1.0f);
+
+DALI_IMPORT_API extern const Vector4 TRANSPARENT; ///< Black transparent (0.0f, 0.0f, 0.0f, 0.0f);
+
+} // namespace Color
+
+/**
+ * @brief Math constants
+ * @since_tizen 2.4
+ */
+namespace Math
+{
+DALI_IMPORT_API extern const float MACHINE_EPSILON_0;      ///< Epsilon for values near zero
+DALI_IMPORT_API extern const float MACHINE_EPSILON_1;      ///< Epsilon for values near 1
+DALI_IMPORT_API extern const float MACHINE_EPSILON_10;     ///< Epsilon for values near 10
+DALI_IMPORT_API extern const float MACHINE_EPSILON_100;    ///< Epsilon for values near 100
+DALI_IMPORT_API extern const float MACHINE_EPSILON_1000;   ///< Epsilon for values near 1000
+DALI_IMPORT_API extern const float MACHINE_EPSILON_10000;  ///< Epsilon for values near 10000
+
+// float is preferred to double for performance on ARM targets
+static const float PI   = static_cast<float>(M_PI);       ///< Constant representing PI
+static const float PI_2 = static_cast<float>(M_PI_2);     ///< Constant representing PI/2
+static const float PI_4 = static_cast<float>(M_PI_4);     ///< Constant representing PI/4
+static const float PI_OVER_180 = Dali::Math::PI/180.0f;   ///< Constant used to convert degree to radian
+static const float ONE80_OVER_PI = 180.0f/Dali::Math::PI; ///< Constant used to convert radian to degree
+
+} // namespace Math
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONSTANTS_H__
diff --git a/dali/public-api/common/dali-common.cpp b/dali/public-api/common/dali-common.cpp
new file mode 100644 (file)
index 0000000..ab03ff1
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/common/dali-common.h>
+
+// EXTERNAL INCLUDES
+#include <stdlib.h>
+#include <string>
+#include <cstdio>
+
+#ifndef EMSCRIPTEN // cxxabi not supported
+# include <execinfo.h>
+# include <cxxabi.h>
+#endif
+
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+const int MAX_NUM_STACK_FRAMES = 25;
+}
+
+namespace Dali
+{
+
+#if defined(BACKTRACE_ENABLED)
+
+std::string Demangle(const char* symbol)
+{
+  std::string result;
+
+  // backtrace ::=  <filename>'('['_'<mangled-symbol>'_']['+'<offset>]')'
+  // Only want <mangled-symbol>:
+  const char* openParen = strchr(symbol, '(');
+  if(openParen != NULL)
+  {
+    const char* startOfToken = openParen + 1;
+    const char* plus = strchr(startOfToken, '+');
+    const char* closeParen = strchr(startOfToken, ')');
+    const char* endOfToken = NULL;
+    if(plus != NULL)
+    {
+      endOfToken = plus;
+    }
+    else if(closeParen != NULL)
+    {
+      endOfToken = closeParen;
+    }
+    if(endOfToken != NULL)
+    {
+      size_t tokenLength = endOfToken - startOfToken;
+
+      // Allocate space for symbol
+      char *mangledSymbol = (char*)malloc(tokenLength+1u);
+      if(mangledSymbol != NULL)
+      {
+        strncpy(mangledSymbol, startOfToken, tokenLength);
+        mangledSymbol[tokenLength] = '\0';
+
+        size_t size;
+        int    status;
+        char*  demangled=NULL;
+        demangled = abi::__cxa_demangle( mangledSymbol, NULL, &size, &status );
+        if( demangled != NULL )
+        {
+          result = demangled;
+          free(demangled); // demangle() allocates returned string, so free it
+        }
+        else
+        {
+          result = symbol;
+        }
+        free(mangledSymbol);
+      }
+    }
+  }
+
+  return result;
+}
+
+DALI_EXPORT_API DaliException::DaliException( const char* location, const char* condition )
+: location( location ), condition( condition )
+{
+  // Note, if a memory error has occured, then the backtrace won't work - backtrace_symbols relies on
+  // allocating memory.
+
+  // Initial dlog error message is output in DALI_ASSERT_ALWAYS macro
+  // Also output on stderr
+#if defined(DEBUG_ENABLED)
+  fprintf(stderr, "Exception: \n%s\n thrown at %s\nSee dlog for backtrace\n", condition, location);
+#else
+  fprintf(stderr, "Exception: \n%s\n thrown\nSee dlog for backtrace\n", condition );
+#endif
+
+  DALI_LOG_ERROR_NOFN("Backtrace:\n");
+
+  void* frameArray[MAX_NUM_STACK_FRAMES];
+  int nSize = backtrace(frameArray, MAX_NUM_STACK_FRAMES);
+  char** symbols = backtrace_symbols(frameArray, nSize);
+  for(int i=1; i< nSize; i++)
+  {
+    std::string demangled_symbol = Demangle(symbols[i]);
+    DALI_LOG_ERROR_NOFN("[%02d]   %s\n", i, demangled_symbol.c_str() );
+  }
+  free(symbols);
+}
+
+
+#else // BACKTRACE_ENABLED
+
+DALI_EXPORT_API DaliException::DaliException( const char* location, const char* condition )
+: location( location ), condition( condition )
+{
+#if defined(DEBUG_ENABLED)
+  printf("Exception: \n%s\n thrown at %s\n", condition, location );
+#else
+  printf("Exception: \n%s\n thrown\n", condition );
+#endif
+}
+
+
+#endif // BACKTRACE_ENABLED
+
+DALI_EXPORT_API void DaliAssertMessage( const char* location, const char* condition )
+{
+#if defined(DEBUG_ENABLED)
+  DALI_LOG_ERROR_NOFN( "Assert (%s) failed in: %s\n", condition, location );
+#else
+  DALI_LOG_ERROR_NOFN( "Assert (%s) failed\n", condition );
+#endif
+}
+
+} // Dali
diff --git a/dali/public-api/common/dali-common.h b/dali/public-api/common/dali-common.h
new file mode 100644 (file)
index 0000000..f54b4a9
--- /dev/null
@@ -0,0 +1,188 @@
+#ifndef __DALI_COMMON_H__
+#define __DALI_COMMON_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+#ifdef EMSCRIPTEN
+#include <emscripten/emscripten.h>
+#endif
+
+/*
+ * Definitions for shared library support
+ *
+ * If a library is configured with --enable-exportall or --enable-debug
+ * then HIDE_DALI_INTERNALS is not defined, and nothing is hidden.
+ * If it is configured without these options (the default), then HIDE_INTERNALS
+ * is defined when building the library, visibility is automatically hidden, and the explicit
+ * defines below come into use.
+ * When building a library that uses DALI, HIDE_DALI_INTERNALS
+ */
+#if __GNUC__ >= 4
+#  ifndef HIDE_DALI_INTERNALS
+#    define DALI_EXPORT_API
+#    define DALI_IMPORT_API
+#    define DALI_INTERNAL
+#  else
+#    define DALI_EXPORT_API __attribute__ ((visibility ("default")))
+#    define DALI_IMPORT_API __attribute__ ((visibility ("default")))
+#    define DALI_INTERNAL   __attribute__ ((visibility ("hidden")))
+#  endif
+#else
+/** Visibility attribute to show method definitions */
+#  define DALI_EXPORT_API
+/** Visibility attribute to show declarations */
+#  define DALI_IMPORT_API
+/** Visibility attribute to hide declarations */
+#  define DALI_INTERNAL
+#endif
+
+#if defined (__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
+// C++0x support
+#define _CPP11
+#else
+// C++0x not supported
+#endif
+
+#ifdef EMSCRIPTEN
+
+#ifndef __clang__
+# error not clang?
+#endif
+
+// clang cpp11 check is per feature
+#if !__has_feature(cxx_constexpr)
+# error constexpr needed for compile-time-math. Use -std=c+11
+#endif
+
+#define _CPP11
+
+#endif
+
+/**
+ * @brief The DALi namespace
+ * @since_tizen 2.4
+ */
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief Method to log assertion message in DALI_ASSERT_ALWAYS macro below.
+ *
+ * @since_tizen 2.4
+ * @param[in] location Where the assertion occurred
+ * @param[in] condition The assertion condition
+ */
+DALI_IMPORT_API void DaliAssertMessage( const char* location, const char* condition );
+
+/**
+ * @brief Exception class for Dali Core library - Raised by assertions in codebase.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API DaliException
+{
+public:
+  /**
+   * @brief Constructor.
+   *
+   * Will always display a backtrace when raised in a debug build.
+   *
+   * @since_tizen 2.4
+   * @param[in] location  - the location of the assertion
+   * @param[in] condition - The assertion condition
+   */
+  DaliException( const char* location, const char* condition );
+
+  const char* location;
+  const char* condition;
+};
+
+/**
+ * @}
+ */
+}// Dali
+
+/**
+ * @brief An invariant concurrent assertion to ensure its argument always evaluates TRUE.
+ *
+ * Use this for rules that must always be true regardless of build options.
+ * For example, Actor must only ever have one parent.
+ * To be clear, this test remains compiled into release builds that are deployed
+ * on the platform.
+ * Semantically, a failure of this test is signalling that dali is giving up and
+ * quitting.
+ * Since we don't catch the exception, a failure on any thread other than event
+ * will propagate up the call stack and kill that thread.
+ * A failure on the event thread may give the application an opportunity to
+ * recover if there is an application-written exception handler on the call
+ * stack between the throw site and the thread root and the application is built
+ * with a compatible ABI.
+ * Handle this macro with care at the level you would if it expanded to:
+ *    if(!cond) { exit(EXIT_FAILURE); }
+ * (which it is often equivalent to in effect).
+ * It should not be used for simple parameter validation for instance.
+ */
+
+/**
+ * @brief Strip assert location for release builds, assert text is descriptive enough
+ * This is to save space for low spec devices
+ * @since_tizen 2.4
+ */
+#if defined(DEBUG_ENABLED)
+#define ASSERT_LOCATION __PRETTY_FUNCTION__
+#else
+#define ASSERT_LOCATION NULL
+#endif
+
+#ifdef EMSCRIPTEN
+
+#define DALI_ASSERT_ALWAYS(cond)                \
+  if(!(cond)) \
+  { \
+    Dali::DaliAssertMessage( ASSERT_LOCATION, #cond );   \
+    throw Dali::DaliException( ASSERT_LOCATION, #cond );  \
+    EM_ASM(print(new Error().stack)); \
+  }
+#else
+
+#define DALI_ASSERT_ALWAYS(cond)                \
+  if(!(cond)) \
+  { \
+    Dali::DaliAssertMessage( ASSERT_LOCATION, #cond );   \
+    throw Dali::DaliException( ASSERT_LOCATION, #cond );  \
+  }
+#endif
+
+/**
+ * @brief An invariant concurrent assertion to ensure its argument evaluates TRUE in debug builds.
+ *
+ * Use this to sanity check algorithms and prevent internal programming errors
+ * @since_tizen 2.4
+ */
+#if defined(DEBUG_ENABLED)
+#define DALI_ASSERT_DEBUG(cond) DALI_ASSERT_ALWAYS(cond)
+#else
+#define DALI_ASSERT_DEBUG(cond)
+#endif
+
+#endif // __DALI_COMMON_H__
diff --git a/dali/public-api/common/dali-vector.cpp b/dali/public-api/common/dali-vector.cpp
new file mode 100644 (file)
index 0000000..084515e
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/common/dali-vector.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for memcpy & memmove
+
+namespace Dali
+{
+
+VectorBase::VectorBase()
+  : mData( NULL )
+{
+}
+
+VectorBase::~VectorBase()
+{
+}
+
+VectorBase::SizeType VectorBase::Capacity() const
+{
+  SizeType capacity = 0u;
+  if( mData )
+  {
+    SizeType* metadata = reinterpret_cast< SizeType* >( mData );
+    capacity = *(metadata - 2u);
+  }
+  return capacity;
+}
+
+
+void VectorBase::Release()
+{
+  if( mData )
+  {
+    // adjust pointer to real beginning
+    SizeType* metadata = reinterpret_cast< SizeType* >( mData );
+    // TODO would be nice to memset to a bitpattern to catch illegal use of container after release
+    // but that would require knowledge of the itemsize
+    free( metadata - 2u );
+    mData = 0u;
+  }
+}
+
+void VectorBase::SetCount( SizeType count )
+{
+  // someone can call Resize( 0u ) before ever populating the vector
+  if( mData )
+  {
+    SizeType* metadata = reinterpret_cast< SizeType* >( mData );
+    *(metadata - 1u) = count;
+  }
+}
+
+void VectorBase::Reserve( SizeType capacity, SizeType elementSize )
+{
+  SizeType oldCapacity = Capacity();
+  SizeType oldCount = Count();
+  if( capacity > oldCapacity )
+  {
+    const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
+    void* wholeData = (void*)malloc( wholeAllocation );
+    DALI_ASSERT_ALWAYS( wholeData && "VectorBase::Reserve - Memory allocation failed" );
+
+#if defined( DEBUG_ENABLED )
+    // in debug build this will help identify a vector of uninitialized data
+    memset( wholeData, 0xaa, wholeAllocation );
+#endif
+    SizeType* metaData = reinterpret_cast< SizeType* >( wholeData );
+    *metaData++ = capacity;
+    *metaData++ = oldCount;
+    if( mData )
+    {
+      // copy over the old data
+      memcpy( metaData, mData, oldCount * elementSize );
+      // release old buffer
+      Release();
+    }
+    mData = metaData;
+  }
+}
+
+void VectorBase::Copy( const VectorBase& vector, SizeType elementSize )
+{
+  // release old data
+  Release();
+  // reserve space based on source capacity
+  const SizeType capacity = vector.Capacity();
+  Reserve( capacity, elementSize );
+  // copy over whole data
+  const SizeType wholeAllocation = sizeof(SizeType) * 2u + capacity * elementSize;
+  SizeType* srcData = reinterpret_cast< SizeType* >( vector.mData );
+  SizeType* dstData = reinterpret_cast< SizeType* >( mData );
+  memcpy( dstData - 2u, srcData - 2u, wholeAllocation );
+}
+
+void VectorBase::Swap( VectorBase& vector )
+{
+  // just swap the data pointers, metadata will swap as side effect
+  std::swap( mData, vector.mData );
+}
+
+void VectorBase::Erase( char* address, SizeType elementSize )
+{
+  // erase can be called on an unallocated vector
+  if( mData )
+  {
+    char* startAddress = address + elementSize;
+    const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
+    SizeType numberOfBytes = endAddress - startAddress;
+    // addresses overlap so use memmove
+    memmove( address, startAddress, numberOfBytes );
+    SetCount( Count() - 1u );
+  }
+}
+
+char* VectorBase::Erase( char* first, char* last, SizeType elementSize )
+{
+  char* next = NULL;
+
+  if( mData )
+  {
+    char* startAddress = last;
+    const char* endAddress = reinterpret_cast< char* >( mData ) + Count() * elementSize;
+    SizeType numberOfBytes = endAddress - startAddress;
+    // addresses overlap so use memmove
+    memmove( first, startAddress, numberOfBytes );
+    SetCount( Count() - ( last - first ) / elementSize );
+
+    next = first;
+  }
+
+  return next;
+}
+
+void VectorBase::CopyMemory( char* destination, const char* source, size_t numberOfBytes )
+{
+  if( ( ( source < destination ) && ( source + numberOfBytes > destination ) ) ||
+      ( ( destination < source ) && ( destination + numberOfBytes > source ) ) )
+  {
+    // If there is overlap, use memmove.
+    memmove( destination, source, numberOfBytes );
+  }
+  else
+  {
+    // It's safe to use memcpy if there isn't overlap.
+    memcpy( destination, source, numberOfBytes );
+  }
+}
+
+} // namespace Dali
+
diff --git a/dali/public-api/common/dali-vector.h b/dali/public-api/common/dali-vector.h
new file mode 100644 (file)
index 0000000..cbdb4a3
--- /dev/null
@@ -0,0 +1,759 @@
+#ifndef __DALI_VECTOR_H__
+#define __DALI_VECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+#include <algorithm>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+#include <dali/public-api/math/math-utils.h>
+
+/**
+ * @brief For DALi internal use asserts are enabled in debug builds.
+ *
+ * For Application use asserts can be enabled manually.
+ * @since_tizen 2.4
+ */
+#if defined( DEBUG_ENABLED )
+#define ENABLE_VECTOR_ASSERTS
+#endif
+
+#if defined( ENABLE_VECTOR_ASSERTS )
+#define DALI_ASSERT_VECTOR(cond) DALI_ASSERT_ALWAYS(cond)
+#else
+#define DALI_ASSERT_VECTOR(cond)
+#endif
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief Base class to handle the memory of simple vector.
+ *
+ * Memory layout is such that it has two std::size_t to hold the count
+ * and capacity of the vector. mData is adjusted so that it points to the
+ * beginning of the first real item so that iterating the items is quick.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API VectorBase
+{
+public: // Typedefs
+
+  typedef std::size_t SizeType;
+
+protected: // Construction
+
+  /**
+   * @brief Default constructor. Does not allocate space.
+   * @since_tizen 2.4
+   */
+  VectorBase();
+
+  /**
+   * @brief Destructor.
+   *
+   * Does not release the space. Derived class needs to call Release.
+   * Not virtual as should not be called directly and we do not want
+   * a vtable for this class as it would unnecessarily increase size.
+   * @since_tizen 2.4
+   */
+  ~VectorBase();
+
+public: // API
+
+  /**
+   * @brief This method is inlined as its needed frequently for End() iterator.
+   *
+   * @since_tizen 2.4
+   * @return The count of elements in this vector.
+   */
+  SizeType Count() const
+  {
+    SizeType items = 0u;
+    if( mData )
+    {
+      SizeType* metadata = reinterpret_cast< SizeType* >( mData );
+      items = *(metadata - 1u);
+    }
+    return items;
+  }
+
+  /**
+   * @brief Gets the count of elements in this vector.
+   * @since_tizen 2.4
+   * @return The count of elements in this vector.
+   */
+  SizeType Size() const
+  {
+    return Count();
+  }
+
+  /**
+   * @brief Gets the capacity of this vector.
+   * @since_tizen 2.4
+   * @return The capacity of this vector.
+   */
+  SizeType Capacity() const;
+
+  /**
+   * @brief Release the data.
+   *
+   * Does not call destructors on objects held.
+   * @since_tizen 2.4
+   */
+  void Release();
+
+protected: // for Derived classes
+
+  /**
+   * @brief Helper to set the count.
+   *
+   * @since_tizen 2.4
+   * @param count Number of elements in the vector.
+   */
+  void SetCount( SizeType count );
+
+  /**
+   * @brief Reserve space in the vector.
+   *
+   * @since_tizen 2.4
+   * @param count of elements to reserve.
+   * @param elementSize of a single element.
+   */
+  void Reserve( SizeType count, SizeType elementSize );
+
+  /**
+   * @brief Copy a vector.
+   *
+   * @since_tizen 2.4
+   * @param vector Vector to copy from.
+   * @param elementSize of a single element.
+   */
+  void Copy( const VectorBase& vector, SizeType elementSize );
+
+  /**
+   * @brief Swap the contents of two vectors.
+   *
+   * @since_tizen 2.4
+   * @param vector Vector to swap with.
+   */
+  void Swap( VectorBase& vector );
+
+  /**
+   * @brief Erase an element.
+   *
+   * Does not change capacity.
+   * @since_tizen 2.4
+   * @param address to erase from.
+   * @param elementSize to erase.
+   * @pre last element cannot be erased as there is nothing to move.
+   */
+  void Erase( char* address, SizeType elementSize );
+
+  /**
+   * @brief Erase a range of elements.
+   *
+   * Does not change capacity.
+   * @since_tizen 2.4
+   * @param[in] first Address to the first element to be erased.
+   * @param[in] last Address to the last element to be erased.
+   * @param[in] elementSize Size of one of the elements to be erased.
+   * @return address pointing to the next element of the last one.
+   */
+  char* Erase( char* first, char* last, SizeType elementSize );
+
+  /**
+   * @brief Copies a number of bytes from \e source to \e destination.
+   *
+   * \e source and \e destination must not overlap.
+   *
+   * @since_tizen 2.4
+   * @param[in] destination Pointer to the destination address.
+   * @param[in] source Pointer to the source address.
+   * @param[in] numberOfBytes The number of bytes to be copied.
+   */
+  void CopyMemory( char* destination, const char* source, size_t numberOfBytes );
+
+private:
+
+  // not copiable as it does not know the size of elements
+  VectorBase( const VectorBase& ); ///< Undefined
+  VectorBase& operator=( const VectorBase& ); ///< Undefined
+
+protected: // Data
+
+  void* mData; ///< Pointer to the data.
+
+};
+
+/**
+ * @brief Vector algorithm variant for trivial types.
+ *
+ * Trivial types do not need destructor or copy constructor called.
+ * @since_tizen 2.4
+ */
+template< bool IsTrivial >
+class VectorAlgorithms : public VectorBase
+{
+protected: // API for deriving classes
+
+  typedef VectorBase::SizeType SizeType;
+
+  /**
+   * @brief Empty constructor.
+   * @since_tizen 2.4
+   */
+  VectorAlgorithms()
+  { }
+
+  /**
+   * @brief Empty destructor.
+   * @since_tizen 2.4
+   */
+  ~VectorAlgorithms()
+  { }
+
+  /**
+   * @brief Copy vector contents.
+   *
+   * @since_tizen 2.4
+   * @param rhs to copy from.
+   * @param elementSize of the content.
+   */
+  void Copy( const VectorBase& rhs, SizeType elementSize )
+  {
+    if( rhs.Capacity() > 0u )
+    {
+      VectorBase::Copy( rhs, elementSize );
+    }
+    else
+    {
+      VectorBase::Release();
+    }
+  }
+
+  /**
+   * @brief Reserve space in the vector.
+   *
+   * @since_tizen 2.4
+   * @param count of elements to reserve.
+   * @param elementSize of a single element.
+   */
+  void Reserve( SizeType count, SizeType elementSize )
+  {
+    VectorBase::Reserve( count, elementSize );
+  }
+
+  /**
+   * @brief Resize the vector. Does not change capacity.
+   *
+   * @since_tizen 2.4
+   * @param count to resize to.
+   * @param elementSize of a single element.
+   */
+  void Resize( SizeType count, SizeType elementSize )
+  {
+    // reserve will copy old elements as well
+    Reserve( count, elementSize );
+  }
+
+  /**
+   * @brief Clear the contents.
+   *
+   * For simple types nothing to do.
+   * @since_tizen 2.4
+   */
+  void Clear()
+  {
+    if( mData )
+    {
+      VectorBase::SetCount( 0u );
+    }
+  }
+
+  /**
+   * @brief Release the vector.
+   * @since_tizen 2.4
+   */
+  void Release()
+  {
+    VectorBase::Release();
+  }
+
+  /**
+   * @brief Erase an element. Does not change capacity.
+   *
+   * @since_tizen 2.4
+   * @param address to erase from.
+   * @param elementSize to erase.
+   */
+  void Erase( char* address, SizeType elementSize )
+  {
+    VectorBase::Erase( address, elementSize );
+  }
+
+  /**
+   * @brief Erase a range of elements. Does not change capacity.
+   *
+   * @since_tizen 2.4
+   * @param[in] first Address to the first element to be erased.
+   * @param[in] last Address to the last element to be erased.
+   * @param[in] elementSize Size of one of the elements to be erased.
+   * @return address pointing to the next element of the last one.
+   */
+  char* Erase( char* first, char* last, SizeType elementSize )
+  {
+    return VectorBase::Erase( first, last, elementSize );
+  }
+
+  /**
+   * @brief Inserts the given elements into the vector.
+   *
+   * @since_tizen 2.4
+   * @param[in] at Address where to insert the elements into the vector.
+   * @param[in] from Address to the first element to be inserted.
+   * @param[in] to Address to the last element to be inserted.
+   * @param[in] elementSize Size of one of the elements to be inserted.
+   */
+  void Insert( char* at, char* from, char* to, SizeType elementSize )
+  {
+    const SizeType size = to - from;
+    const SizeType count = Count();
+    const SizeType newCount = count + size / elementSize;
+
+    if( newCount > Capacity() )
+    {
+      // Calculate the at offset as the pointer is invalid after the Reserve() call.
+      std::size_t offset = at - reinterpret_cast<char*>( mData );
+
+      // need more space
+      Reserve( NextPowerOfTwo( newCount ), elementSize ); // reserve enough space to store at least the next power of two elements of the new required size.
+
+      // Set the new at pointer.
+      at = reinterpret_cast<char*>( mData ) + offset;
+    }
+    // set new count first as otherwise the debug assert will hit us
+    SetCount( newCount );
+
+    // Move current items to a new position inside the vector.
+    CopyMemory( at + size,
+                at,
+                ( reinterpret_cast<char*>( mData ) + count * elementSize ) - at );
+
+    // Copy the given items.
+    CopyMemory( at, from, size );
+  }
+};
+
+/**
+ * @brief Vector algorithm variant for complex types.
+ *
+ * Not yet supported so will lead to compile error
+ * as constructor and destructor are private.
+ * TODO add support for this variant.
+ * @since_tizen 2.4
+ */
+template<>
+class VectorAlgorithms< false > : public VectorBase
+{
+private:
+  VectorAlgorithms()
+  { }
+  ~VectorAlgorithms()
+  { }
+};
+
+/**
+ * @brief Vector class with minimum space allocation when its empty.
+ *
+ * @since_tizen 2.4
+ * @param type of the data that the vector holds.
+ */
+template< class T, bool IsTrivialType = TypeTraits<T>::IS_TRIVIAL_TYPE == true >
+class Vector : public VectorAlgorithms< IsTrivialType >
+{
+public: // API
+
+  /**
+   * @brief Type definitions.
+   * @since_tizen 2.4
+   */
+  typedef VectorBase::SizeType SizeType;
+  typedef T* Iterator;  ///< Most simple Iterator is a pointer
+  typedef const T* ConstIterator;
+  typedef T  ItemType;
+
+  enum
+  {
+    BaseType = IsTrivialType
+  };
+
+  /**
+   * @brief Default constructor. Does not allocate any space.
+   * @since_tizen 2.4
+   */
+  Vector()
+  { }
+
+  /**
+   * @brief Destructor. Releases the allocated space.
+   * @since_tizen 2.4
+   */
+  ~Vector()
+  {
+    Release();
+  }
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @since_tizen 2.4
+   * @param vector Vector to copy from.
+   */
+  Vector( const Vector& vector )
+  {
+    // reuse assignment
+    operator=( vector );
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param  vector Vector to assign from.
+   * @return reference to self for chaining.
+   */
+  Vector& operator=( const Vector& vector )
+  {
+    if( this != &vector )
+    {
+      VectorAlgorithms<BaseType>::Copy( vector, sizeof( ItemType ) );
+    }
+    return *this;
+  }
+
+  /**
+   * @brief Iterator to the beginning of the data.
+   * @since_tizen 2.4
+   * @return Iterator to the beginning of the data.
+   */
+  Iterator Begin() const
+  {
+    ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
+    return address;
+  }
+
+  /**
+   * @brief Iterator to the end of the data (one past last element).
+   * @since_tizen 2.4
+   * @return Iterator to the end of the data (one past last element).
+   */
+  Iterator End() const
+  {
+    ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
+    address += VectorBase::Count();
+    return address;
+  }
+
+  /**
+   * @brief Subscript operator.
+   * @since_tizen 2.4
+   * @param  index of the element.
+   * @return reference to the element for given index.
+   * @pre index must be in the vector's range.
+   */
+  ItemType& operator[]( SizeType index )
+  {
+    // reuse the const version
+    return const_cast< ItemType& >( const_cast< const Vector< ItemType >& >( *this )[ index ] );
+  }
+
+  /**
+   * @brief Subscript operator.
+   * @since_tizen 2.4
+   * @param  index of the element.
+   * @return reference to the element for given index.
+   * @pre index must be in the vector's range.
+   */
+  const ItemType& operator[]( SizeType index ) const
+  {
+    DALI_ASSERT_VECTOR( VectorBase::mData && "Vector is empty" );
+    DALI_ASSERT_VECTOR( index < VectorBase::Count() && "Index out of bounds" );
+    ItemType* address = reinterpret_cast<ItemType*>( VectorBase::mData );
+    address += index;
+    return *address;
+  }
+
+  /**
+   * @brief Push back an element to the vector.
+   *
+   * The underlying storage may be reallocated to provide space.
+   * If this occurs, all pre-existing pointers into the vector will
+   * become invalid.
+   *
+   * @since_tizen 2.4
+   * @param[in] element to be added.
+   */
+  void PushBack( const ItemType& element )
+  {
+    const SizeType count = VectorBase::Count();
+    const SizeType newCount = count + 1u;
+    const SizeType capacity = VectorBase::Capacity();
+    if( newCount > capacity )
+    {
+      // need more space
+      Reserve( newCount << 1u ); // reserve double the current count
+    }
+    // set new count first as otherwise the debug assert will hit us
+    VectorBase::SetCount( newCount );
+    operator[]( count ) = element;
+  }
+
+  /**
+   *@brief Insert an element to the vector.
+   *
+   * Elements after \e at are moved one position to the right.
+   *
+   * The underlying storage may be reallocated to provide space.
+   * If this occurs, all pre-existing pointers into the vector will
+   * become invalid.
+   *
+   * @pre Iterator at must be in the vector's range ( Vector::Begin(), Vector::End() ).
+   *
+   * @param[in] at Iterator where to insert the elements into the vector.
+   * @param[in] element to be added.
+   *@since_tizen 2.4
+   */
+  void Insert( Iterator at, const ItemType& element )
+  {
+    DALI_ASSERT_VECTOR( ( at <= End() ) && ( at >= Begin() ) && "Iterator not inside vector" );
+    const SizeType size = sizeof( ItemType );
+    char* address = const_cast<char*>( reinterpret_cast<const char*>( &element ) );
+    VectorAlgorithms<BaseType>::Insert( reinterpret_cast< char* >( at ),
+                                        address,
+                                        address + size,
+                                        size );
+  }
+
+  /**
+   * @brief Inserts the given elements into the vector.
+   *
+   * Elements after \e at are moved the number of given elements positions to the right.
+   *
+   * The underlying storage may be reallocated to provide space.
+   * If this occurs, all pre-existing pointers into the vector will
+   * become invalid.
+   *
+   * @since_tizen 2.4
+   * @param[in] at Iterator where to insert the elements into the vector.
+   * @param[in] from Iterator to the first element to be inserted.
+   * @param[in] to Iterator to the last element to be inserted.
+   * @pre Iterator \e at must be in the vector's range ( Vector::Begin(), Vector::End() ).
+   * @pre Iterators \e from and \e to must be valid iterators.
+   * @pre Iterator \e from must not be grater than Iterator \e to.
+   *
+   */
+  void Insert( Iterator at, Iterator from, Iterator to )
+  {
+    DALI_ASSERT_VECTOR( ( at <= End() ) && ( at >= Begin() ) && "Iterator not inside vector" );
+    DALI_ASSERT_VECTOR( ( from <= to ) && "from address can't be greater than to" );
+
+    if( from == to )
+    {
+      // nothing to copy.
+      return;
+    }
+
+    VectorAlgorithms<BaseType>::Insert( reinterpret_cast< char* >( at ),
+                                        reinterpret_cast< char* >( from ),
+                                        reinterpret_cast< char* >( to ),
+                                        sizeof( ItemType ) );
+  }
+
+  /**
+   * @brief Reserve space in the vector.
+   *
+   * Reserving less than current Capacity is a no-op.
+   * @since_tizen 2.4
+   * @param count of elements to reserve.
+   */
+  void Reserve( SizeType count )
+  {
+    VectorAlgorithms<BaseType>::Reserve( count, sizeof( ItemType ) );
+  }
+
+  /**
+   * @brief Resize the vector. Does not change capacity.
+   *
+   * @since_tizen 2.4
+   * @param count to resize to.
+   * @param item to insert to the new indices.
+   */
+  void Resize( SizeType count, ItemType item = ItemType() )
+  {
+    const SizeType oldCount = VectorBase::Count();
+    if( count <= oldCount )
+    {
+      // getting smaller so just set count
+      VectorBase::SetCount( count );
+    }
+    else
+    {
+      // remember how many new items get added
+      SizeType newItems = count - oldCount;
+      Reserve( count );
+      for( ; newItems > 0u; --newItems )
+      {
+        PushBack( item );
+      }
+    }
+  }
+
+  /**
+   * @brief Erase an element.
+   *
+   * Does not change capacity. Other elements get moved.
+   *
+   * @since_tizen 2.4
+   * @param iterator Iterator pointing to item to remove.
+   * @return Iterator pointing to next element.
+   * @pre Iterator \e iterator must be within the vector's range ( Vector::Begin(), Vector::End() - 1 ).
+   *
+   */
+  Iterator Erase( Iterator iterator )
+  {
+    DALI_ASSERT_VECTOR( (iterator < End()) && (iterator >= Begin()) && "Iterator not inside vector" );
+    if( iterator < ( End() - 1u ) )
+    {
+      VectorAlgorithms<BaseType>::Erase( reinterpret_cast< char* >( iterator ), sizeof( ItemType ) );
+    }
+    else
+    {
+      // just remove the element
+      Remove( iterator );
+    }
+    return iterator;
+  }
+
+  /**
+   * @brief Erase a range of elements.
+   *
+   * Does not change capacity. Other elements get moved.
+   *
+   * @since_tizen 2.4
+   * @param[in] first Iterator to the first element to be erased.
+   * @param[in] last Iterator to the last element to be erased.
+   *
+   * @return Iterator pointing to the next element of the last one.
+   * @pre Iterator \e first must be in the vector's range ( Vector::Begin(), Vector::End() ).
+   * @pre Iterator \e last must be in the vector's range ( Vector::Begin(), Vector::End() ).
+   * @pre Iterator \e first must not be grater than Iterator \e last.
+   *
+   */
+  Iterator Erase( Iterator first, Iterator last )
+  {
+    DALI_ASSERT_VECTOR( ( first <= End() ) && ( first >= Begin() ) && "Iterator not inside vector" );
+    DALI_ASSERT_VECTOR( ( last <= End() ) && ( last >= Begin() ) && "Iterator not inside vector" );
+    DALI_ASSERT_VECTOR( ( first <= last ) && "first iterator greater than last" );
+
+    Iterator nextElement;
+
+    if( last == End() )
+    {
+      // Erase up to the end.
+      VectorBase::SetCount( VectorBase::Count() - ( last - first ) );
+      nextElement = End();
+    }
+    else
+    {
+      nextElement = reinterpret_cast<Iterator>( VectorAlgorithms<BaseType>::Erase( reinterpret_cast< char* >( first ),
+                                                                                   reinterpret_cast< char* >( last ),
+                                                                                   sizeof( ItemType ) ) );
+    }
+
+    return nextElement;
+  }
+
+  /**
+   * @brief Removes an element.
+   *
+   * Does not maintain order.  Swaps the element with end and
+   * decreases size by one.  This is much faster than Erase so use
+   * this in case order does not matter. Does not change capacity.
+   *
+   * @since_tizen 2.4
+   * @param iterator Iterator pointing to item to remove.
+   * @pre Iterator \e iterator must be in the vector's range ( Vector::Begin(), Vector::End() - 1 ).
+   *
+   */
+  void Remove( Iterator iterator )
+  {
+    DALI_ASSERT_VECTOR( (iterator < End()) && (iterator >= Begin()) && "Iterator not inside vector" );
+
+    Iterator last = End() - 1u;
+    if( last > iterator )
+    {
+      std::swap( *iterator, *last );
+    }
+    VectorBase::SetCount( VectorBase::Count() - 1u );
+  }
+
+  /**
+   * @brief Swap the contents of two vectors.
+   *
+   * @since_tizen 2.4
+   * @param vector Vector to swap with.
+   */
+  void Swap( Vector& vector )
+  {
+    VectorBase::Swap( vector );
+  }
+
+  /**
+   * @brief Clear the contents of the vector. Keeps its capacity.
+   * @since_tizen 2.4
+   */
+  void Clear()
+  {
+    VectorAlgorithms<BaseType>::Clear();
+  }
+
+  /**
+   * @brief Release the memory that the vector holds.
+   * @since_tizen 2.4
+   */
+  void Release()
+  {
+    VectorAlgorithms<BaseType>::Release();
+  }
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif /* __DALI_VECTOR_H__ */
diff --git a/dali/public-api/common/intrusive-ptr.h b/dali/public-api/common/intrusive-ptr.h
new file mode 100644 (file)
index 0000000..7584197
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef __DALI_INTRUSIVE_PTR_H__
+#define __DALI_INTRUSIVE_PTR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief Templated intrusive pointer class
+ *
+ * Uses the Dali:Refobject type supply actual reference counting
+ * The object is responsible for destroying itself
+ * @since_tizen 2.4
+ */
+template<typename T>
+class IntrusivePtr
+{
+
+public:
+
+  /**
+   * @brief Standard constructor to unassigned object.
+   * @since_tizen 2.4
+   */
+  IntrusivePtr() : mPtr( 0 ) {}
+
+  /**
+   * @brief Constructor to attach existing object.
+   *
+   * @since_tizen 2.4
+   * @param p pointer to object,
+   */
+  IntrusivePtr( T* p ) : mPtr( p )
+  {
+    if( mPtr )
+    {
+      mPtr->Reference();
+    }
+  }
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @since_tizen 2.4
+   * @param rhs const reference to an IntrusivePtr
+   * @tparam U reference counter object type
+   */
+  template<typename U>
+  IntrusivePtr( IntrusivePtr<U> const& rhs ) : mPtr( rhs.Get() )
+  {
+    if( mPtr )
+    {
+      mPtr->Reference();
+    }
+  }
+
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 2.4
+   */
+  IntrusivePtr( IntrusivePtr const& rhs ) : mPtr( rhs.mPtr )
+  {
+    if( mPtr )
+    {
+      mPtr->Reference();
+    }
+  }
+
+  /**
+   * @brief Destructor.
+   *
+   * Object will self-destruct if reference count is zero
+   * @since_tizen 2.4
+   */
+  ~IntrusivePtr()
+  {
+    if( mPtr )
+    {
+      mPtr->Unreference();
+    }
+  }
+
+  /**
+   * @brief Get pointer to reference counted object.
+   *
+   * @since_tizen 2.4
+   * @return pointer to reference counted object
+   */
+  T* Get() const
+  {
+    return mPtr;
+  }
+
+  /**
+   * @brief Pointer operator override.
+   *
+   * @since_tizen 2.4
+   * @return pointer to reference counted object
+   */
+  T* operator->() const
+  {
+    return mPtr;
+  }
+
+  /**
+   * @brief Dereference operator override.
+   *
+   * @since_tizen 2.4
+   * @return reference to reference counted object
+   */
+  T& operator*() const
+  {
+    return *mPtr;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param rhs const reference to intrusive pointer
+   * @return reference to reference counted object
+   */
+  IntrusivePtr& operator=( IntrusivePtr const& rhs )
+  {
+    IntrusivePtr( rhs ).Swap( *this );
+    return *this;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param rhs pointer to object to wrap
+   * @return A reference to this object
+   */
+  IntrusivePtr& operator=( T* rhs )
+  {
+    IntrusivePtr( rhs ).Swap( *this );
+    return *this;
+  }
+
+  /**
+   * @brief Reset intrusive pointer.
+   * @since_tizen 2.4
+   */
+  void Reset()
+  {
+    IntrusivePtr().Swap( *this );
+  }
+
+  /**
+   * @brief Reset intrusive pointer with reference counted object.
+   *
+   * @since_tizen 2.4
+   * @param rhs pointer to object
+   */
+  void Reset( T* rhs )
+  {
+    IntrusivePtr( rhs ).Swap( *this );
+  }
+
+  // IntrusivePtr comparisons - This is a variation of the safe bool idiom
+
+  /**
+   * @brief Pointer-to-member type.
+   *
+   * Objects can be implicitly converted to this for validity checks.
+   */
+  typedef void (IntrusivePtr::*BooleanType)() const;
+
+  /**
+   * @brief Converts an object handle to a BooleanType.
+   *
+   * This is useful for checking whether the handle is NULL.
+   * @since_tizen 2.4
+   */
+  operator BooleanType() const
+  {
+    return mPtr ? &IntrusivePtr::ThisIsSaferThanReturningVoidStar : 0;
+  }
+
+  /**
+   * @brief Detach pointer from intrusive ptr counting.
+   *
+   * Use with care.
+   * @since_tizen 2.4
+   */
+  T* Detach()
+  {
+    T* ptr = mPtr;
+    mPtr = 0;
+    return ptr;
+  }
+
+private:
+
+  /**
+   * @brief Used by the safe bool idiom.
+   * @since_tizen 2.4
+   */
+  void ThisIsSaferThanReturningVoidStar() const {}
+
+  /**
+   * @brief Internal swap function
+   * @since_tizen 2.4
+   */
+  void Swap( IntrusivePtr& rhs )
+  {
+    T* tmp = mPtr;
+    mPtr = rhs.mPtr;
+    rhs.mPtr = tmp;
+  }
+
+  T* mPtr;  ///< pointer to RefObject
+};
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers.
+ *
+ * @since_tizen 2.4
+ * @param lhs intrusive pointer to compare with
+ * @param rhs intrusive pointer to compare against
+ * @return true if the pointers point at the same object
+ */
+template<typename T, typename U>
+inline bool operator==( IntrusivePtr<T>const& lhs, IntrusivePtr<U>const& rhs )
+{
+  return lhs.Get() == rhs.Get();
+}
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers.
+ *
+ * @since_tizen 2.4
+ * @param lhs intrusive pointer to compare with
+ * @param rhs intrusive pointer to compare against
+ * @return true if the pointers point at different objects
+ */
+template<typename T, typename U>
+inline bool operator!=( IntrusivePtr<T>const& lhs, IntrusivePtr<U>const &rhs)
+{
+  return lhs.Get() != rhs.Get();
+}
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers
+ *
+ * @since_tizen 2.4
+ * @param lhs intrusive pointer to compare with
+ * @param rhs object to compare against
+ * @return true if the intrusive pointer points at the specified object
+ */
+template<typename T, typename U>
+inline bool operator==( IntrusivePtr<T>const& lhs, U* rhs )
+{
+  return lhs.Get() == rhs;
+}
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers.
+ *
+ * @since_tizen 2.4
+ * @param lhs intrusive pointer to compare with
+ * @param rhs intrusive pointer to compare against
+ * @return true if the intrusive pointer doesn't point at the specified object
+ */
+template<typename T, typename U>
+inline bool operator!=( IntrusivePtr<T>const& lhs, U* rhs )
+{
+  return lhs.Get() != rhs;
+}
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers
+ *
+ * @since_tizen 2.4
+ * @param lhs object to compare with
+ * @param rhs intrusive pointer to compare against
+ * @return true if the intrusive pointer points at the specified object
+ */
+template<typename T, typename U>
+inline bool operator==( T* lhs, IntrusivePtr<U>const& rhs )
+{
+  return lhs == rhs.Get();
+}
+
+/**
+ * @brief Comparison overrides of objects wrapped by intrusive pointers
+ *
+ * @since_tizen 2.4
+ * @param lhs object to compare with
+ * @param rhs intrusive pointer to compare against
+ * @return true if the intrusive pointer doesn't point at the specified object
+ */
+template<typename T, typename U>
+inline bool operator!=( T* lhs, IntrusivePtr<U>const& rhs )
+{
+  return lhs != rhs.Get();
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif /* __DALI_INTRUSIVE_PTR_H__ */
diff --git a/dali/public-api/common/loading-state.h b/dali/public-api/common/loading-state.h
new file mode 100644 (file)
index 0000000..4500653
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __DALI_LOADING_STATE_H__
+#define __DALI_LOADING_STATE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief The status during resource loading operations.
+ * @since_tizen 2.4
+ */
+enum LoadingState
+{
+  ResourceLoading,          ///< The resource is loading
+  ResourceLoadingSucceeded, ///< The resource loaded successfully
+  ResourceLoadingFailed     ///< The resource failed to load
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_LOADING_STATE_H__
diff --git a/dali/public-api/common/stage.cpp b/dali/public-api/common/stage.cpp
new file mode 100644 (file)
index 0000000..9a1e43f
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/common/stage.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/common/core-impl.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/object/object-registry.h>
+
+namespace Dali
+{
+
+using Internal::Core;
+
+const Vector4 Stage::DEFAULT_BACKGROUND_COLOR(0.0f, 0.0f, 0.0f, 1.0f);
+const Vector4 Stage::DEBUG_BACKGROUND_COLOR(0.2f, 0.5f, 0.2f, 1.0f);
+
+Stage::Stage()
+{
+}
+
+Stage::~Stage()
+{
+}
+
+Stage::Stage(const Stage& handle)
+: BaseHandle(handle)
+{
+}
+
+Stage& Stage::operator=(const Stage& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+Stage::Stage(Internal::Stage* internal)
+: BaseHandle(internal)
+{
+}
+
+Stage Stage::GetCurrent()
+{
+  Internal::Stage* stage = Internal::Stage::GetCurrent();
+  DALI_ASSERT_ALWAYS( stage && "Stage doesn't exist" );
+  return Stage( stage );
+}
+
+bool Stage::IsInstalled()
+{
+  return Internal::Stage::IsInstalled();
+}
+
+void Stage::Add(Actor& actor)
+{
+  GetImplementation(*this).Add(GetImplementation(actor));
+}
+
+void Stage::Remove(Actor& actor)
+{
+  GetImplementation(*this).Remove(GetImplementation(actor));
+}
+
+RenderTaskList Stage::GetRenderTaskList() const
+{
+  return RenderTaskList( &GetImplementation(*this).GetRenderTaskList() );
+}
+
+Vector2 Stage::GetSize() const
+{
+  return GetImplementation(*this).GetSize();
+}
+
+unsigned int Stage::GetLayerCount() const
+{
+  return GetImplementation(*this).GetLayerCount();
+}
+
+Layer Stage::GetLayer(unsigned int depth) const
+{
+  return GetImplementation(*this).GetLayer(depth);
+}
+
+Layer Stage::GetRootLayer() const
+{
+  return GetImplementation(*this).GetRootLayer();
+}
+
+void Stage::SetBackgroundColor(Vector4 color)
+{
+  GetImplementation(*this).SetBackgroundColor(color);
+}
+
+Vector4 Stage::GetBackgroundColor() const
+{
+  return GetImplementation(*this).GetBackgroundColor();
+}
+
+Vector2 Stage::GetDpi() const
+{
+  return GetImplementation(*this).GetDpi();
+}
+
+ObjectRegistry Stage::GetObjectRegistry() const
+{
+  Internal::Stage* stage = Internal::Stage::GetCurrent();
+  DALI_ASSERT_ALWAYS( stage && "GetObjectRegistry() : Stage is null" );
+
+  Internal::ObjectRegistry& internal = stage->GetObjectRegistry();
+  return ObjectRegistry(&internal);
+}
+
+void Stage::KeepRendering( float durationSeconds )
+{
+  GetImplementation(*this).KeepRendering( durationSeconds );
+}
+
+Stage::KeyEventSignalType& Stage::KeyEventSignal()
+{
+  return GetImplementation(*this).KeyEventSignal();
+}
+
+Stage::EventProcessingFinishedSignalType& Stage::EventProcessingFinishedSignal()
+{
+  return GetImplementation(*this).EventProcessingFinishedSignal();
+}
+
+Stage::TouchedSignalType& Stage::TouchedSignal()
+{
+  return GetImplementation(*this).TouchedSignal();
+}
+
+Stage::WheelEventSignalType& Stage::WheelEventSignal()
+{
+  return GetImplementation(*this).WheelEventSignal();
+}
+
+Stage::ContextStatusSignal& Stage::ContextLostSignal()
+{
+  return GetImplementation(*this).ContextLostSignal();
+}
+
+Stage::ContextStatusSignal& Stage::ContextRegainedSignal()
+{
+  return GetImplementation(*this).ContextRegainedSignal();
+}
+
+Stage::SceneCreatedSignalType& Stage::SceneCreatedSignal()
+{
+  return GetImplementation(*this).SceneCreatedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/common/stage.h b/dali/public-api/common/stage.h
new file mode 100644 (file)
index 0000000..7e1c6ac
--- /dev/null
@@ -0,0 +1,350 @@
+#ifndef __DALI_STAGE_H__
+#define __DALI_STAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class Stage;
+}
+
+class Actor;
+class Layer;
+class ObjectRegistry;
+class RenderTaskList;
+struct Vector2;
+struct Vector3;
+struct Vector4;
+struct KeyEvent;
+struct TouchEvent;
+struct WheelEvent;
+
+/**
+ * @brief The Stage is a top-level object used for displaying a tree of Actors.
+ *
+ * Multiple stage/window support is not currently provided.
+ *
+ * Signals
+ * | %Signal Name              | Method                               |
+ * |---------------------------|--------------------------------------|
+ * | key-event                 | @ref KeyEventSignal()                |
+ * | event-processing-finished | @ref EventProcessingFinishedSignal() |
+ * | touched                   | @ref TouchedSignal()                 |
+ * | wheel-event               | @ref WheelEventSignal()              |
+ * | context-lost              | @ref ContextLostSignal()             |
+ * | context-regained          | @ref ContextRegainedSignal()         |
+ * | scene-created             | @ref SceneCreatedSignal()            |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Stage : public BaseHandle
+{
+public:
+
+  typedef Signal< void (const KeyEvent&)> KeyEventSignalType;     ///< Key event signal type
+  typedef Signal< void () > EventProcessingFinishedSignalType;    ///< Event Processing finished signal type
+  typedef Signal< void (const TouchEvent&)> TouchedSignalType;    ///< Touched signal type
+  typedef Signal< void (const WheelEvent&)> WheelEventSignalType; ///< Touched signal type
+  typedef Signal< void () > ContextStatusSignal;                  ///< Context status signal type
+  typedef Signal< void () > SceneCreatedSignalType;               ///< Scene created signal type
+
+  static const Vector4 DEFAULT_BACKGROUND_COLOR; ///< Default black background.
+  static const Vector4 DEBUG_BACKGROUND_COLOR;   ///< Green background, useful when debugging.
+
+  /**
+   * @brief Allows the creation of an empty stage handle.
+   *
+   * To retrieve the current stage, this handle can be set using Stage::GetCurrent().
+   * @since_tizen 2.4
+   */
+  Stage();
+
+  /**
+   * @brief Get the current Stage.
+   *
+   * @since_tizen 2.4
+   * @return The current stage or an empty handle if Core has not been created or has been already destroyed.
+   */
+  static Stage GetCurrent();
+
+  /**
+   * @brief Query whether the Stage exists; this should only return false during or after destruction of Dali core.
+   *
+   * @since_tizen 2.4
+   * @return True when it's safe to call Stage::GetCurrent().
+   */
+  static bool IsInstalled();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Stage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  Stage(const Stage& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Stage& operator=(const Stage& rhs);
+
+  // Containment
+
+  /**
+   * @brief Adds a child Actor to the Stage.
+   *
+   * The child will be referenced.
+   * @since_tizen 2.4
+   * @param [in] actor The child.
+   * @pre The actor has been initialized.
+   * @pre The actor does not have a parent.
+   */
+  void Add(Actor& actor);
+
+  /**
+   * @brief Removes a child Actor from the Stage.
+   *
+   * The child will be unreferenced.
+   * @since_tizen 2.4
+   * @param [in] actor The child.
+   * @pre The actor has been added to the stage.
+   */
+  void Remove(Actor& actor);
+
+  /**
+   * @brief Returns the size of the Stage in pixels as a Vector.
+   *
+   * The x component will be the width of the Stage in pixels
+   * The y component will be the height of the Stage in pixels
+   * The z component will be the distance between far and near planes
+   * @since_tizen 2.4
+   * @return The size of the Stage as a Vector.
+   */
+  Vector2 GetSize() const;
+
+  // Render Tasks
+
+  /**
+   * @brief Retrieve the list of render-tasks.
+   *
+   * @since_tizen 2.4
+   * @return A valid handle to a RenderTaskList.
+   */
+  RenderTaskList GetRenderTaskList() const;
+
+  // Layers
+
+  /**
+   * @brief Query the number of on-stage layers.
+   *
+   * Note that a default layer is always provided (count >= 1).
+   * @since_tizen 2.4
+   * @return The number of layers.
+   */
+  unsigned int GetLayerCount() const;
+
+  /**
+   * @brief Retrieve the layer at a specified depth.
+   *
+   * @since_tizen 2.4
+   * @param[in] depth The depth.
+   * @return The layer found at the given depth.
+   * @pre depth is less than layer count; see GetLayerCount().
+   */
+  Layer GetLayer(unsigned int depth) const;
+
+  /**
+   * @brief Returns the Stage's Root Layer.
+   *
+   * @since_tizen 2.4
+   * @return The root layer.
+   */
+  Layer GetRootLayer() const;
+
+  // Background color
+
+  /**
+   * @brief Set the background color of the stage.
+   *
+   * @since_tizen 2.4
+   * @param[in] color The new background color.
+   */
+  void SetBackgroundColor(Vector4 color);
+
+  /**
+   * @brief Retrieve the background color of the stage.
+   *
+   * @since_tizen 2.4
+   * @return The background color.
+   */
+  Vector4 GetBackgroundColor() const;
+
+  /**
+   * @brief Retrieve the DPI of the display device to which the stage is connected.
+   *
+   * @since_tizen 2.4
+   * @return the horizontal and vertical DPI
+   */
+  Vector2 GetDpi() const;
+
+  /**
+   * @brief Get the Object registry.
+   *
+   * @since_tizen 2.4
+   * @return The object registry.
+   */
+  ObjectRegistry GetObjectRegistry() const;
+
+  // Rendering
+
+  /**
+   * @brief Keep rendering for at least the given amount of time.
+   *
+   * By default Dali will stop rendering when no Actor positions are being set, and when no animations are running etc.
+   * This method is useful to force screen refreshes e.g. when updating a NativeImage.
+   * @since_tizen 2.4
+   * @param durationSeconds to keep rendering, 0 means render at least one more frame
+   */
+  void KeepRendering( float durationSeconds );
+
+  // Signals
+
+  /**
+   * @brief This signal is emitted when key event is received.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(const KeyEvent& event);
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   */
+  KeyEventSignalType& KeyEventSignal();
+
+  /**
+   * @brief This signal is emitted just after the event processing is finished.
+   *
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   */
+  EventProcessingFinishedSignalType& EventProcessingFinishedSignal();
+
+  /**
+   * @brief This signal is emitted when the screen is touched and when the touch ends
+   * (i.e. the down & up touch events only).
+   *
+   * If there are multiple touch points, then this will be emitted when the first touch occurs and
+   * then when the last finger is lifted.
+   * An interrupted event will also be emitted.
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(const TouchEvent& event);
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @return The touch signal to connect to.
+   * @note Motion events are not emitted.
+   */
+  TouchedSignalType& TouchedSignal();
+
+  /**
+   * @brief This signal is emitted when wheel event is received.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(const WheelEvent& event);
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   */
+  WheelEventSignalType& WheelEventSignal();
+
+  /**
+   * @brief This signal is emitted when the GL context is lost (Platform specific behaviour).
+   *
+   * If the application is responsible for handling context loss, it should listen to
+   * this signal and tear down UI components when recieved.
+   * @since_tizen 2.4
+   * @return The ContextLost signal to connect to.
+   */
+  ContextStatusSignal& ContextLostSignal();
+
+  /**
+   * @brief This signal is emitted when the GL context is regained (Platform specific
+   * behaviour).
+   *
+   * If the application is responsible for handling context loss, it should listen to
+   * this signal and rebuild UI components on receipt.
+   * @since_tizen 2.4
+   * @return The ContextRegained signal to connect to.
+   */
+  ContextStatusSignal& ContextRegainedSignal();
+
+  /**
+   * @brief This signal is emitted after the initial scene is created. It will be triggered after the
+   * application init signal.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName();
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   */
+  SceneCreatedSignalType& SceneCreatedSignal();
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali GetCurrent() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] stage A pointer to a Dali resource
+   */
+  explicit DALI_INTERNAL Stage(Internal::Stage* stage);
+};
+
+/**
+ * @}
+ */
+
+} // namespace Dali
+
+#endif // __DALI_STAGE_H__
diff --git a/dali/public-api/common/type-traits.h b/dali/public-api/common/type-traits.h
new file mode 100644 (file)
index 0000000..6342b3a
--- /dev/null
@@ -0,0 +1,65 @@
+#ifndef __DALI_TYPE_TRAITS_H__
+#define __DALI_TYPE_TRAITS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief Basic type traits that every type has by default
+ * This allows specialisations to not have to repeat all flags
+ * @since_tizen 2.4
+ */
+template <typename Type>
+struct BasicTypes
+{
+  /**
+   * This flag tells Dali if a class can be considered POD. If it declares copy constructor and/or destructor, its not considered trivial
+   * and cannot be copied by using memcpy etc.
+   */
+  enum { IS_TRIVIAL_TYPE = __has_trivial_destructor(Type) && __has_trivial_copy(Type) };
+};
+
+/**
+ * @brief Type traits support
+ * An example of overriding a traits flag for a custom type can be done by:
+ * <code>
+ * namespace Dali
+ * {
+ *   /// Tell DALi that Matrix is POD, even though it has a copy constructor
+ *   template <> struct TypeTraits< Matrix > : public BasicTypes< Matrix > { enum { IS_TRIVIAL_TYPE = true }; };
+ * }
+ * </code>
+ * @since_tizen 2.4
+ */
+template <typename Type>
+struct TypeTraits : public BasicTypes< Type >
+{
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif /* __DALI_TYPE_TRAITS_H__ */
diff --git a/dali/public-api/common/vector-wrapper.h b/dali/public-api/common/vector-wrapper.h
new file mode 100644 (file)
index 0000000..0606a1a
--- /dev/null
@@ -0,0 +1,47 @@
+#ifndef __VECTOR_WRAPPER_H__
+#define __VECTOR_WRAPPER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+#ifndef HIDE_DALI_INTERNALS
+
+#include <vector>
+
+#else
+
+// ensure that default visibility is used with any class that is used as an exception type
+#include <memory>
+#include <new>
+#include <stdexcept>
+
+#include <bits/c++config.h>
+#undef _GLIBCXX_VISIBILITY_ATTR
+#define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ ("hidden")))
+#include <vector>
+#undef _GLIBCXX_VISIBILITY_ATTR
+#define _GLIBCXX_VISIBILITY_ATTR(V) __attribute__ ((__visibility__ (#V))) // restore `_GLIBCXX_VISIBILITY_ATTR`
+
+#endif //ifndef HIDE_DALI_INTERNALS
+
+#endif /* __VECTOR_WRAPPER__H__ */
diff --git a/dali/public-api/common/view-mode.h b/dali/public-api/common/view-mode.h
new file mode 100644 (file)
index 0000000..17edbd9
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DALI_VIEW_MODE_H__
+#define __DALI_VIEW_MODE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_common
+ * @{
+ */
+
+/**
+ * @brief Stereoscopic view modes
+ * @since_tizen 2.4
+ */
+enum ViewMode
+{
+  MONO,              ///< Monoscopic (single camera). This is the default
+  STEREO_HORIZONTAL, ///< Stereoscopic. Frame buffer is split horizontally with the left and right camera views in their respective sides.
+  STEREO_VERTICAL,   ///< Stereoscopic. Frame buffer is split vertically with the left camera view at the top and the right camera view at the bottom.
+  STEREO_INTERLACED  ///< Stereoscopic. Left/Right camera views are rendered into the framebuffer on alternate frames.
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_VIEW_MODE_H__
diff --git a/dali/public-api/dali-core-version.cpp b/dali/public-api/dali-core-version.cpp
new file mode 100644 (file)
index 0000000..4759dc7
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include <dali/public-api/dali-core-version.h>
+
+// EXTERNAL INCLUDES
+#ifdef DEBUG_ENABLED
+#include <iostream>
+#endif
+
+namespace Dali
+{
+
+const unsigned int CORE_MAJOR_VERSION = 1;
+const unsigned int CORE_MINOR_VERSION = 0;
+const unsigned int CORE_MICRO_VERSION = 49;
+const char * const CORE_BUILD_DATE    = __DATE__ " " __TIME__;
+
+#ifdef DEBUG_ENABLED
+namespace
+{
+/// Allows the printing of the version number ONLY when debug is enabled
+struct PrintVersion
+{
+  PrintVersion()
+  {
+    std::cout << "DALi Core:      " << CORE_MAJOR_VERSION << "." << CORE_MINOR_VERSION << "." << CORE_MICRO_VERSION << " (" << CORE_BUILD_DATE << ")" << std::endl;
+  }
+};
+PrintVersion CORE_VERSION;
+} // unnamed namespace
+#endif
+
+} // namespace Dali
diff --git a/dali/public-api/dali-core-version.h b/dali/public-api/dali-core-version.h
new file mode 100644 (file)
index 0000000..48bf112
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __DALI_CORE_VERSION_H__
+#define __DALI_CORE_VERSION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+DALI_IMPORT_API extern const unsigned int CORE_MAJOR_VERSION; ///< The major version number of the Core library.
+DALI_IMPORT_API extern const unsigned int CORE_MINOR_VERSION; ///< The minor version number of the Core library.
+DALI_IMPORT_API extern const unsigned int CORE_MICRO_VERSION; ///< The micro version number of the Core library.
+DALI_IMPORT_API extern const char * const CORE_BUILD_DATE;    ///< The date/time the Core library was built.
+} // namespace Dali
+
+#endif // __DALI_CORE_VERSION_H__
diff --git a/dali/public-api/dali-core.h b/dali/public-api/dali-core.h
new file mode 100644 (file)
index 0000000..046654a
--- /dev/null
@@ -0,0 +1,128 @@
+#ifndef __DALI_CORE_H__
+#define __DALI_CORE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/actors/actor-enumerations.h>
+#include <dali/public-api/actors/blending.h>
+#include <dali/public-api/actors/camera-actor.h>
+#include <dali/public-api/actors/custom-actor-impl.h>
+#include <dali/public-api/actors/custom-actor.h>
+#include <dali/public-api/actors/draw-mode.h>
+#include <dali/public-api/actors/image-actor.h>
+#include <dali/public-api/actors/layer.h>
+#include <dali/public-api/actors/sampling.h>
+
+#include <dali/public-api/animation/alpha-function.h>
+#include <dali/public-api/animation/animation.h>
+#include <dali/public-api/animation/constraint-source.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/animation/constraints.h>
+#include <dali/public-api/animation/key-frames.h>
+#include <dali/public-api/animation/linear-constrainer.h>
+#include <dali/public-api/animation/path.h>
+#include <dali/public-api/animation/time-period.h>
+
+#include <dali/public-api/common/compile-time-assert.h>
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+#include <dali/public-api/common/loading-state.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/view-mode.h>
+
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/events/hover-event.h>
+#include <dali/public-api/events/key-event.h>
+#include <dali/public-api/events/long-press-gesture-detector.h>
+#include <dali/public-api/events/long-press-gesture.h>
+#include <dali/public-api/events/wheel-event.h>
+#include <dali/public-api/events/pan-gesture-detector.h>
+#include <dali/public-api/events/pan-gesture.h>
+#include <dali/public-api/events/pinch-gesture-detector.h>
+#include <dali/public-api/events/pinch-gesture.h>
+#include <dali/public-api/events/tap-gesture-detector.h>
+#include <dali/public-api/events/tap-gesture.h>
+#include <dali/public-api/events/touch-event.h>
+#include <dali/public-api/events/touch-point.h>
+
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/public-api/images/encoded-buffer-image.h>
+#include <dali/public-api/images/frame-buffer-image.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/native-image.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/images/nine-patch-image.h>
+#include <dali/public-api/images/pixel.h>
+
+#include <dali/public-api/math/angle-axis.h>
+#include <dali/public-api/math/compile-time-math.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/random.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/uint-16-pair.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/object/any.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/base-object.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/object-registry.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/property-conditions.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/object/property-input.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/property-notification-declarations.h>
+#include <dali/public-api/object/property-notification.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/object/type-info.h>
+#include <dali/public-api/object/type-registry.h>
+
+#include <dali/public-api/render-tasks/render-task-list.h>
+#include <dali/public-api/render-tasks/render-task.h>
+
+#include <dali/public-api/signals/base-signal.h>
+#include <dali/public-api/signals/callback.h>
+#include <dali/public-api/signals/connection-tracker-interface.h>
+#include <dali/public-api/signals/connection-tracker.h>
+#include <dali/public-api/signals/dali-signal.h>
+#include <dali/public-api/signals/functor-delegate.h>
+#include <dali/public-api/signals/signal-slot-connections.h>
+#include <dali/public-api/signals/signal-slot-observers.h>
+#include <dali/public-api/signals/slot-delegate.h>
+
+#include <dali/public-api/shader-effects/shader-effect.h>
+
+#include <dali/public-api/size-negotiation/relayout-container.h>
+
+#include <dali/public-api/dali-core-version.h>
+
+#endif // __DALI_CORE_H__
diff --git a/dali/public-api/events/gesture-detector.cpp b/dali/public-api/events/gesture-detector.cpp
new file mode 100644 (file)
index 0000000..16f2be0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/gesture-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/gesture-detector-impl.h>
+
+namespace Dali
+{
+
+GestureDetector::GestureDetector(Internal::GestureDetector* internal)
+: Handle(internal)
+{
+}
+
+GestureDetector::GestureDetector()
+{
+}
+
+GestureDetector GestureDetector::DownCast( BaseHandle handle )
+{
+  return GestureDetector( dynamic_cast<Dali::Internal::GestureDetector*>(handle.GetObjectPtr()) );
+}
+
+GestureDetector::~GestureDetector()
+{
+}
+
+GestureDetector::GestureDetector(const GestureDetector& handle)
+: Handle(handle)
+{
+}
+
+GestureDetector& GestureDetector::operator=(const GestureDetector& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void GestureDetector::Attach(Actor actor)
+{
+  GetImplementation(*this).Attach(GetImplementation(actor));
+}
+
+void GestureDetector::Detach(Actor actor)
+{
+  GetImplementation(*this).Detach(GetImplementation(actor));
+}
+
+void GestureDetector::DetachAll()
+{
+  GetImplementation(*this).DetachAll();
+}
+
+size_t GestureDetector::GetAttachedActorCount() const
+{
+  return GetImplementation(*this).GetAttachedActorCount();
+}
+
+Actor GestureDetector::GetAttachedActor(size_t index) const
+{
+  return GetImplementation(*this).GetAttachedActor(index);
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/gesture-detector.h b/dali/public-api/events/gesture-detector.h
new file mode 100644 (file)
index 0000000..1171917
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __DALI_GESTURE_DETECTOR_H__
+#define __DALI_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/object/handle.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class GestureDetector;
+}
+
+class Actor;
+
+/**
+ * @brief GestureDetectors analyse a stream of touch events and attempt to determine the intention of the user.
+ *
+ * An actor is attached to a gesture detector and if the detector recognises a pattern in its analysis, it will
+ * emit a detected signal to the application.
+ *
+ * This is the base class for different gesture detectors available and provides functionality that is common
+ * to all the gesture detectors.
+ *
+ * @since_tizen 2.4
+ * @see Gesture
+ */
+class DALI_IMPORT_API GestureDetector : public Handle
+{
+public: // Creation & Destruction
+
+  /**
+   * @brief Create an uninitialized GestureDetector; this can be initialized with one of the derived gestures' New() methods.
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  GestureDetector();
+
+  /**
+   * @brief Downcast an Object handle to GestureDetector handle.
+   *
+   * If handle points to a GestureDetector object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a GestureDetector object or an uninitialized handle
+   */
+  static GestureDetector DownCast( BaseHandle handle );
+
+  /**
+   * @brief Dali::GestureDetector is intended as a base class
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~GestureDetector();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  GestureDetector(const GestureDetector& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  GestureDetector& operator=(const GestureDetector& rhs);
+
+public: // Actor related
+
+  /**
+   * @brief Attaches an actor to the gesture.
+   *
+   * The detected signal will be dispatched when the gesture occurs on
+   * the attached actor.
+   * @since_tizen 2.4
+   * @param[in]  actor  The actor to attach to the gesture detector
+   * @pre The gesture detector has been initialized.
+   * @note You can attach several actors to a gesture detector.
+   */
+  void Attach(Actor actor);
+
+  /**
+   * @brief Detaches the attached actor from the gesture detector.
+   *
+   * @since_tizen 2.4
+   * @param[in]  actor  The actor to detach from the gesture detector.
+   * @pre The gesture detector has been initialized.
+   * @pre The specified actor has been attached to the gesture detector.
+   */
+  void Detach(Actor actor);
+
+  /**
+   * @brief Detaches all the actors that have been attached to the gesture detector.
+   *
+   * @since_tizen 2.4
+   * @pre The gesture detector has been initialized.
+   * @pre At least one actor has been attached to the gesture detector.
+   */
+  void DetachAll();
+
+  /**
+   * @brief Returns the number of actors attached to the gesture detector.
+   *
+   * @since_tizen 2.4
+   * @return The count
+   * @pre The gesture detector has been initialized.
+   */
+  size_t GetAttachedActorCount() const;
+
+  /**
+   * @brief Returns an actor by index. An empty handle if the index is not valid.
+   *
+   * @since_tizen 2.4
+   * @return The attached actor or an empty handle.
+   * @pre The gesture detector has been initialized.
+   */
+  Actor GetAttachedActor(size_t index) const;
+
+protected:
+
+  /**
+   * @brief This constructor is used by Dali New() methods of derived classes.
+   *
+   * @since_tizen 2.4
+   * @param [in]  internal  A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL GestureDetector(Internal::GestureDetector* internal);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_GESTURE_DETECTOR_H__
diff --git a/dali/public-api/events/gesture.cpp b/dali/public-api/events/gesture.cpp
new file mode 100644 (file)
index 0000000..31c3b25
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/gesture.h>
+
+namespace Dali
+{
+
+Gesture::Gesture( const Gesture& rhs )
+: type(rhs.type),
+  state(rhs.state),
+  time(rhs.time)
+{
+}
+
+Gesture& Gesture::operator=( const Gesture& rhs )
+{
+  type = rhs.type;
+  state = rhs.state;
+  time = rhs.time;
+
+  return *this;
+}
+
+Gesture::~Gesture()
+{
+}
+
+Gesture::Gesture(Type gestureType, State gestureState)
+: type(gestureType),
+  state(gestureState),
+  time(0)
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/gesture.h b/dali/public-api/events/gesture.h
new file mode 100644 (file)
index 0000000..68ec415
--- /dev/null
@@ -0,0 +1,132 @@
+#ifndef __DALI_GESTURE_H__
+#define __DALI_GESTURE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief Base structure for different gestures that an application can receive.
+ *
+ * A gesture is an event that is produced from a combination of
+ * several touch events in a particular order or within a certain time
+ * frame (e.g pinch).
+ *
+ * To receive a particular gesture, the application has to create and connect to the appropriate
+ * GestureDetector.
+ *
+ * @since_tizen 2.4
+ * @note An instance of this class cannot be created.
+ * @see GestureDetector
+ *
+ */
+struct DALI_IMPORT_API Gesture
+{
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 2.4
+   */
+  Gesture( const Gesture& rhs );
+
+  /**
+   * @brief Assignment operator.
+   * @since_tizen 2.4
+   */
+  Gesture& operator=( const Gesture& rhs );
+
+  // Destruction
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~Gesture();
+
+  /**
+   * @brief Type of gesture.
+   * @since_tizen 2.4
+   */
+  enum Type
+  {
+    Pinch      = 1 << 0, ///< When two touch points move away or towards each other.
+    Pan        = 1 << 1, ///< When the user drags their finger(s) in a particular direction.
+    Tap        = 1 << 2, ///< When the user taps the screen.
+    LongPress  = 1 << 3  ///< When the user continues to touch the same area on the screen for the device configured time.
+  };
+
+  /**
+   * @brief State of the gesture.
+   * @since_tizen 2.4
+   */
+  enum State
+  {
+    Clear,      ///< There is no state associated with this gesture.
+    Started,    ///< The touched points on the screen have moved enough to be considered a gesture.
+    Continuing, ///< The gesture is continuing.
+    Finished,   ///< The user has lifted a finger or touched an additional point on the screen.
+    Cancelled,  ///< The gesture has been cancelled.
+    Possible    ///< A gesture is possible.
+  };
+
+  // Data
+
+  /**
+   * @brief The gesture type.
+   */
+  Type type;
+
+  /**
+   * @brief The gesture state.
+   *
+   * Please see the description in the sub-classes to see the states
+   * used by the actual gesture.
+   */
+  State state;
+
+  /**
+   * @brief The time the gesture took place.
+   */
+  unsigned int time;
+
+protected: // Creation
+
+  /**
+   * @brief This constructor is only used by derived classes.
+   *
+   * @since_tizen 2.4
+   * @param[in] gestureType   The type of gesture event.
+   * @param[in] gestureState  The state of the gesture event.
+   */
+  Gesture(Type gestureType, State gestureState);
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_GESTURE_H__
diff --git a/dali/public-api/events/hover-event.cpp b/dali/public-api/events/hover-event.cpp
new file mode 100644 (file)
index 0000000..395a569
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/hover-event.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+HoverEvent::HoverEvent()
+: time(0)
+{
+}
+
+HoverEvent::HoverEvent(unsigned long time)
+: time(time)
+{
+}
+
+HoverEvent::~HoverEvent()
+{
+}
+
+unsigned int HoverEvent::GetPointCount() const
+{
+  return points.size();
+}
+
+const TouchPoint& HoverEvent::GetPoint(unsigned int point) const
+{
+  DALI_ASSERT_ALWAYS( point < points.size() && "No point at index" );
+  return points[point];
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/hover-event.h b/dali/public-api/events/hover-event.h
new file mode 100644 (file)
index 0000000..d950620
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_HOVER_EVENT_H__
+#define __DALI_HOVER_EVENT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief Hover events are a collection of touch points at a specific moment in time.
+ *
+ * When a multi-touch event occurs, each touch point represents the points that are currently being
+ * hovered or the points where a hover has stopped.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API HoverEvent
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Default constructor
+   * @since_tizen 2.4
+   */
+  HoverEvent();
+
+  /**
+   * @brief Constructor
+   * @since_tizen 2.4
+   * @param[in]  time  The time the event occurred
+   */
+  HoverEvent(unsigned long time);
+
+  /**
+   * @brief Destructor
+   * @since_tizen 2.4
+   */
+  ~HoverEvent();
+
+  // Data
+
+  /**
+   * @brief This is a container of points for this hover event.
+   *
+   * The first point in the set is always the
+   * primary touch point (i.e. the first point touched in a multi-touch event).
+   */
+  TouchPointContainer points;
+
+  /**
+   * @brief The time (in ms) that the hover event occurred.
+   */
+  unsigned long time;
+
+  // Convenience Methods
+
+  /**
+   * @brief Returns the total number of points in this HoverEvent.
+   *
+   * @since_tizen 2.4
+   * @return Total number of Points.
+   */
+  unsigned int GetPointCount() const;
+
+  /**
+   * @brief Returns a touch point at the index requested.
+   *
+   * The first point in the set is always the primary
+   * touch point (i.e. the first point touched in a multi-touch event).
+   * @since_tizen 2.4
+   * @param[in] point The index of the required Point.
+   * @return Point requested
+   * @note "point" should be less than the value returned by GetPointCount().
+   *       If out of range, then program asserts.
+   */
+  const TouchPoint& GetPoint(unsigned int point) const;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_HOVER_EVENT_H__
diff --git a/dali/public-api/events/key-event.cpp b/dali/public-api/events/key-event.cpp
new file mode 100644 (file)
index 0000000..0645ed1
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/key-event.h>
+
+namespace Dali
+{
+
+namespace
+{
+const unsigned int MODIFIER_SHIFT = 0x1;
+const unsigned int MODIFIER_CTRL  = 0x2;
+const unsigned int MODIFIER_ALT   = 0x4;
+const int KEY_INVALID_CODE = -1;
+
+}
+
+KeyEvent::KeyEvent()
+: keyPressedName(""),
+  keyPressed(""),
+  keyCode(KEY_INVALID_CODE),
+  keyModifier(0),
+  time(0),
+  state(KeyEvent::Down)
+{
+}
+
+KeyEvent::KeyEvent(const std::string& keyName, const std::string& keyString, int keyCode, int keyModifier,unsigned long timeStamp, const State& keyState)
+: keyPressedName(keyName),
+  keyPressed(keyString),
+  keyCode(keyCode),
+  keyModifier(keyModifier),
+  time(timeStamp),
+  state(keyState)
+{
+}
+
+KeyEvent::~KeyEvent()
+{
+}
+
+bool KeyEvent::IsShiftModifier() const
+{
+  if ((MODIFIER_SHIFT & keyModifier) == MODIFIER_SHIFT)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool KeyEvent::IsCtrlModifier() const
+{
+  if ((MODIFIER_CTRL & keyModifier) == MODIFIER_CTRL)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool KeyEvent::IsAltModifier() const
+{
+  if ((MODIFIER_ALT & keyModifier) == MODIFIER_ALT)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/key-event.h b/dali/public-api/events/key-event.h
new file mode 100644 (file)
index 0000000..c9b855d
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef __DALI_KEY_EVENT_H__
+#define __DALI_KEY_EVENT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief The key event structure is used to store a key press.
+ *
+ * It facilitates processing of these key presses and passing to other
+ * libraries like Toolkit. The keyString is the actual character you
+ * might want to display while the key name is just a descriptive
+ * name.  There is a key modifier which relates to keys like alt,
+ * shift and control functions are supplied to check if they have been
+ * pressed.
+ *
+ * Currently KeyEvent is also being used to relay messages from the
+ * IMF keyboard to Core. In future IMF may communicate via its own
+ * module.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API KeyEvent
+{
+  // Enumerations
+
+  /**
+   * @brief Specifies the state of the key event.
+   * @since_tizen 2.4
+   */
+  enum State
+  {
+    Down,        ///< Key down
+    Up,          ///< Key up
+    Last
+  };
+
+  /**
+   * @brief Default constructor
+   * @since_tizen 2.4
+   */
+  KeyEvent();
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in]  keyName       The name of the key pressed or command from the IMF, if later then the some following parameters will be needed.
+   * @param[in]  keyString     A string of input characters or key pressed
+   * @param[in]  keyCode       The unique key code for the key pressed.
+   * @param[in]  keyModifier   The key modifier for special keys like shift and alt
+   * @param[in]  timeStamp The time (in ms) that the key event occurred.
+   * @param[in]  keyState The state of the key event.
+   */
+  KeyEvent(const std::string& keyName, const std::string& keyString, int keyCode, int keyModifier, unsigned long timeStamp, const State& keyState);
+
+  /**
+   * @brief Destructor.
+   * @since_tizen 2.4
+   */
+  ~KeyEvent();
+
+  /**
+   * @brief Check to see if Shift key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if shift modifier
+   */
+  bool IsShiftModifier() const;
+
+  /**
+   * @brief Check to see if Ctrl (control) key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if ctrl modifier
+   */
+  bool IsCtrlModifier() const;
+
+  /**
+   * @brief Check to see if Alt key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if alt modifier
+   */
+  bool IsAltModifier() const;
+
+  // Data
+
+  /**
+   * @brief name given to the key pressed.
+   */
+  std::string keyPressedName;
+
+  /**
+   * @brief The actual string returned that should be used for input editors.
+   */
+  std::string keyPressed;
+
+  /**
+   * @brief Keycode for the key pressed.
+   */
+  int  keyCode;
+
+  /**
+   * @brief special keys like shift, alt and control which modify the next key pressed.
+   */
+  int  keyModifier;
+
+  /**
+   * @brief The time (in ms) that the key event occurred.
+   */
+  unsigned long time;
+
+  /**
+   * @brief State of the key event.
+   *
+   * @see State
+   */
+  State state;
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_KEY_EVENT_H__
diff --git a/dali/public-api/events/long-press-gesture-detector.cpp b/dali/public-api/events/long-press-gesture-detector.cpp
new file mode 100644 (file)
index 0000000..d49e9b9
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/long-press-gesture-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/long-press-gesture-detector-impl.h>
+
+namespace Dali
+{
+
+LongPressGestureDetector::LongPressGestureDetector(Internal::LongPressGestureDetector* internal)
+: GestureDetector(internal)
+{
+}
+
+LongPressGestureDetector::LongPressGestureDetector()
+{
+}
+
+LongPressGestureDetector LongPressGestureDetector::New()
+{
+  Internal::LongPressGestureDetectorPtr internal = Internal::LongPressGestureDetector::New();
+
+  return LongPressGestureDetector(internal.Get());
+}
+
+LongPressGestureDetector LongPressGestureDetector::New(unsigned int touchesRequired)
+{
+  Internal::LongPressGestureDetectorPtr internal = Internal::LongPressGestureDetector::New(touchesRequired);
+
+  return LongPressGestureDetector(internal.Get());
+}
+
+LongPressGestureDetector LongPressGestureDetector::New(unsigned int minTouches, unsigned int maxTouches)
+{
+  Internal::LongPressGestureDetectorPtr internal = Internal::LongPressGestureDetector::New(minTouches, maxTouches);
+
+  return LongPressGestureDetector(internal.Get());
+}
+
+LongPressGestureDetector LongPressGestureDetector::DownCast( BaseHandle handle )
+{
+  return LongPressGestureDetector( dynamic_cast<Dali::Internal::LongPressGestureDetector*>(handle.GetObjectPtr()) );
+}
+
+LongPressGestureDetector::~LongPressGestureDetector()
+{
+}
+
+LongPressGestureDetector::LongPressGestureDetector(const LongPressGestureDetector& handle)
+: GestureDetector(handle)
+{
+}
+
+LongPressGestureDetector& LongPressGestureDetector::operator=(const LongPressGestureDetector& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void LongPressGestureDetector::SetTouchesRequired(unsigned int touches)
+{
+  GetImplementation(*this).SetTouchesRequired(touches);
+}
+
+void LongPressGestureDetector::SetTouchesRequired(unsigned int minTouches, unsigned int maxTouches)
+{
+  GetImplementation(*this).SetTouchesRequired(minTouches, maxTouches);
+}
+
+unsigned int LongPressGestureDetector::GetMinimumTouchesRequired() const
+{
+  return GetImplementation(*this).GetMinimumTouchesRequired();
+}
+
+unsigned int LongPressGestureDetector::GetMaximumTouchesRequired() const
+{
+  return GetImplementation(*this).GetMaximumTouchesRequired();
+}
+
+LongPressGestureDetector::DetectedSignalType& LongPressGestureDetector::DetectedSignal()
+{
+  return GetImplementation(*this).DetectedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/long-press-gesture-detector.h b/dali/public-api/events/long-press-gesture-detector.h
new file mode 100644 (file)
index 0000000..6c38785
--- /dev/null
@@ -0,0 +1,228 @@
+#ifndef __DALI_LONG_PRESS_GESTURE_DETECTOR_H__
+#define __DALI_LONG_PRESS_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class LongPressGestureDetector;
+}
+
+struct LongPressGesture;
+
+/**
+ * @brief This class emits a signals when a long press gesture occurs that meets the requirements set by the application.
+ * @since_tizen 2.4
+ * @see LongPressGestureDetector::SetTouchesRequired.
+ *
+ * For any valid long press, two signals will be emitted:
+ * - First identifying the beginning (state = Started) i.e. when fingers held down for the required time.
+ * - Second identifying the ending (state = Finished) i.e. when fingers are released.
+ *
+ * The application programmer can use this gesture detector as follows:
+ * @code
+ * LongPressGestureDetector detector = LongPressGestureDetector::New();
+ * detector.Attach(myActor);
+ * detector.DetectedSignal().Connect(this, &MyApplication::OnLongPress);
+ * @endcode
+ *
+ * @see LongPressGesture
+ *
+ * Signals
+ * | %Signal Name        | Method                |
+ * |---------------------|-----------------------|
+ * | long-press-detected | @ref DetectedSignal() |
+ */
+class DALI_IMPORT_API LongPressGestureDetector : public GestureDetector
+{
+public: // Typedefs
+
+  typedef Signal< void ( Actor, const LongPressGesture& ) > DetectedSignalType; ///< Gesture detected signal type
+
+public: // Creation & Destruction
+
+  /**
+   * @brief Create an uninitialized LongPressGestureDetector; this can be initialized with LongPressGestureDetector::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  LongPressGestureDetector();
+
+  /**
+   * @brief Create an initialized LongPressGestureDetector.
+   *
+   * By default, this would create a gesture detector that requires only one touch.
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static LongPressGestureDetector New();
+
+  /**
+   * @brief Create an initialized LongPressGestureDetector with the number of touches required.
+   *
+   * A long press gesture will be emitted from this detector if the number of fingers touching the
+   * screen is equal to the touches required.
+   * @since_tizen 2.4
+   * @param[in]  touchesRequired  The number of touches required.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static LongPressGestureDetector New(unsigned int touchesRequired);
+
+  /**
+   * @brief Create an initialized LongPressGestureDetector with the minimum and maximum number of touches required.
+   *
+   * A long press gesture will be emitted from this detector if the number of fingers touching the screen
+   * falls between the minimum and maximum touches set.
+   * @since_tizen 2.4
+   * @param[in]  minTouches  The minimum number of touches required.
+   * @param[in]  maxTouches  The maximum number of touches required.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static LongPressGestureDetector New(unsigned int minTouches, unsigned int maxTouches);
+
+  /**
+   * @brief Downcast an Object handle to LongPressGestureDetector handle.
+   *
+   * If handle points to a LongPressGestureDetector object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a LongPressGestureDetector object or an uninitialized handle
+   */
+  static LongPressGestureDetector DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~LongPressGestureDetector();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  LongPressGestureDetector(const LongPressGestureDetector& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  LongPressGestureDetector& operator=(const LongPressGestureDetector& rhs);
+
+public: // Setters
+
+  /**
+   * @brief Set the number of touches required.
+   *
+   * The number of touches corresponds to the number of fingers a user
+   * has on the screen.  This sets the minimum and maximum touches to
+   * the input parameter.
+   *
+   * @since_tizen 2.4
+   * @param[in]  touches  Touches required.
+   * @pre The gesture detector has been initialized.
+   * @note The default is '1'.
+   */
+  void SetTouchesRequired(unsigned int touches);
+
+  /**
+   * @brief Sets the minimum and maximum touches required.
+   *
+   * The number of touches corresponds to the number of fingers a user
+   * has on the screen.
+   *
+   * @since_tizen 2.4
+   * @param[in]  minTouches  Minimum Touches required.
+   * @param[in]  maxTouches  Maximum Touches required.
+   * @pre The gesture detector has been initialized.
+   * @note The default is '1'.
+   */
+  void SetTouchesRequired(unsigned int minTouches, unsigned int maxTouches);
+
+public: // Getters
+
+  /**
+   * @brief Retrieves the minimum number of touches required.
+   *
+   * @since_tizen 2.4
+   * @return The minimum number of touches required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMinimumTouchesRequired() const;
+
+  /**
+   * @brief Retrieves the maximum number of touches required.
+   *
+   * @since_tizen 2.4
+   * @return The maximum number of touches required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMaximumTouchesRequired() const;
+
+public: // Signals
+
+  /**
+   * @brief  This signal is emitted when the specified long press is detected on the attached actor.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( Actor actor, const LongPressGesture& gesture );
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The gesture detector has been initialized.
+   */
+  DetectedSignalType& DetectedSignal();
+
+public: // Not intended for Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in]  internal  A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL LongPressGestureDetector(Internal::LongPressGestureDetector* internal);
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_LONG_PRESS_GESTURE_DETECTOR_H__
diff --git a/dali/public-api/events/long-press-gesture.cpp b/dali/public-api/events/long-press-gesture.cpp
new file mode 100644 (file)
index 0000000..b9dd141
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/long-press-gesture.h>
+
+namespace Dali
+{
+
+LongPressGesture::LongPressGesture(Gesture::State state)
+: Gesture( Gesture::LongPress, state ),
+  numberOfTouches( 1 )
+{
+}
+
+LongPressGesture::LongPressGesture( const LongPressGesture& rhs )
+: Gesture( rhs ),
+  numberOfTouches( rhs.numberOfTouches ),
+  screenPoint( rhs.screenPoint ),
+  localPoint( rhs.localPoint )
+{
+}
+
+LongPressGesture& LongPressGesture::operator=( const LongPressGesture& rhs )
+{
+  Gesture::operator=(rhs);
+  numberOfTouches = rhs.numberOfTouches;
+  screenPoint = rhs.screenPoint;
+  localPoint = rhs.localPoint;
+
+  return *this;
+}
+
+LongPressGesture::~LongPressGesture()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/long-press-gesture.h b/dali/public-api/events/long-press-gesture.h
new file mode 100644 (file)
index 0000000..72ba0da
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef __DALI_LONG_PRESS_GESTURE_H__
+#define __DALI_LONG_PRESS_GESTURE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief A LongPressGesture is emitted when the user touches and holds the screen with the stated number of fingers.
+ *
+ * This gesture can be in one of two states, when the long-press gesture is first detected: "Started";
+ * and when the long-press gesture ends: "Finished".
+ *
+ * Long press gesture finishes when all touches have been released.
+ *
+ * @since_tizen 2.4
+ * @see LongPressGestureDetector
+ */
+struct DALI_IMPORT_API LongPressGesture : public Gesture
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Constructor
+   *
+   * @since_tizen 2.4
+   * @param[in] state  The state of the gesture
+   */
+  LongPressGesture(Gesture::State state);
+
+  /**
+   * @brief Copy constructor
+   * @since_tizen 2.4
+   */
+  LongPressGesture( const LongPressGesture& rhs );
+
+  /**
+   * @brief Assignment operator
+   * @since_tizen 2.4
+   */
+  LongPressGesture& operator=( const LongPressGesture& rhs );
+
+  /**
+   * @brief Virtual destructor
+   * @since_tizen 2.4
+   */
+  virtual ~LongPressGesture();
+
+  // Data
+
+  /**
+   * @brief The number of touch points in this long press gesture, i.e. the number of fingers the user had
+   * on the screen to generate the long press gesture.
+   */
+  unsigned int numberOfTouches;
+
+  /**
+   * @brief This is the point, in screen coordinates, where the long press occurred.
+   *
+   * If a multi-touch long press, then this is the centroid of all the touch points.
+   */
+  Vector2 screenPoint;
+
+  /**
+   * @brief This is the point, in local actor coordinates, where the long press occurred.
+   *
+   * If a multi-touch long press, then this is the centroid of all the touch points.
+   * @return The point where tap has occurred (in local actor coordinates).
+   */
+  Vector2 localPoint;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_LONG_PRESS_GESTURE_H__
diff --git a/dali/public-api/events/pan-gesture-detector.cpp b/dali/public-api/events/pan-gesture-detector.cpp
new file mode 100644 (file)
index 0000000..78ed53d
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/pan-gesture-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/pan-gesture-detector-impl.h>
+
+namespace Dali
+{
+
+const Radian PanGestureDetector::DIRECTION_LEFT( -Math::PI );
+const Radian PanGestureDetector::DIRECTION_RIGHT( 0.0f );
+const Radian PanGestureDetector::DIRECTION_UP( -0.5f * Math::PI );
+const Radian PanGestureDetector::DIRECTION_DOWN( 0.5f * Math::PI );
+const Radian PanGestureDetector::DIRECTION_HORIZONTAL( Math::PI );
+const Radian PanGestureDetector::DIRECTION_VERTICAL( -0.5f * Math::PI );
+const Radian PanGestureDetector::DEFAULT_THRESHOLD( 0.25f * Math::PI );
+
+PanGestureDetector::PanGestureDetector(Internal::PanGestureDetector* internal)
+: GestureDetector(internal)
+{
+}
+
+PanGestureDetector::PanGestureDetector()
+{
+}
+
+PanGestureDetector PanGestureDetector::New()
+{
+  Internal::PanGestureDetectorPtr internal = Internal::PanGestureDetector::New();
+
+  return PanGestureDetector(internal.Get());
+}
+
+PanGestureDetector PanGestureDetector::DownCast( BaseHandle handle )
+{
+  return PanGestureDetector( dynamic_cast<Dali::Internal::PanGestureDetector*>(handle.GetObjectPtr()) );
+}
+
+PanGestureDetector::~PanGestureDetector()
+{
+}
+
+PanGestureDetector::PanGestureDetector(const PanGestureDetector& handle)
+: GestureDetector(handle)
+{
+}
+
+PanGestureDetector& PanGestureDetector::operator=(const PanGestureDetector& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void PanGestureDetector::SetMinimumTouchesRequired(unsigned int minimum)
+{
+  GetImplementation(*this).SetMinimumTouchesRequired(minimum);
+}
+
+void PanGestureDetector::SetMaximumTouchesRequired(unsigned int maximum)
+{
+  GetImplementation(*this).SetMaximumTouchesRequired(maximum);
+}
+
+unsigned int PanGestureDetector::GetMinimumTouchesRequired() const
+{
+  return GetImplementation(*this).GetMinimumTouchesRequired();
+}
+
+unsigned int PanGestureDetector::GetMaximumTouchesRequired() const
+{
+  return GetImplementation(*this).GetMaximumTouchesRequired();
+}
+
+void PanGestureDetector::AddAngle( Radian angle, Radian threshold )
+{
+  GetImplementation(*this).AddAngle( angle, threshold );
+}
+
+void PanGestureDetector::AddDirection( Radian direction, Radian threshold )
+{
+  GetImplementation(*this).AddDirection( direction, threshold );
+}
+
+size_t PanGestureDetector::GetAngleCount() const
+{
+  return GetImplementation(*this).GetAngleCount();
+}
+
+PanGestureDetector::AngleThresholdPair PanGestureDetector::GetAngle(size_t index) const
+{
+  return GetImplementation(*this).GetAngle(index);
+}
+
+void PanGestureDetector::ClearAngles()
+{
+  GetImplementation(*this).ClearAngles();
+}
+
+void PanGestureDetector::RemoveAngle( Radian angle )
+{
+  GetImplementation(*this).RemoveAngle( angle );
+}
+
+void PanGestureDetector::RemoveDirection( Radian direction )
+{
+  GetImplementation(*this).RemoveDirection( direction );
+}
+
+PanGestureDetector::DetectedSignalType& PanGestureDetector::DetectedSignal()
+{
+  return GetImplementation(*this).DetectedSignal();
+}
+
+void PanGestureDetector::SetPanGestureProperties( const PanGesture& pan )
+{
+  Internal::PanGestureDetector::SetPanGestureProperties( pan );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/pan-gesture-detector.h b/dali/public-api/events/pan-gesture-detector.h
new file mode 100644 (file)
index 0000000..0b3febf
--- /dev/null
@@ -0,0 +1,354 @@
+#ifndef __DALI_PAN_GESTURE_DETECTOR_H__
+#define __DALI_PAN_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+
+struct Radian;
+
+namespace Internal DALI_INTERNAL
+{
+class PanGestureDetector;
+}
+
+struct PanGesture;
+
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief This class looks for panning (or dragging) gestures.
+ *
+ * The user will be pressing one or more fingers on an actor while they pan it.
+ *
+ * The application programmer can use this gesture detector as follows:
+ * @code
+ * PanGestureDetector detector = PanGestureDetector::New();
+ * detector.Attach(myActor);
+ * detector.DetectedSignal().Connect(this, &MyApplication::OnPan);
+ *
+ * // Detect pan gesture for single and double touch.
+ * detector.SetMaximumTouchesRequired(2);
+ * @endcode
+ *
+ * @since_tizen 2.4
+ * @see PanGesture
+ *
+ * Signals
+ * | %Signal Name | Method                |
+ * |--------------|-----------------------|
+ * | pan-detected | @ref DetectedSignal() |
+ */
+class DALI_IMPORT_API PanGestureDetector : public GestureDetector
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the PanGestureDetector class.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      SCREEN_POSITION = DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX, ///< name "screen-position",     type Vector2
+      SCREEN_DISPLACEMENT,                                             ///< name "screen-displacement", type Vector2
+      SCREEN_VELOCITY,                                                 ///< name "screen-velocity",     type Vector2
+      LOCAL_POSITION,                                                  ///< name "local-position",      type Vector2
+      LOCAL_DISPLACEMENT,                                              ///< name "local-displacement",  type Vector2
+      LOCAL_VELOCITY,                                                  ///< name "local-velocity",      type Vector2
+      PANNING,                                                         ///< name "panning",             type bool
+    };
+  };
+
+  // Typedefs
+  typedef Signal< void ( Actor, const PanGesture& ) > DetectedSignalType; ///< Pan gesture detected signal type
+
+  // Directional Pan
+  typedef std::pair< Radian, Radian > AngleThresholdPair; ///< Range of angles for a direction
+
+  static const Radian DIRECTION_LEFT;       ///< For a left pan (-PI Radians).
+  static const Radian DIRECTION_RIGHT;      ///< For a right pan (0 Radians).
+  static const Radian DIRECTION_UP;         ///< For an up pan (-0.5 * PI Radians).
+  static const Radian DIRECTION_DOWN;       ///< For a down pan (0.5 * PI Radians).
+  static const Radian DIRECTION_HORIZONTAL; ///< For a left and right pan (PI Radians). Useful for AddDirection().
+  static const Radian DIRECTION_VERTICAL;   ///< For an up and down pan (-0.5 * PI Radians). Useful for AddDirection().
+
+  static const Radian DEFAULT_THRESHOLD;    ///< The default threshold is PI * 0.25 radians (or 45 degrees).
+
+public: // Creation & Destruction
+
+  /**
+   * @brief Create an uninitialized PanGestureDetector; this can be initialized with PanGestureDetector::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  PanGestureDetector();
+
+  /**
+   * @brief Create an initialized PanGestureDetector.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static PanGestureDetector New();
+
+  /**
+   * @brief Downcast an Object handle to PanGestureDetector handle.
+   *
+   * If handle points to a PanGestureDetector object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a PanGestureDetector object or an uninitialized handle
+   */
+  static PanGestureDetector DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~PanGestureDetector();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  PanGestureDetector(const PanGestureDetector& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  PanGestureDetector& operator=(const PanGestureDetector& rhs);
+
+public: // Setters
+
+  /**
+   * @brief This is the minimum number of touches required for the pan gesture to be detected.
+   *
+   * @since_tizen 2.4
+   * @param[in]  minimum  Minimum touches required.
+   * @pre The gesture detector has been initialized.
+   * @note The default minimum is '1'.
+   */
+  void SetMinimumTouchesRequired(unsigned int minimum);
+
+  /**
+   * @brief This is the maximum number of touches required for the pan gesture to be detected.
+   *
+   * @since_tizen 2.4
+   * @param[in]  maximum  Maximum touches required.
+   * @pre The gesture detector has been initialized.
+   * @note The default maximum is '1'.
+   */
+  void SetMaximumTouchesRequired(unsigned int maximum);
+
+public: // Getters
+
+  /**
+   * @brief Retrieves the minimum number of touches required for the pan gesture to be detected.
+   *
+   * @since_tizen 2.4
+   * @return The minimum touches required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMinimumTouchesRequired() const;
+
+  /**
+   * @brief Retrieves the maximum number of touches required for the pan gesture to be detected.
+   *
+   * @since_tizen 2.4
+   * @return The maximum touches required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMaximumTouchesRequired() const;
+
+public: // Directional Panning
+
+  /**
+   * @brief The pan gesture is only emitted if the pan occurs in the direction specified by this method with a +/- threshold allowance.
+   *
+   * The angle is from -180 -> 0 -> 180 degrees (or -M_PI -> 0 -> M_PI in radians) i.e:
+   *
+   * @code
+   *           -90.0f ( -0.5f * PI )
+   *                     |
+   *                     |
+   * 180.0f ( PI ) ------------- 0.0f ( 0.0f )
+   *                     |
+   *                     |
+   *            90.0f ( 0.5f * PI )
+   * @endcode
+   *
+   * If an angle of 0.0 degrees is specified and the threshold is 45 degrees then the acceptable
+   * direction range is from -45 to 45 degrees.
+   *
+   * @since_tizen 2.4
+   * @param[in]  angle      The angle that pan should be allowed.
+   * @param[in]  threshold  The threshold around that angle.
+   *
+   * @pre The gesture detector has been initialized.
+   * @note The angle added using this API is only checked when the gesture first starts, after that,
+   *       this detector will emit the gesture regardless of what angle the pan is moving.
+   * @note The user can add as many angles as they require.
+   * @note If an angle outside the range above is given, then it is wrapped within the range, i.e.
+   *       190 degrees becomes -170 degrees and 370 degrees becomes 10 degrees.
+   * @note As long as you specify the type, you can also pass in a Dali::Degree to this method.
+   * @note If no threshold is provided, then the default threshold (PI * 0.25) is used.
+   * @note If the threshold is greater than PI, then PI will be used as the threshold.
+   *
+   */
+  void AddAngle( Radian angle, Radian threshold = DEFAULT_THRESHOLD );
+
+  /**
+   * @brief A helper method for adding bi-directional angles where the pan should take place.
+   *
+   * In other words, if 0 is requested, then PI will also be added so that we have both left and
+   * right scrolling.
+   *
+   * @since_tizen 2.4
+   * @param[in]  direction  The direction of panning required.
+   * @param[in]  threshold  The threshold.
+   *
+   * @pre The gesture detector has been initialized.
+   *
+   * @note If a direction outside the range above is given, then it is wrapped within the range, i.e.
+   *       190 degrees becomes -170 degrees and 370 degrees becomes 10 degrees.
+   * @note If no threshold is provided, then the default threshold (PI * 0.25) is used.
+   * @note If the threshold is greater than PI, then PI will be used as the threshold.
+   * @note As long as you specify the type, you can also pass in a Dali::Degree to this method.
+   *
+   * @see AddAngle
+   */
+  void AddDirection( Radian direction, Radian threshold = DEFAULT_THRESHOLD );
+
+  /**
+   * @brief Returns the count of angles that this pan gesture detector emits a signal.
+   *
+   * @since_tizen 2.4
+   * @return The count.
+   * @pre The gesture detector has been initialized.
+   */
+  size_t GetAngleCount() const;
+
+  /**
+   * @brief Returns the angle by index that this pan gesture detector emits a signal.
+   *
+   * @since_tizen 2.4
+   * @return an angle threshold pair, or a zero valued angle pair when index is invalid.
+   * @pre The gesture detector has been initialized.
+   * @pre The index is less than GetAngleCount()
+   */
+  AngleThresholdPair GetAngle(size_t index) const;
+
+  /**
+   * @brief Clears any directional angles that are used by the gesture detector.
+   *
+   * After this, the pan gesture
+   * will be emitted for a pan in ANY direction.
+   * @since_tizen 2.4
+   * @pre The gesture detector has been initialized.
+   */
+  void ClearAngles();
+
+  /**
+   * @brief Removes the angle specified from the container.
+   *
+   * @since_tizen 2.4
+   * @param[in]  angle  The angle to remove.
+   * @pre The gesture detector has been initialized.
+   * @note This will only remove the first instance of the angle found from the container.
+   * @note If an angle outside the range in AddAngle() is given, then the value is wrapped within
+   *       the range and that is removed.
+   */
+  void RemoveAngle( Radian angle );
+
+  /**
+   * @brief Removes the two angles that make up the direction from the container.
+   *
+   * @since_tizen 2.4
+   * @param[in]  direction  The direction to remove.
+   * @pre The gesture detector has been initialized.
+   * @note If a direction outside the range in AddAngle() is given, then the value is wrapped within
+   *       the range and that is removed.
+   */
+  void RemoveDirection( Radian direction );
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when the pan gesture is detected on the attached actor.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( Actor actor, const PanGesture& gesture );
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The gesture detector has been initialized.
+   */
+  DetectedSignalType& DetectedSignal();
+
+public: // Pan Properties Setters
+
+  /**
+   * @brief Allows setting of the pan properties that are returned in constraints.
+   *
+   * @since_tizen 2.4
+   * @param[in]  pan  The pan gesture to set.
+   * @note If a normal pan is taking place, then any value set is ignored.
+   */
+  static void SetPanGestureProperties( const PanGesture& pan );
+
+public: // Not intended for Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in]  internal  A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL PanGestureDetector(Internal::PanGestureDetector* internal);
+
+};
+
+/**
+ * @}
+ */
+
+} // namespace Dali
+
+#endif // __DALI_PAN_GESTURE_DETECTOR_H__
diff --git a/dali/public-api/events/pan-gesture.cpp b/dali/public-api/events/pan-gesture.cpp
new file mode 100644 (file)
index 0000000..f6011ad
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/pan-gesture.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+PanGesture::PanGesture()
+: Gesture(Gesture::Pan, Gesture::Clear),
+  numberOfTouches(1)
+{
+}
+
+PanGesture::PanGesture(Gesture::State state)
+: Gesture(Gesture::Pan, state),
+  numberOfTouches(1)
+{
+}
+
+PanGesture::PanGesture( const PanGesture& rhs )
+: Gesture( rhs ),
+  velocity( rhs.velocity ),
+  displacement( rhs.displacement ),
+  position( rhs.position ),
+  screenVelocity( rhs.screenVelocity ),
+  screenDisplacement( rhs.screenDisplacement ),
+  screenPosition( rhs.screenPosition ),
+  numberOfTouches( rhs.numberOfTouches )
+{
+}
+
+PanGesture& PanGesture::operator=( const PanGesture& rhs )
+{
+  Gesture::operator=(rhs);
+  velocity = rhs.velocity;
+  displacement = rhs.displacement;
+  position = rhs.position;
+  screenVelocity = rhs.screenVelocity;
+  screenDisplacement = rhs.screenDisplacement;
+  screenPosition = rhs.screenPosition;
+  numberOfTouches = rhs.numberOfTouches;
+
+  return *this;
+}
+
+PanGesture::~PanGesture()
+{
+}
+
+float PanGesture::GetSpeed() const
+{
+  return velocity.Length();
+}
+
+float PanGesture::GetDistance() const
+{
+  return displacement.Length();
+}
+
+float PanGesture::GetScreenSpeed() const
+{
+  return screenVelocity.Length();
+}
+
+float PanGesture::GetScreenDistance() const
+{
+  return screenDisplacement.Length();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/pan-gesture.h b/dali/public-api/events/pan-gesture.h
new file mode 100644 (file)
index 0000000..2b646fb
--- /dev/null
@@ -0,0 +1,189 @@
+#ifndef __DALI_PAN_GESTURE_H__
+#define __DALI_PAN_GESTURE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief A PanGesture is emitted when the user moves one or more fingers in a particular direction.
+ *
+ * This gesture can be in one of three states, when the pan gesture is first detected: "Started";
+ * when the pan gesture is continuing: "Continuing"; and finally, when the pan gesture ends:
+ * "Finished".
+ *
+ * A pan gesture will end in the following ways:
+ * - User releases the primary finger (the first touch).
+ * - User has more fingers on the screen than the maximum specified.
+ * - User has less fingers on the screen than the minimum specified.
+ * - Cancelled by the system.
+ *
+ * A pan gesture will continue to be sent to the actor under than initial pan until it ends.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API PanGesture: public Gesture
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Default Constructor.
+   * @since_tizen 2.4
+   */
+  PanGesture();
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in]  state  The state of the gesture
+   */
+  PanGesture(Gesture::State state);
+
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 2.4
+   */
+  PanGesture( const PanGesture& rhs );
+
+  /**
+   * @brief Assignment operator.
+   * @since_tizen 2.4
+   */
+  PanGesture& operator=( const PanGesture& rhs );
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~PanGesture();
+
+  // Data
+
+  /**
+   * @brief The velocity at which the user is moving their fingers.
+   *
+   * This is represented as a Vector2 and is the pixel movement per millisecond.
+   * A positive x value shows that the user is panning to the right, a negative x value means the opposite.
+   * A positive y value shows that the user is panning downwards, a negative y values means upwards.
+   * This value represents the local coordinates of the actor attached to the PanGestureDetector.
+   */
+  Vector2 velocity;
+
+  /**
+   * @brief This is a Vector2 showing how much the user has panned (dragged) since the last pan gesture or,
+   * if the gesture has just started, then the amount panned since the user touched the screen.
+   *
+   * A positive x value shows that the user is panning to the right, a negative x value means the opposite.
+   * A positive y value shows that the user is panning downwards, a negative y value means upwards.
+   * This value is in local actor coordinates, the actor being the one attached to the
+   * PanGestureDetector.
+   */
+  Vector2 displacement;
+
+  /**
+   * @brief This current touch position of the primary touch point in local actor coordinates.
+   */
+  Vector2 position;
+
+  /**
+   * @brief The velocity at which the user is moving their fingers.
+   *
+   * This is represented as a Vector2 and is the pixel movement per millisecond.
+   * A positive x value shows that the user is panning to the right, a negative x value means the opposite.
+   * A positive y value shows that the user is panning downwards, a negative y values means upwards.
+   * This value represents the screen coordinates.
+   */
+  Vector2 screenVelocity;
+
+  /**
+   * @brief This is a Vector2 showing how much the user has panned (dragged) since the last pan gesture or,
+   * if the gesture has just started, then the amount panned since the user touched the screen.
+   *
+   * A positive x value shows that the user is panning to the right, a negative x value means the opposite.
+   * A positive y value shows that the user is panning downwards, a negative y value means upwards.
+   * This value is in screen coordinates.
+   */
+  Vector2 screenDisplacement;
+
+  /**
+   * @brief This current touch position of the primary touch point in screen coordinates.
+   */
+  Vector2 screenPosition;
+
+  /**
+   * @brief The total number of fingers touching the screen in a pan gesture.
+   */
+  unsigned int numberOfTouches;
+
+  // Convenience Methods
+
+  /**
+   * @brief Returns the speed at which the user is moving their fingers.
+   *
+   * This is the pixel movement per millisecond.
+   * @since_tizen 2.4
+   * @return The speed of the pan (in pixels per millisecond).
+   */
+  float GetSpeed() const;
+
+  /**
+   * @brief This returns the distance the user has panned (dragged) since the last pan gesture or,
+   * if the gesture has just started, then the distance moved since the user touched the screen.
+   *
+   * This is always a positive value.
+   * @since_tizen 2.4
+   * @return The distance, as a float, a user's finger has panned.
+   */
+  float GetDistance() const;
+
+  /**
+   * @brief Returns the speed at which the user is moving their fingers relative to screen coordinates.
+   *
+   * This is the pixel movement per millisecond.
+   * @since_tizen 2.4
+   * @return The speed of the pan (in pixels per millisecond).
+   */
+  float GetScreenSpeed() const;
+
+  /**
+   * @brief This returns the distance the user has panned (dragged) since the last pan gesture in screen
+   * coordinates or, if the gesture has just started, then the distance in screen coordinates moved
+   * since the user touched the screen.
+   *
+   * This is always a positive value.
+   * @since_tizen 2.4
+   * @return The distance, as a float, a user's finger has panned.
+   */
+  float GetScreenDistance() const;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PAN_GESTURE_H__
diff --git a/dali/public-api/events/pinch-gesture-detector.cpp b/dali/public-api/events/pinch-gesture-detector.cpp
new file mode 100644 (file)
index 0000000..7eb5d70
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/pinch-gesture-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/pinch-gesture-detector-impl.h>
+
+namespace Dali
+{
+PinchGestureDetector::PinchGestureDetector(Internal::PinchGestureDetector* internal)
+: GestureDetector(internal)
+{
+}
+
+PinchGestureDetector::PinchGestureDetector()
+{
+}
+
+PinchGestureDetector PinchGestureDetector::New()
+{
+  Internal::PinchGestureDetectorPtr internal = Internal::PinchGestureDetector::New();
+
+  return PinchGestureDetector(internal.Get());
+}
+
+PinchGestureDetector PinchGestureDetector::DownCast( BaseHandle handle )
+{
+  return PinchGestureDetector( dynamic_cast<Dali::Internal::PinchGestureDetector*>(handle.GetObjectPtr()) );
+}
+
+PinchGestureDetector::~PinchGestureDetector()
+{
+}
+
+PinchGestureDetector::PinchGestureDetector(const PinchGestureDetector& handle)
+: GestureDetector(handle)
+{
+}
+
+PinchGestureDetector& PinchGestureDetector::operator=(const PinchGestureDetector& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+PinchGestureDetector::DetectedSignalType& PinchGestureDetector::DetectedSignal()
+{
+  return GetImplementation(*this).DetectedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/pinch-gesture-detector.h b/dali/public-api/events/pinch-gesture-detector.h
new file mode 100644 (file)
index 0000000..4a70c21
--- /dev/null
@@ -0,0 +1,157 @@
+#ifndef __DALI_PINCH_GESTURE_DETECTOR_H__
+#define __DALI_PINCH_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class PinchGestureDetector;
+}
+
+struct PinchGesture;
+
+/**
+ * @brief This class looks for pinching gestures involving two touches.
+ *
+ * It tries to detect when the user moves two touch points towards or
+ * away from each other.  Please see PinchGesture for more
+ * information.
+ *
+ * The application programmer can use this gesture detector as follows:
+ * @code
+ * PinchGestureDetector detector = PinchGestureDetector::New();
+ * detector.Attach(myActor);
+ * detector.DetectedSignal().Connect(this, &MyApplication::OnPinch);
+ * @endcode
+ *
+ * @since_tizen 2.4
+ * @see PinchGesture
+ *
+ * Signals
+ * | %Signal Name   | Method                |
+ * |----------------|-----------------------|
+ * | pinch-detected | @ref DetectedSignal() |
+ */
+class DALI_IMPORT_API PinchGestureDetector : public GestureDetector
+{
+public: // Typedefs
+
+  /**
+   * @brief Signal type.
+   * @since_tizen 2.4
+   */
+  typedef Signal< void ( Actor, const PinchGesture& ) > DetectedSignalType;
+
+public: // Creation & Destruction
+
+  /**
+   * @brief Create an uninitialized PinchGestureDetector; this can be initialized with PinchGestureDetector::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  PinchGestureDetector();
+
+  /**
+   * @brief Create an initialized PinchGestureDetector.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static PinchGestureDetector New();
+
+  /**
+   * @brief Downcast an Object handle to PinchGestureDetector handle.
+   *
+   * If handle points to a PinchGestureDetector object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a PinchGestureDetector object or an uninitialized handle
+   */
+  static PinchGestureDetector DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~PinchGestureDetector();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  PinchGestureDetector(const PinchGestureDetector& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  PinchGestureDetector& operator=(const PinchGestureDetector& rhs);
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when the pinch gesture is detected on the attached actor.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( Actor actor, const PinchGesture& gesture );
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The gesture detector has been initialized.
+   */
+  DetectedSignalType& DetectedSignal();
+
+public: // Not intended for Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in]  internal  A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL PinchGestureDetector(Internal::PinchGestureDetector* internal);
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PINCH_GESTURE_DETECTOR_H__
diff --git a/dali/public-api/events/pinch-gesture.cpp b/dali/public-api/events/pinch-gesture.cpp
new file mode 100644 (file)
index 0000000..d074efe
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/pinch-gesture.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+PinchGesture::PinchGesture(Gesture::State state)
+: Gesture(Gesture::Pinch, state),
+  scale(0.0f),
+  speed(0.0f)
+{
+}
+
+PinchGesture::PinchGesture( const PinchGesture& rhs )
+: Gesture( rhs ),
+  scale( rhs.scale ),
+  speed( rhs.speed ),
+  screenCenterPoint( rhs.screenCenterPoint ),
+  localCenterPoint( rhs.localCenterPoint )
+{
+}
+
+PinchGesture& PinchGesture::operator=( const PinchGesture& rhs )
+{
+  Gesture::operator=(rhs);
+  scale = rhs.scale;
+  speed = rhs.speed;
+  screenCenterPoint = rhs.screenCenterPoint;
+  localCenterPoint = rhs.localCenterPoint;
+
+  return *this;
+}
+
+PinchGesture::~PinchGesture()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/pinch-gesture.h b/dali/public-api/events/pinch-gesture.h
new file mode 100644 (file)
index 0000000..848dda8
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef __DALI_PINCH_GESTURE_H__
+#define __DALI_PINCH_GESTURE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief A PinchGesture is emitted when the user moves two fingers towards or away from each other.
+ *
+ * This gesture can be in one of three states; when the pinch gesture is first detected, its
+ * state is set to "Started".  After this, if there is change in the gesture, the state will
+ * be "Continuing".  Finally, when the gesture ends, the state of the gesture changes to
+ * "Finished".
+ *
+ * A pinch gesture will continue to be sent to the actor under the center point of the pinch
+ * until the pinch ends.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API PinchGesture: public Gesture
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Default Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in]  state  The state of the gesture
+   */
+  PinchGesture(Gesture::State state);
+
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 2.4
+   */
+  PinchGesture( const PinchGesture& rhs );
+
+  /**
+   * @brief Assignment operator.
+   * @since_tizen 2.4
+   */
+  PinchGesture& operator=( const PinchGesture& rhs );
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~PinchGesture();
+
+  // Data
+
+  /**
+   * @brief The scale factor from the start of the pinch gesture till the latest pinch gesture.
+   *
+   * If the user is moving their fingers away from each other, then
+   * this value increases.  Conversely, if the user is moving their
+   * fingers towards each other, this value will decrease.
+   */
+  float scale;
+
+  /**
+   * @brief The speed at which the user is moving their fingers.
+   *
+   * This is the pixel movement per second.
+   */
+  float speed;
+
+  /**
+   * @brief The center point of the two points that caused the pinch gesture in screen coordinates.
+   */
+  Vector2 screenCenterPoint;
+
+  /**
+   * @brief The center point of the two points that caused the pinch gesture in local actor coordinates.
+   */
+  Vector2 localCenterPoint;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PINCH_GESTURE_H__
diff --git a/dali/public-api/events/tap-gesture-detector.cpp b/dali/public-api/events/tap-gesture-detector.cpp
new file mode 100644 (file)
index 0000000..9611496
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/tap-gesture-detector.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/events/tap-gesture-detector-impl.h>
+
+namespace Dali
+{
+TapGestureDetector::TapGestureDetector(Internal::TapGestureDetector* internal)
+: GestureDetector(internal)
+{
+}
+
+TapGestureDetector::TapGestureDetector()
+{
+}
+
+TapGestureDetector TapGestureDetector::New()
+{
+  Internal::TapGestureDetectorPtr internal = Internal::TapGestureDetector::New();
+
+  return TapGestureDetector(internal.Get());
+}
+
+TapGestureDetector TapGestureDetector::New(unsigned int tapsRequired )
+{
+  Internal::TapGestureDetectorPtr internal = Internal::TapGestureDetector::New( tapsRequired );
+
+  return TapGestureDetector(internal.Get());
+}
+
+TapGestureDetector TapGestureDetector::DownCast( BaseHandle handle )
+{
+  return TapGestureDetector( dynamic_cast<Dali::Internal::TapGestureDetector*>(handle.GetObjectPtr()) );
+}
+
+TapGestureDetector::~TapGestureDetector()
+{
+}
+
+TapGestureDetector::TapGestureDetector(const TapGestureDetector& handle)
+: GestureDetector(handle)
+{
+}
+
+TapGestureDetector& TapGestureDetector::operator=(const TapGestureDetector& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void TapGestureDetector::SetMinimumTapsRequired(unsigned int taps)
+{
+  GetImplementation(*this).SetMinimumTapsRequired(taps);
+}
+
+void TapGestureDetector::SetMaximumTapsRequired(unsigned int taps)
+{
+  GetImplementation(*this).SetMaximumTapsRequired(taps);
+}
+
+unsigned int TapGestureDetector::GetMinimumTapsRequired() const
+{
+  return GetImplementation(*this).GetMinimumTapsRequired();
+}
+
+unsigned int TapGestureDetector::GetMaximumTapsRequired() const
+{
+  return GetImplementation(*this).GetMaximumTapsRequired();
+}
+
+TapGestureDetector::DetectedSignalType& TapGestureDetector::DetectedSignal()
+{
+  return GetImplementation(*this).DetectedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/tap-gesture-detector.h b/dali/public-api/events/tap-gesture-detector.h
new file mode 100644 (file)
index 0000000..7363678
--- /dev/null
@@ -0,0 +1,215 @@
+#ifndef __DALI_TAP_GESTURE_DETECTOR_H__
+#define __DALI_TAP_GESTURE_DETECTOR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture-detector.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class TapGestureDetector;
+}
+
+struct TapGesture;
+
+/**
+ * @brief This class emits a signal when a tap gesture occurs that meets the requirements set by the
+ * application.
+ *
+ * See TapGestureDetector::SetTapsRequired
+ *
+ * A Tap Gesture is a discrete gesture, which means it does not have any state information attached
+ * to it.  Please see TapGesture for more information.
+ *
+ * The application programmer can use this gesture detector as follows:
+ * @code
+ * TapGestureDetector detector = TapGestureDetector::New();
+ * detector.Attach(myActor);
+ * detector.DetectedSignal().Connect(this, &MyApplication::OnTap);
+ * @endcode
+ *
+ * @since_tizen 2.4
+ * @note Multi-touch taps are not currently supported. However, multiple taps (double & triple tap etc.) ARE supported.
+ *
+ * Signals
+ * | %Signal Name | Method                |
+ * |--------------|-----------------------|
+ * | tap-detected | @ref DetectedSignal() |
+ * @see TapGesture
+ *
+ */
+class DALI_IMPORT_API TapGestureDetector : public GestureDetector
+{
+public: // Typedefs
+
+  /**
+   * @brief Signal type for detected signal.
+   * @since_tizen 2.4
+   */
+  typedef Signal< void ( Actor, const TapGesture& ) > DetectedSignalType;
+
+public: // Creation & Destruction
+
+  /**
+   * @brief Create an uninitialized TapGestureDetector; this can be initialized with TapGestureDetector::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  TapGestureDetector();
+
+  /**
+   * @brief Create an initialized TapGestureDetector.
+   *
+   * By default, this would create a gesture detector which requires one tap with one touch.
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static TapGestureDetector New();
+
+  /**
+   * @brief Create an initialized TapGestureDetector with the specified parameters.
+   *
+   * @since_tizen 2.4
+   * @param[in]  tapsRequired     The minimum & maximum number of taps required.
+   * @return A handle to a newly allocated Dali resource.
+   */
+  static TapGestureDetector New( unsigned int tapsRequired );
+
+  /**
+   * @brief Downcast an Object handle to TapGestureDetector handle.
+   *
+   * If handle points to a TapGestureDetector object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a TapGestureDetector object or an uninitialized handle
+   */
+  static TapGestureDetector DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~TapGestureDetector();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  TapGestureDetector(const TapGestureDetector& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  TapGestureDetector& operator=(const TapGestureDetector& rhs);
+
+public: // Setters
+
+  /**
+   * @brief Set the minimum number of taps required.
+   *
+   * The tap count is the number of times a user should "tap" the screen.
+   * @since_tizen 2.4
+   * @param[in]  minimumTaps  The minimum taps required.
+   * @pre The gesture detector has been initialized.
+   * @note The default is '1'.
+   */
+  void SetMinimumTapsRequired( unsigned int minimumTaps );
+
+  /**
+   * @brief Set the maximum number of taps required.
+   *
+   * The tap count is the number of times a user should "tap" the screen.
+   * @since_tizen 2.4
+   * @param[in]  maximumTaps  The maximum taps required.
+   * @pre The gesture detector has been initialized.
+   * @note The default is '1'.
+   */
+  void SetMaximumTapsRequired( unsigned int maximumTaps );
+
+public: // Getters
+
+  /**
+   * @brief Retrieves the minimum number of taps required.
+   *
+   * @since_tizen 2.4
+   * @return The minimum taps required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMinimumTapsRequired() const;
+
+  /**
+   * @brief Retrieves the maximum number of taps required.
+   *
+   * @since_tizen 2.4
+   * @return The maximum taps required.
+   * @pre The gesture detector has been initialized.
+   */
+  unsigned int GetMaximumTapsRequired() const;
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when the specified tap is detected on the attached actor.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName( Actor actor, const TapGesture& gesture );
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The gesture detector has been initialized.
+   */
+  DetectedSignalType& DetectedSignal();
+
+public: // Not intended for Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in]  internal  A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL TapGestureDetector(Internal::TapGestureDetector* internal);
+};
+
+/**
+ * @}
+ */
+
+} // namespace Dali
+
+#endif // __DALI_TAP_GESTURE_DETECTOR_H__
diff --git a/dali/public-api/events/tap-gesture.cpp b/dali/public-api/events/tap-gesture.cpp
new file mode 100644 (file)
index 0000000..3d9fed6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/tap-gesture.h>
+
+namespace Dali
+{
+
+TapGesture::TapGesture()
+: Gesture(Gesture::Tap, Gesture::Clear),
+  numberOfTaps(1),
+  numberOfTouches(1)
+{
+}
+
+TapGesture::TapGesture( const TapGesture& rhs )
+: Gesture( rhs ),
+  numberOfTaps( rhs.numberOfTaps ),
+  numberOfTouches( rhs.numberOfTouches ),
+  screenPoint( rhs.screenPoint ),
+  localPoint( rhs.localPoint )
+{
+}
+
+TapGesture& TapGesture::operator=( const TapGesture& rhs )
+{
+  Gesture::operator=(rhs);
+  numberOfTaps = rhs.numberOfTaps;
+  numberOfTouches = rhs.numberOfTouches;
+  screenPoint = rhs.screenPoint;
+  localPoint = rhs.localPoint;
+
+  return *this;
+}
+
+TapGesture::~TapGesture()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/tap-gesture.h b/dali/public-api/events/tap-gesture.h
new file mode 100644 (file)
index 0000000..f85e387
--- /dev/null
@@ -0,0 +1,101 @@
+#ifndef __DALI_TAP_GESTURE_H__
+#define __DALI_TAP_GESTURE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/events/gesture.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief A TapGesture is emitted when the user taps the screen with the stated number of fingers a stated number of times.
+ *
+ * This is a discrete gesture so does not have any state information.
+ * @since_tizen 2.4
+ * @see TapGestureDetector
+ */
+struct DALI_IMPORT_API TapGesture : public Gesture
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Default Constructor
+   * @since_tizen 2.4
+   */
+  TapGesture();
+
+  /**
+   * @brief Copy constructor
+   * @since_tizen 2.4
+   */
+  TapGesture( const TapGesture& rhs );
+
+  /**
+   * @brief Assignment operator
+   * @since_tizen 2.4
+   */
+  TapGesture& operator=( const TapGesture& rhs );
+
+  /**
+   * @brief Virtual destructor
+   * @since_tizen 2.4
+   */
+  virtual ~TapGesture();
+
+  // Data
+
+  /**
+   * @brief The number of taps in this tap gesture.
+   */
+  unsigned int numberOfTaps;
+
+  /**
+   * @brief The number of touch points in this tap gesture, i.e. the number of fingers the user had on the
+   * screen to generate the tap gesture.
+   */
+  unsigned int numberOfTouches;
+
+  /**
+   * @brief This is the point, in screen coordinates, where the tap occurred.
+   *
+   * If a multi-touch tap, then this is the centroid of all the touch points.
+   */
+  Vector2 screenPoint;
+
+  /**
+   * @brief This is the point, in local actor coordinates, where the tap occurred.
+   *
+   * If a multi-touch tap, then this is the centroid of all the touch points.
+   * @return The point where tap has occurred (in local actor coordinates).
+   */
+  Vector2 localPoint;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_TAP_GESTURE_H__
diff --git a/dali/public-api/events/touch-event.cpp b/dali/public-api/events/touch-event.cpp
new file mode 100644 (file)
index 0000000..8090d74
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/touch-event.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+
+TouchEvent::TouchEvent()
+: time(0)
+{
+}
+
+TouchEvent::TouchEvent(unsigned long time)
+: time(time)
+{
+}
+
+TouchEvent::~TouchEvent()
+{
+}
+
+unsigned int TouchEvent::GetPointCount() const
+{
+  return points.size();
+}
+
+const TouchPoint& TouchEvent::GetPoint(unsigned int point) const
+{
+  DALI_ASSERT_ALWAYS( point < points.size() && "No point at index" );
+  return points[point];
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/touch-event.h b/dali/public-api/events/touch-event.h
new file mode 100644 (file)
index 0000000..050825f
--- /dev/null
@@ -0,0 +1,106 @@
+#ifndef __DALI_TOUCH_EVENT_H__
+#define __DALI_TOUCH_EVENT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief Touch events are a collection of touch points at a specific moment in time.
+ *
+ * When a multi-touch event occurs, each touch point represents the points that are currently being
+ * touched or the points where a touch has stopped.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API TouchEvent
+{
+  // Construction & Destruction
+
+  /**
+   * @brief Default constructor
+   * @since_tizen 2.4
+   */
+  TouchEvent();
+
+  /**
+   * @brief Constructor
+   * @since_tizen 2.4
+   * @param[in]  time  The time the event occurred
+   */
+  TouchEvent(unsigned long time);
+
+  /**
+   * @brief Destructor
+   * @since_tizen 2.4
+   */
+  ~TouchEvent();
+
+  // Data
+
+  /**
+   * @brief This is a container of points for this touch event.
+   *
+   * The first point in the set is always the
+   * primary touch point (i.e. the first point touched in a multi-touch event).
+   */
+  TouchPointContainer points;
+
+  /**
+   * @brief The time (in ms) that the touch event occurred.
+   */
+  unsigned long time;
+
+  // Convenience Methods
+
+  /**
+   * @brief Returns the total number of points in this TouchEvent.
+   *
+   * @since_tizen 2.4
+   * @return Total number of Points.
+   */
+  unsigned int GetPointCount() const;
+
+  /**
+   * @brief Returns a touch point at the index requested.
+   *
+   * The first point in the set is always the primary
+   * touch point (i.e. the first point touched in a multi-touch event).
+   * @since_tizen 2.4
+   * @param[in] point The index of the required Point.
+   * @return Point requested
+   * @note "point" should be less than the value returned by GetPointCount().
+   *       If out of range, then program asserts.
+   */
+  const TouchPoint& GetPoint(unsigned int point) const;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_TOUCH_EVENT_H__
diff --git a/dali/public-api/events/touch-point.cpp b/dali/public-api/events/touch-point.cpp
new file mode 100644 (file)
index 0000000..dbc588d
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/touch-point.h>
+
+namespace Dali
+{
+
+TouchPoint::TouchPoint(int id, State state, float screenX, float screenY)
+: deviceId(id),
+  state(state),
+  local(screenX, screenY),
+  screen(screenX, screenY)
+{
+}
+
+TouchPoint::TouchPoint(int id, State state, float screenX, float screenY, float localX, float localY)
+: deviceId(id),
+  state(state),
+  local(localX, localY),
+  screen(screenX, screenY)
+{
+}
+
+TouchPoint::~TouchPoint()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/touch-point.h b/dali/public-api/events/touch-point.h
new file mode 100644 (file)
index 0000000..695d814
--- /dev/null
@@ -0,0 +1,135 @@
+#ifndef __DALI_TOUCH_POINT_H__
+#define __DALI_TOUCH_POINT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief A TouchPoint represents a point on the screen that is currently being touched
+ * or where touch has stopped.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API TouchPoint
+{
+  // Enumerations
+
+  /**
+   * @brief Touch state
+   * @since_tizen 2.4
+   */
+  enum State
+  {
+    Started,        /**< Touch or hover started */
+    Finished,       /**< Touch or hover finished */
+    Down = Started, /**< Screen touched */
+    Up = Finished,  /**< Touch stopped */
+    Motion,         /**< Finger dragged or hovered */
+    Leave,          /**< Leave the boundary of an actor */
+    Stationary,     /**< No change from last event.  Useful when a multi-point event occurs where
+                         all points are sent but indicates that this particular point has not changed
+                         since the last time */
+    Interrupted,    /**< A system event has occurred which has interrupted the touch or hover event sequence. */
+    Last            /**< Number of states. */
+  };
+
+  // Construction & Destruction
+
+  /**
+   * @brief Constructor
+   *
+   * @since_tizen 2.4
+   * @param[in]  id       The touch device ID.
+   * @param[in]  state    The state.
+   * @param[in]  screenX  The X co-ordinate relative to the screen's origin.
+   * @param[in]  screenY  The Y co-ordinate relative to the screen's origin.
+   */
+  TouchPoint(int id, State state, float screenX, float screenY);
+
+  /**
+   * @brief Constructor
+   *
+   * @since_tizen 2.4
+   * @param[in]  id       The touch device ID.
+   * @param[in]  state    The state.
+   * @param[in]  screenX  The X co-ordinate relative to the screen's origin.
+   * @param[in]  screenY  The Y co-ordinate relative to the screen's origin.
+   * @param[in]  localX   The X co-ordinate relative to the top-left (0.0, 0.0, 0.5) of the actor.
+   * @param[in]  localY   The Y co-ordinate relative to the top-left (0.0, 0.0, 0.5) of the actor.
+   */
+  TouchPoint(int id, State state, float screenX, float screenY, float localX, float localY);
+
+  /**
+   * @brief Destructor
+   * @since_tizen 2.4
+   */
+  ~TouchPoint();
+
+  // Data
+
+  /**
+   * @brief Each touch point has a unique device ID which specifies the touch device for that point.
+   */
+  int deviceId;
+
+  /**
+   * @brief State of the point.
+   *
+   * @see State
+   */
+  State state;
+
+  /**
+   * @brief The actor that was underneath the touch point.
+   */
+  Actor hitActor;
+
+  /**
+   * @brief The co-ordinates relative to the top-left of the hit-actor.
+   *
+   * @note The top-left of an actor is (0.0, 0.0, 0.5).
+   * @note If you require the local coordinates of another actor (e.g the parent of the hit actor),
+   * then you should use Actor::ScreenToLocal().
+   */
+  Vector2 local;
+
+  /**
+   * @brief The co-ordinates relative to the top-left of the screen.
+   */
+  Vector2 screen;
+};
+
+typedef std::vector<TouchPoint> TouchPointContainer; ///< Container of touch points.
+typedef TouchPointContainer::iterator TouchPointContainerIterator; ///< Iterator for Dali::TouchPointContainer
+typedef TouchPointContainer::const_iterator TouchPointContainerConstIterator; ///< Const iterator for Dali::TouchPointContainer
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_TOUCH_POINT_H__
diff --git a/dali/public-api/events/wheel-event.cpp b/dali/public-api/events/wheel-event.cpp
new file mode 100644 (file)
index 0000000..5bbb271
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/events/wheel-event.h>
+
+namespace Dali
+{
+
+namespace
+{
+const unsigned int MODIFIER_SHIFT = 0x1;
+const unsigned int MODIFIER_CTRL  = 0x2;
+const unsigned int MODIFIER_ALT   = 0x4;
+
+}
+
+WheelEvent::WheelEvent()
+: type( MOUSE_WHEEL ),
+  direction( 0 ),
+  modifiers( 0 ),
+  point( Vector2::ZERO ),
+  z( 0 ),
+  timeStamp( 0 )
+{
+}
+
+WheelEvent::WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp )
+: type( type ),
+  direction( direction ),
+  modifiers( modifiers ),
+  point( point ),
+  z( z ),
+  timeStamp( timeStamp )
+{
+}
+
+WheelEvent::~WheelEvent()
+{
+}
+
+bool WheelEvent::IsShiftModifier() const
+{
+  if ((MODIFIER_SHIFT & modifiers) == MODIFIER_SHIFT)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool WheelEvent::IsCtrlModifier() const
+{
+  if ((MODIFIER_CTRL & modifiers) == MODIFIER_CTRL)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+bool WheelEvent::IsAltModifier() const
+{
+  if ((MODIFIER_ALT & modifiers) == MODIFIER_ALT)
+  {
+    return true;
+  }
+
+  return false;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/events/wheel-event.h b/dali/public-api/events/wheel-event.h
new file mode 100644 (file)
index 0000000..3c8f875
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef __DALI_WHEEL_EVENT_H__
+#define __DALI_WHEEL_EVENT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_events
+ * @{
+ */
+
+/**
+ * @brief The wheel event structure is used to store a wheel rolling, it facilitates
+ * processing of the wheel rolling and passing to other libraries like Toolkit.
+ *
+ * There is a key modifier which relates to keys like alt, shift and control functions are
+ * supplied to check if they have been pressed when the wheel is being rolled.
+ *
+ * We support a mouse device and there may be another custom device that support the wheel event. The device type is specified as \e type.
+ * The mouse wheel event can be sent to the specific actor but the custom wheel event will be sent to the stage.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API WheelEvent
+{
+  // Enumerations
+
+  /**
+   * @brief Specifies the type of the wheel event.
+   * @since_tizen 2.4
+   */
+  enum Type
+  {
+    MOUSE_WHEEL,      ///< Mouse wheel event
+    CUSTOM_WHEEL      ///< Custom wheel event
+  };
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  WheelEvent();
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in]  type       The type of the wheel event
+   * @param[in]  direction  The direction of wheel rolling (0 = default vertical wheel, 1 = horizontal wheel)
+   * @param[in]  modifiers  modifier keys pressed during the event (such as shift, alt and control)
+   * @param[in]  point      The co-ordinates of the cursor relative to the top-left of the screen.
+   * @param[in]  z          The offset of rolling (positive value means roll down or clockwise, and negative value means roll up or counter-clockwise)
+   * @param[in]  timeStamp  The time the wheel is being rolled.
+   */
+  WheelEvent( Type type, int direction, unsigned int modifiers, Vector2 point, int z, unsigned int timeStamp );
+
+  /**
+   * @brief Destructor.
+   * @since_tizen 2.4
+   */
+  ~WheelEvent();
+
+  /**
+   * @brief Check to see if Shift key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if shift modifier
+   */
+  bool IsShiftModifier() const;
+
+  /**
+   * @brief Check to see if Ctrl (control) key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if ctrl modifier
+   */
+  bool IsCtrlModifier() const;
+
+  /**
+   * @brief Check to see if Alt key modifier has been supplied.
+   *
+   * @since_tizen 2.4
+   * @return bool true if alt modifier
+   */
+  bool IsAltModifier() const;
+
+  // Data
+
+  /**
+   * @brief Type of the event
+   *
+   * @see Type
+   */
+  Type type;
+
+  /**
+   * @brief The direction in which the wheel is being rolled.
+   *
+   * 0 means the default vertical wheel, and 1 means horizontal wheel
+   */
+  int direction;
+
+  /**
+   * @brief Modifier keys pressed during the event (such as shift, alt and control).
+   */
+  unsigned int modifiers;
+
+  /**
+   * @brief The co-ordinates of the cursor relative to the top-left of the screen
+   * when the wheel is being rolled.
+   */
+  Vector2 point;
+
+  /**
+   * @brief The offset of the wheel rolling, where positive value means rolling down or clockwise
+   * and negative value means rolling up or counter-clockwise.
+   */
+  int z;
+
+  /**
+   * @brief The time when the wheel is being rolled.
+   */
+  unsigned int timeStamp;
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_WHEEL_EVENT_H__
diff --git a/dali/public-api/file.list b/dali/public-api/file.list
new file mode 100644 (file)
index 0000000..4cdf643
--- /dev/null
@@ -0,0 +1,213 @@
+#
+# Add public-api source files here
+#
+
+public_api_src_files = \
+  $(public_api_src_dir)/actors/actor.cpp \
+  $(public_api_src_dir)/actors/blending.cpp \
+  $(public_api_src_dir)/actors/camera-actor.cpp \
+  $(public_api_src_dir)/actors/custom-actor.cpp \
+  $(public_api_src_dir)/actors/custom-actor-impl.cpp \
+  $(public_api_src_dir)/actors/image-actor.cpp \
+  $(public_api_src_dir)/actors/layer.cpp \
+  $(public_api_src_dir)/animation/animation.cpp \
+  $(public_api_src_dir)/animation/alpha-function.cpp \
+  $(public_api_src_dir)/animation/constraint.cpp \
+  $(public_api_src_dir)/animation/constraint-source.cpp \
+  $(public_api_src_dir)/animation/key-frames.cpp \
+  $(public_api_src_dir)/animation/linear-constrainer.cpp \
+  $(public_api_src_dir)/animation/path.cpp \
+  $(public_api_src_dir)/animation/time-period.cpp \
+  $(public_api_src_dir)/common/constants.cpp \
+  $(public_api_src_dir)/common/dali-common.cpp \
+  $(public_api_src_dir)/common/dali-vector.cpp \
+  $(public_api_src_dir)/common/stage.cpp \
+  $(public_api_src_dir)/events/gesture.cpp \
+  $(public_api_src_dir)/events/gesture-detector.cpp \
+  $(public_api_src_dir)/events/hover-event.cpp \
+  $(public_api_src_dir)/events/key-event.cpp \
+  $(public_api_src_dir)/events/long-press-gesture.cpp \
+  $(public_api_src_dir)/events/long-press-gesture-detector.cpp \
+  $(public_api_src_dir)/events/wheel-event.cpp \
+  $(public_api_src_dir)/events/pan-gesture.cpp \
+  $(public_api_src_dir)/events/pan-gesture-detector.cpp \
+  $(public_api_src_dir)/events/pinch-gesture.cpp \
+  $(public_api_src_dir)/events/pinch-gesture-detector.cpp \
+  $(public_api_src_dir)/events/tap-gesture.cpp \
+  $(public_api_src_dir)/events/tap-gesture-detector.cpp \
+  $(public_api_src_dir)/events/touch-point.cpp \
+  $(public_api_src_dir)/events/touch-event.cpp \
+  $(public_api_src_dir)/images/image.cpp \
+  $(public_api_src_dir)/images/pixel.cpp \
+  $(public_api_src_dir)/images/buffer-image.cpp \
+  $(public_api_src_dir)/images/frame-buffer-image.cpp \
+  $(public_api_src_dir)/images/encoded-buffer-image.cpp \
+  $(public_api_src_dir)/images/nine-patch-image.cpp \
+  $(public_api_src_dir)/images/resource-image.cpp \
+  $(public_api_src_dir)/images/native-image.cpp \
+  $(public_api_src_dir)/math/compile-time-math.cpp \
+  $(public_api_src_dir)/math/degree.cpp \
+  $(public_api_src_dir)/math/matrix.cpp \
+  $(public_api_src_dir)/math/matrix3.cpp \
+  $(public_api_src_dir)/math/quaternion.cpp \
+  $(public_api_src_dir)/math/vector2.cpp \
+  $(public_api_src_dir)/math/vector3.cpp \
+  $(public_api_src_dir)/math/vector4.cpp \
+  $(public_api_src_dir)/object/any.cpp \
+  $(public_api_src_dir)/object/base-handle.cpp \
+  $(public_api_src_dir)/object/handle.cpp \
+  $(public_api_src_dir)/object/base-object.cpp \
+  $(public_api_src_dir)/object/object-registry.cpp \
+  $(public_api_src_dir)/object/property.cpp \
+  $(public_api_src_dir)/object/property-array.cpp \
+  $(public_api_src_dir)/object/property-conditions.cpp \
+  $(public_api_src_dir)/object/property-input.cpp \
+  $(public_api_src_dir)/object/property-map.cpp \
+  $(public_api_src_dir)/object/property-notification.cpp \
+  $(public_api_src_dir)/object/property-types.cpp \
+  $(public_api_src_dir)/object/property-value.cpp \
+  $(public_api_src_dir)/object/ref-object.cpp \
+  $(public_api_src_dir)/render-tasks/render-task.cpp \
+  $(public_api_src_dir)/render-tasks/render-task-list.cpp \
+  $(public_api_src_dir)/shader-effects/shader-effect.cpp \
+  $(public_api_src_dir)/signals/callback.cpp \
+  $(public_api_src_dir)/signals/connection-tracker.cpp \
+  $(public_api_src_dir)/signals/connection-tracker-interface.cpp \
+  $(public_api_src_dir)/signals/signal-slot-connections.cpp \
+  $(public_api_src_dir)/signals/signal-slot-observers.cpp \
+  $(public_api_src_dir)/signals/base-signal.cpp \
+  $(public_api_src_dir)/signals/functor-delegate.cpp \
+  $(public_api_src_dir)/object/type-info.cpp \
+  $(public_api_src_dir)/object/type-registry.cpp \
+  $(public_api_src_dir)/dali-core-version.cpp
+
+
+#
+# Add public header files here
+#
+
+public_api_header_files = \
+  $(public_api_src_dir)/dali-core.h \
+  $(public_api_src_dir)/dali-core-version.h
+
+public_api_core_actors_header_files =  \
+  $(public_api_src_dir)/actors/actor.h \
+  $(public_api_src_dir)/actors/actor-enumerations.h \
+  $(public_api_src_dir)/actors/blending.h \
+  $(public_api_src_dir)/actors/camera-actor.h \
+  $(public_api_src_dir)/actors/custom-actor.h \
+  $(public_api_src_dir)/actors/custom-actor-impl.h \
+  $(public_api_src_dir)/actors/draw-mode.h \
+  $(public_api_src_dir)/actors/image-actor.h \
+  $(public_api_src_dir)/actors/layer.h \
+  $(public_api_src_dir)/actors/sampling.h
+
+public_api_core_animation_header_files = \
+  $(public_api_src_dir)/animation/alpha-function.h \
+  $(public_api_src_dir)/animation/animation.h \
+  $(public_api_src_dir)/animation/constraint.h \
+  $(public_api_src_dir)/animation/constraints.h \
+  $(public_api_src_dir)/animation/constraint-source.h \
+  $(public_api_src_dir)/animation/key-frames.h \
+  $(public_api_src_dir)/animation/linear-constrainer.h \
+  $(public_api_src_dir)/animation/path.h \
+  $(public_api_src_dir)/animation/time-period.h
+
+public_api_core_common_header_files = \
+  $(public_api_src_dir)/common/compile-time-assert.h \
+  $(public_api_src_dir)/common/constants.h \
+  $(public_api_src_dir)/common/dali-common.h \
+  $(public_api_src_dir)/common/dali-vector.h \
+  $(public_api_src_dir)/common/intrusive-ptr.h \
+  $(public_api_src_dir)/common/loading-state.h \
+  $(public_api_src_dir)/common/stage.h \
+  $(public_api_src_dir)/common/type-traits.h \
+  $(public_api_src_dir)/common/vector-wrapper.h \
+  $(public_api_src_dir)/common/view-mode.h
+
+public_api_core_events_header_files = \
+  $(public_api_src_dir)/events/gesture.h \
+  $(public_api_src_dir)/events/gesture-detector.h \
+  $(public_api_src_dir)/events/hover-event.h \
+  $(public_api_src_dir)/events/key-event.h \
+  $(public_api_src_dir)/events/long-press-gesture.h \
+  $(public_api_src_dir)/events/long-press-gesture-detector.h \
+  $(public_api_src_dir)/events/wheel-event.h \
+  $(public_api_src_dir)/events/pan-gesture.h \
+  $(public_api_src_dir)/events/pan-gesture-detector.h \
+  $(public_api_src_dir)/events/pinch-gesture.h \
+  $(public_api_src_dir)/events/pinch-gesture-detector.h \
+  $(public_api_src_dir)/events/tap-gesture.h \
+  $(public_api_src_dir)/events/tap-gesture-detector.h \
+  $(public_api_src_dir)/events/touch-point.h \
+  $(public_api_src_dir)/events/touch-event.h
+
+public_api_core_images_header_files = \
+  $(public_api_src_dir)/images/buffer-image.h \
+  $(public_api_src_dir)/images/encoded-buffer-image.h \
+  $(public_api_src_dir)/images/frame-buffer-image.h \
+  $(public_api_src_dir)/images/image.h \
+  $(public_api_src_dir)/images/image-operations.h \
+  $(public_api_src_dir)/images/nine-patch-image.h \
+  $(public_api_src_dir)/images/pixel.h \
+  $(public_api_src_dir)/images/resource-image.h \
+  $(public_api_src_dir)/images/native-image.h \
+  $(public_api_src_dir)/images/native-image-interface.h
+
+public_api_core_math_header_files = \
+  $(public_api_src_dir)/math/angle-axis.h \
+  $(public_api_src_dir)/math/compile-time-math.h \
+  $(public_api_src_dir)/math/degree.h \
+  $(public_api_src_dir)/math/math-utils.h \
+  $(public_api_src_dir)/math/matrix.h \
+  $(public_api_src_dir)/math/matrix3.h \
+  $(public_api_src_dir)/math/quaternion.h \
+  $(public_api_src_dir)/math/radian.h \
+  $(public_api_src_dir)/math/random.h \
+  $(public_api_src_dir)/math/rect.h \
+  $(public_api_src_dir)/math/uint-16-pair.h \
+  $(public_api_src_dir)/math/vector2.h \
+  $(public_api_src_dir)/math/vector3.h \
+  $(public_api_src_dir)/math/vector4.h \
+  $(public_api_src_dir)/math/viewport.h
+
+public_api_core_object_header_files = \
+  $(public_api_src_dir)/object/any.h \
+  $(public_api_src_dir)/object/base-handle.h \
+  $(public_api_src_dir)/object/base-object.h \
+  $(public_api_src_dir)/object/handle.h \
+  $(public_api_src_dir)/object/object-registry.h \
+  $(public_api_src_dir)/object/property-array.h \
+  $(public_api_src_dir)/object/property-conditions.h \
+  $(public_api_src_dir)/object/property-index-ranges.h \
+  $(public_api_src_dir)/object/property-input.h \
+  $(public_api_src_dir)/object/property-map.h \
+  $(public_api_src_dir)/object/property-notification-declarations.h \
+  $(public_api_src_dir)/object/property-notification.h \
+  $(public_api_src_dir)/object/property-types.h \
+  $(public_api_src_dir)/object/property-value.h \
+  $(public_api_src_dir)/object/property.h \
+  $(public_api_src_dir)/object/ref-object.h \
+  $(public_api_src_dir)/object/type-info.h \
+  $(public_api_src_dir)/object/type-registry.h
+
+public_api_core_render_tasks_header_files = \
+  $(public_api_src_dir)/render-tasks/render-task.h \
+  $(public_api_src_dir)/render-tasks/render-task-list.h
+
+public_api_core_shader_effects_header_files = \
+  $(public_api_src_dir)/shader-effects/shader-effect.h
+
+public_api_core_size_negotiation_header_files = \
+  $(public_api_src_dir)/size-negotiation/relayout-container.h
+
+public_api_core_signals_header_files = \
+  $(public_api_src_dir)/signals/base-signal.h \
+  $(public_api_src_dir)/signals/callback.h \
+  $(public_api_src_dir)/signals/connection-tracker-interface.h \
+  $(public_api_src_dir)/signals/connection-tracker.h \
+  $(public_api_src_dir)/signals/dali-signal.h \
+  $(public_api_src_dir)/signals/functor-delegate.h \
+  $(public_api_src_dir)/signals/signal-slot-connections.h \
+  $(public_api_src_dir)/signals/signal-slot-observers.h \
+  $(public_api_src_dir)/signals/slot-delegate.h
diff --git a/dali/public-api/images/buffer-image.cpp b/dali/public-api/images/buffer-image.cpp
new file mode 100644 (file)
index 0000000..1bd44f5
--- /dev/null
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/buffer-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/event/images/buffer-image-impl.h>
+
+namespace Dali
+{
+
+BufferImage::BufferImage()
+{
+}
+
+BufferImage::BufferImage(Internal::BufferImage* internal)
+  : Image(internal)
+{
+}
+
+BufferImage BufferImage::DownCast( BaseHandle handle )
+{
+  return BufferImage( dynamic_cast<Dali::Internal::BufferImage*>(handle.GetObjectPtr()) );
+}
+
+BufferImage::~BufferImage()
+{
+}
+
+BufferImage::BufferImage(const BufferImage& handle)
+: Image(handle)
+{
+}
+
+BufferImage& BufferImage::operator=(const BufferImage& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+const BufferImage BufferImage::WHITE()
+{
+  Internal::BufferImage* internal = new Internal::BufferImage(1,1,Pixel::RGBA8888, Dali::Image::NEVER);
+  PixelBuffer* pBuf = internal->GetBuffer();
+  if ( pBuf )
+  {
+    pBuf[0] = pBuf[1] = pBuf[2] = pBuf[3] = 0xFF;
+  }
+  return BufferImage(internal);
+}
+
+BufferImage BufferImage::New(unsigned int width, unsigned int height, Pixel::Format pixelformat)
+{
+  DALI_ASSERT_ALWAYS( 0u != width  && "Invalid BufferImage width requested" );
+  DALI_ASSERT_ALWAYS( 0u != height && "Invalid BufferImage height requested" );
+
+  Internal::BufferImagePtr internal = Internal::BufferImage::New(width, height, pixelformat);
+  return BufferImage(internal.Get());
+}
+
+BufferImage BufferImage::New(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePol)
+{
+  DALI_ASSERT_ALWAYS( 0u != width  && "Invalid BufferImage width requested" );
+  DALI_ASSERT_ALWAYS( 0u != height && "Invalid BufferImage height requested" );
+
+  Internal::BufferImagePtr internal = Internal::BufferImage::New(width, height, pixelformat, releasePol);
+  return BufferImage(internal.Get());
+}
+
+BufferImage BufferImage::New(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride)
+{
+  DALI_ASSERT_ALWAYS( 0u != width  && "Invalid BufferImage width requested" );
+  DALI_ASSERT_ALWAYS( 0u != height && "Invalid BufferImage height requested" );
+
+  Internal::BufferImagePtr internal = Internal::BufferImage::New(pixBuf, width, height, pixelformat, stride);
+  return BufferImage(internal.Get());
+}
+
+BufferImage BufferImage::New(PixelBuffer* pixBuf, unsigned int width, unsigned int height, Pixel::Format pixelformat, unsigned int stride, ReleasePolicy releasePol)
+{
+  DALI_ASSERT_ALWAYS( 0u != width  && "Invalid BufferImage width requested" );
+  DALI_ASSERT_ALWAYS( 0u != height && "Invalid BufferImage height requested" );
+  Internal::BufferImagePtr internal = Internal::BufferImage::New(pixBuf, width, height, pixelformat, stride, releasePol);
+  return BufferImage(internal.Get());
+}
+
+PixelBuffer* BufferImage::GetBuffer()
+{
+  return GetImplementation(*this).GetBuffer();
+}
+
+unsigned int BufferImage::GetBufferSize() const
+{
+  return GetImplementation(*this).GetBufferSize();
+}
+
+unsigned int BufferImage::GetBufferStride() const
+{
+  return GetImplementation(*this).GetBufferStride();
+}
+
+Pixel::Format BufferImage::GetPixelFormat() const
+{
+  return GetImplementation(*this).GetPixelFormat();
+}
+
+void BufferImage::Update ()
+{
+  RectArea area;
+  GetImplementation(*this).Update(area);
+}
+
+void BufferImage::Update (RectArea updateArea)
+{
+  GetImplementation(*this).Update(updateArea);
+}
+
+bool BufferImage::IsDataExternal() const
+{
+  return GetImplementation(*this).IsDataExternal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/buffer-image.h b/dali/public-api/images/buffer-image.h
new file mode 100644 (file)
index 0000000..46442b8
--- /dev/null
@@ -0,0 +1,314 @@
+#ifndef __DALI_BUFFER_IMAGE_H__
+#define __DALI_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/pixel.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class BufferImage;
+}
+
+typedef unsigned char         PixelBuffer;  ///< pixel data buffer
+typedef Rect<unsigned int>    RectArea;     ///< rectangular area (x,y,w,h)
+
+
+/**
+ * @brief BufferImage represents an image resource that can be added to ImageViews.
+ * Its pixel buffer data is provided by the application developer.
+ *
+ * Care should be taken with pixel data allocated by the application,
+ * as the data is copied to GL both when the image is added to the
+ * stage and after a call to Update().  In both of these cases, a
+ * SignalUploaded will be sent to the application confirming that the
+ * operation has completed.
+ *
+ * The application can free the pixel data after receiving a
+ * SignalUploaded.
+ *
+ * Similarly, once the image is on stage (i.e. it's being used by an
+ * ImageView that is on stage), the application should only write to
+ * the buffer after receiving a SignalUploaded, then call Update()
+ * once the write is finished. This avoids the pixel data being changed
+ * whilst it's being copied to GL. Writing to the buffer without waiting
+ * for the signal will likely result in visible tearing.
+ *
+ * If the pixel format of the pixel buffer contains an alpha channel,
+ * then the image is considered to be have transparent pixels without
+ * regard for the actual content of the channel, and will be blended.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API BufferImage : public Image
+{
+public:
+  /**
+   * @brief Constructor which creates an uninitialized BufferImage object.
+   *
+   * Use BufferImage::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  BufferImage();
+
+  /**
+   * @brief Create a new BufferImage.
+   *
+   * Also a pixel buffer for image data is allocated.
+   * Dali has ownership of the buffer.
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @note: default resource management policies are Immediate and Never
+   *
+   * @since_tizen 2.4
+   * @param [in] width       image width in pixels
+   * @param [in] height      image height in pixels
+   * @param [in] pixelformat the pixel format (rgba 32 bit by default)
+   * @return a handle to a new instance of BufferImage
+   * @pre width & height are greater than zero
+   */
+  static BufferImage New(unsigned int width,
+                         unsigned int height,
+                         Pixel::Format pixelformat=Pixel::RGBA8888);
+
+  /**
+   * @brief Create a new BufferImage.
+   *
+   * Also a pixel buffer for image data is allocated.
+   * Dali has ownership of the buffer.
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   *
+   * @since_tizen 2.4
+   * @param [in] width          Image width in pixels
+   * @param [in] height         Image height in pixels
+   * @param [in] pixelFormat    The pixel format
+   * @param [in] releasePolicy  Optionally release memory when image is not visible on screen.
+   * @return a handle to a new instance of BufferImage
+   * @pre width & height are greater than zero
+   */
+  static BufferImage New(unsigned int  width,
+                         unsigned int  height,
+                         Pixel::Format pixelFormat,
+                         ReleasePolicy releasePolicy);
+
+  /**
+   * @brief Create a new BufferImage, which uses an external data source.
+   *
+   * The PixelBuffer has to be allocated by application.
+   *
+   * The application holds ownership of the buffer. It must not
+   * destroy the PixelBuffer on a staged image if it has called
+   * Update() and hasn't received a SignalUploaded, or if it has just
+   * added it to the stage and has not received a SignalUploaded.
+   *
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   *
+   * @since_tizen 2.4
+   * @param [in] pixelBuffer  pixel buffer. has to be allocated by application.
+   * @param [in] width        image width in pixels
+   * @param [in] height       image height in pixels
+   * @param [in] pixelFormat  the pixel format (rgba 32 bit by default)
+   * @param [in] stride       the internal stride of the pixelbuffer in pixels
+   * @return a handle to a new instance of BufferImage
+   * @pre width & height are greater than zero
+   */
+  static BufferImage New(PixelBuffer*  pixelBuffer,
+                         unsigned int  width,
+                         unsigned int  height,
+                         Pixel::Format pixelFormat=Pixel::RGBA8888,
+                         unsigned int  stride=0);
+
+  /**
+   * @brief Create a new BufferImage, which uses an external data source.
+   *
+   * The PixelBuffer has to be allocated by application.
+   *
+   * The application holds ownership of the buffer. It must not
+   * destroy the PixelBuffer on a staged image if it has called
+   * Update() and hasn't received a SignalUploaded, or if it has just
+   * added it to the stage and has not received a SignalUploaded.
+   *
+   * For better performance and portability use power of two dimensions.
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   *
+   * @since_tizen 2.4
+   * @param [in] pixelBuffer   pixel buffer. has to be allocated by application.
+   * @param [in] width         image width in pixels
+   * @param [in] height        image height in pixels
+   * @param [in] pixelFormat   the pixel format
+   * @param [in] stride        the internal stride of the pixelbuffer in pixels
+   * @param [in] releasePolicy optionally relase memory when image is not visible on screen.
+   * @return a handle to a new instance of BufferImage
+   * @pre width & height are greater than zero
+   * @note in case releasePolicy is "Unused", application has to call
+   * BufferImage::Update() whenever image is re-added to the stage
+   *
+   */
+  static BufferImage New(PixelBuffer*  pixelBuffer,
+                         unsigned int  width,
+                         unsigned int  height,
+                         Pixel::Format pixelFormat,
+                         unsigned int  stride,
+                         ReleasePolicy releasePolicy);
+
+  /**
+   * @brief Downcast an Object handle to BufferImage.
+   *
+   * If handle points to a BufferImage the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a BufferImage or an uninitialized handle
+   */
+  static BufferImage DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~BufferImage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  BufferImage(const BufferImage& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  BufferImage& operator=(const BufferImage& rhs);
+
+  /**
+   * @brief White pixel as image data.
+   *
+   * Can be used to create solid color actors.
+   * @since_tizen 2.4
+   * @return 1 white pixel with 32 bit colordepth
+   */
+  static const BufferImage WHITE();
+
+public:
+  /**
+   * @brief Returns the pixel buffer of the Image.
+   *
+   * The application can write to the buffer to modify its contents.
+   *
+   * Whilst the image is on stage, after writing to the buffer the
+   * application should call Update() and wait for the
+   * SignalUploaded() method before writing again.
+   *
+   * @since_tizen 2.4
+   * @return the pixel buffer
+   */
+  PixelBuffer* GetBuffer();
+
+  /**
+   * @brief Returns buffer size in bytes.
+   *
+   * @since_tizen 2.4
+   * @return the buffer size in bytes
+   */
+  unsigned int GetBufferSize() const;
+
+  /**
+   * @brief Returns buffer stride (in bytes).
+   *
+   * @since_tizen 2.4
+   * @return the buffer stride
+   */
+  unsigned int GetBufferStride() const;
+
+  /**
+   * @brief Returns the pixel format of the contained buffer
+   *
+   * @since_tizen 2.4
+   * @return the pixel format
+   */
+  Pixel::Format GetPixelFormat() const;
+
+  /**
+   * @brief Inform Dali that the contents of the buffer have changed.
+   *
+   * SignalUploaded will be sent in response if the image is on stage
+   * and the image data has been successfully copied to graphics
+   * memory. To avoid visual tearing, the application should wait for
+   * the SignalUploaded before modifying the data.
+   *
+   * The application must not destroy an external PixelBuffer on a staged
+   * image after calling this method until the SignalUploaded has been
+   * successfully received.
+   *
+   * @note: BufferImage::Update might not work with BGR/BGRA formats!
+   * @note: Some GPUs may not support Non power of two buffer updates (for
+   * example C110/SGX540)
+   * @since_tizen 2.4
+   */
+  void Update();
+
+  /**
+   * @copydoc Update()
+   * @param [in] updateArea area that has changed in buffer
+   */
+  void Update( RectArea updateArea );
+
+  /**
+   * @brief Returns whether BufferImage uses external data source or not.
+   *
+   * If not, dali holds ownership of the PixelBuffer, otherwise the application
+   * is responsible for freeing it.
+   *
+   * The application must not destroy an external PixelBuffer on a staged image
+   * if it has called Update() and hasn't received a SignalUploaded.
+   *
+   * @since_tizen 2.4
+   * @return true if application owns data, false otherwise
+   */
+  bool IsDataExternal() const;
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL BufferImage(Internal::BufferImage*);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_BUFFER_IMAGE_H__
diff --git a/dali/public-api/images/encoded-buffer-image.cpp b/dali/public-api/images/encoded-buffer-image.cpp
new file mode 100644 (file)
index 0000000..5c53e14
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/encoded-buffer-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/internal/common/image-attributes.h>
+#include <dali/internal/event/images/encoded-buffer-image-impl.h>
+
+namespace Dali
+{
+
+EncodedBufferImage::EncodedBufferImage()
+{
+}
+
+EncodedBufferImage::EncodedBufferImage(Internal::EncodedBufferImage* internal)
+  : Image(internal)
+{
+}
+
+EncodedBufferImage EncodedBufferImage::New( const uint8_t * const encodedImage,
+                                            std::size_t encodedImageByteCount,
+                                            ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode,
+                                            ReleasePolicy releasePol,
+                                            bool orientationCorrection )
+{
+  Internal::EncodedBufferImagePtr internal = Internal::EncodedBufferImage::New( encodedImage, encodedImageByteCount, size, fittingMode, samplingMode, orientationCorrection, releasePol );
+  EncodedBufferImage image(internal.Get());
+  return image;
+}
+
+EncodedBufferImage EncodedBufferImage::New( const uint8_t * const encodedImage, const std::size_t encodedImageByteCount )
+{
+  ImageDimensions size(0, 0);
+  FittingMode::Type fittingMode = FittingMode::DEFAULT;
+  SamplingMode::Type samplingMode = SamplingMode::DEFAULT;
+  Internal::EncodedBufferImagePtr internal = Internal::EncodedBufferImage::New( encodedImage, encodedImageByteCount, size, fittingMode, samplingMode, true, Dali::Image::NEVER );
+  EncodedBufferImage image( internal.Get() );
+  return image;
+}
+
+EncodedBufferImage EncodedBufferImage::DownCast( BaseHandle handle )
+{
+  return EncodedBufferImage( dynamic_cast<Dali::Internal::EncodedBufferImage*>(handle.GetObjectPtr()) );
+}
+
+EncodedBufferImage::~EncodedBufferImage()
+{
+}
+
+EncodedBufferImage::EncodedBufferImage( const EncodedBufferImage& handle )
+: Image(handle)
+{
+}
+
+EncodedBufferImage& EncodedBufferImage::operator=( const EncodedBufferImage& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/encoded-buffer-image.h b/dali/public-api/images/encoded-buffer-image.h
new file mode 100644 (file)
index 0000000..85354cd
--- /dev/null
@@ -0,0 +1,170 @@
+#ifndef __DALI_ENCODED_BUFFER_IMAGE_H__
+#define __DALI_ENCODED_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/image-operations.h>
+#include <dali/public-api/math/uint-16-pair.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class EncodedBufferImage;
+}
+
+typedef Uint16Pair ImageDimensions;
+
+
+/**
+ * @brief EncodedBufferImage represents an image resource that can be added to
+ * ImageViews.
+ *
+ * A memory buffer of encoded image data is provided by the application and
+ * decoded asynchronously on a background thread to fill the image's
+ * pixel data.
+ *
+ * The buffer of data provided to an EncodedBufferImage factory function
+ * (New) should be filled with encoded image data in one of %Dali's
+ * supported image file formats, with the sequence of bytes in the buffer
+ * exactly matching the sequence of bytes that a file in the file system
+ * holding the encoded image data would have.
+ *
+ * The application may free the encoded image buffer passed to one of the
+ * New() static factory member functions as soon as they return.
+ *
+ * <h3> Signals </h3>
+ *
+ * Image::LoadingFinishedSignal is emitted when the decoding of the
+ * image data is completed, either successfully or not.
+ *
+ * Image::UploadedSignal is emitted when the decoded image data gets
+ * uploaded to the OpenGL ES implementation.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API EncodedBufferImage : public Image
+{
+public:
+  /**
+   * @brief Constructor which creates an uninitialized EncodedBufferImage object.
+   *
+   * Use Image::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  EncodedBufferImage();
+
+  /**
+   * @brief Create an initialised image object from an encoded image buffer in memory.
+   *
+   * The image will be created eagerly using LoadPolicy::Immediate.
+   * The function is non-blocking and returns immediately while the image
+   * decoding happens on a background thread.
+   * @since_tizen 2.4
+   * @param [in] encodedImage The encoded bytes of an image, in a supported
+   * image format such as PNG, JPEG, GIF, BMP, KTX, ICO, and WBMP, organised
+   * exactly as it would be as a file in the filesystem.
+   * The caller retains ownership of this buffer and is free to modify or
+   * discard it as soon as the function returns.
+   * @param [in] encodedImageByteCount The size in bytes of the buffer pointed to
+   * by encodedImage.
+   * @param [in] size The width and height to fit the loaded image to.
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
+   * @param [in] releasePol The ReleasePolicy to apply to Image. If the Unused
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * policy is set, a reload will not be possible, so the Image should never be
+   * used once all actors using it have gone off-stage.
+   * @return A handle to a newly allocated object.
+   */
+  static EncodedBufferImage New( const uint8_t * const encodedImage, std::size_t encodedImageByteCount, ImageDimensions size, FittingMode::Type fittingMode, SamplingMode::Type samplingMode, ReleasePolicy releasePol = Image::NEVER, bool orientationCorrection = true );
+
+  /**
+   * @brief Create an initialised image object from an encoded image buffer in memory.
+   *
+   * The image will be created eagerly using LoadPolicy::Immediate.
+   * The function is non-blocking and returns immediately while the image
+   * decoding happens on a background thread.
+   * @since_tizen 2.4
+   * @param [in] encodedImage The encoded bytes of an image, in a supported
+   * image format such as PNG, JPEG, GIF, BMP, KTX, ICO, and WBMP, organised
+   * exactly as it would be as a file in the filesystem.
+   * The caller retains ownership of this buffer and is free to modify or
+   * discard it as soon as the function returns.
+   * @param [in] encodedImageByteCount The size in bytes of the buffer pointed to
+   * by encodedImage.
+   * @return A handle to a newly allocated object.
+   */
+  static EncodedBufferImage New( const uint8_t * const encodedImage, std::size_t encodedImageByteCount );
+
+  /**
+   * @brief Downcast an Object handle to EncodedBufferImage.
+   *
+   * If handle points to a EncodedBufferImage the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a EncodedBufferImage or an uninitialized handle
+   */
+  static EncodedBufferImage DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~EncodedBufferImage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  EncodedBufferImage(const EncodedBufferImage& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  EncodedBufferImage& operator=(const EncodedBufferImage& rhs);
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL EncodedBufferImage(Internal::EncodedBufferImage*);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ENCODED_BUFFER_IMAGE_H__
diff --git a/dali/public-api/images/frame-buffer-image.cpp b/dali/public-api/images/frame-buffer-image.cpp
new file mode 100644 (file)
index 0000000..559f60c
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/frame-buffer-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/stage.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/internal/event/images/frame-buffer-image-impl.h>
+
+namespace Dali
+{
+
+FrameBufferImage::FrameBufferImage()
+{
+}
+
+FrameBufferImage::FrameBufferImage(Internal::FrameBufferImage* internal)
+: Image(internal)
+{
+}
+
+FrameBufferImage::~FrameBufferImage()
+{
+}
+
+FrameBufferImage::FrameBufferImage(const FrameBufferImage& handle)
+: Image(handle)
+{
+}
+
+FrameBufferImage& FrameBufferImage::operator=(const FrameBufferImage& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+FrameBufferImage FrameBufferImage::New(unsigned int width, unsigned int height, Pixel::Format pixelformat, RenderBuffer::Format bufferformat)
+{
+  Dali::Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New(
+    (0 == width) ? stageSize.width : width,
+    (0 == height) ? stageSize.height : height,
+    pixelformat,
+    Dali::Image::NEVER,
+    bufferformat);
+
+  return FrameBufferImage(internal.Get());
+}
+
+FrameBufferImage FrameBufferImage::New(unsigned int width, unsigned int height, Pixel::Format pixelformat, ReleasePolicy releasePolicy, RenderBuffer::Format bufferformat)
+{
+  Dali::Vector2 stageSize = Stage::GetCurrent().GetSize();
+  Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New(
+    (0 == width) ? stageSize.width : width,
+    (0 == height) ? stageSize.height : height,
+    pixelformat,
+    releasePolicy,
+    bufferformat);
+
+  return FrameBufferImage(internal.Get());
+}
+
+FrameBufferImage FrameBufferImage::New( NativeImageInterface& image, ReleasePolicy releasePolicy )
+{
+  Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New( image, releasePolicy );
+  return FrameBufferImage(internal.Get());
+}
+
+FrameBufferImage FrameBufferImage::New( NativeImageInterface& image )
+{
+  Internal::FrameBufferImagePtr internal = Internal::FrameBufferImage::New( image );
+  return FrameBufferImage(internal.Get());
+}
+
+FrameBufferImage FrameBufferImage::DownCast( BaseHandle handle )
+{
+  return FrameBufferImage( dynamic_cast<Dali::Internal::FrameBufferImage*>(handle.GetObjectPtr()) );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/frame-buffer-image.h b/dali/public-api/images/frame-buffer-image.h
new file mode 100644 (file)
index 0000000..6dd499f
--- /dev/null
@@ -0,0 +1,186 @@
+#ifndef __DALI_FRAME_BUFFER_IMAGE_H__
+#define __DALI_FRAME_BUFFER_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/native-image-interface.h>
+#include <dali/public-api/images/pixel.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class FrameBufferImage;
+}
+
+namespace RenderBuffer
+{
+/**
+ * @brief Render Buffer formats
+ * The default format for framebuffer creation is COLOR, so If a depth buffer for 3D rendering is required use
+ * COLOR_DEPTH instead
+ * @since_tizen 2.4
+ */
+enum Format ///< Framebuffer format, default color depth is RGBA 32 bit with alpha
+{
+  COLOR,                ///< Framebuffer will be created with color buffer.
+  COLOR_DEPTH,          ///< Framebuffer will be created with color and depth buffer
+  COLOR_STENCIL,        ///< Framebuffer will be created with color and stencil buffer
+  COLOR_DEPTH_STENCIL   ///< Framebuffer will be created with color, depth and stencil buffer. NOTE: May be not supported in all devices
+};
+}
+
+/**
+ * @brief FrameBufferImage represents a GLES Frame Buffer Object and contains the result
+ * of an 'off screen' render pass of a RenderTask.
+ * The FrameBufferImage can then be used with an ImageView (with optional shader
+ * effects) and rendered to the screen.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API FrameBufferImage : public Image
+{
+public:
+  /**
+   * @brief Constructor which creates an uninitialized FrameBufferImage object.
+   *
+   * Use Image::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  FrameBufferImage();
+
+  /**
+   * @brief Create a new FrameBufferImage.
+   *
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * The ReleasePolicy defaults to Dali::Image::Never.
+   * @since_tizen 2.4
+   * @param [in] width       The width in pixels. Setting to zero will use the width of the stage.
+   * @param [in] height      The height in pixels. Setting to zero will use the height of the stage.
+   * @param [in] pixelFormat The pixel format (rgba 32 bit by default)
+   * @param [in] bufferFormat The format of the buffers that are going to be created for the FBO, (COLOR and DEPTH buffer as default)
+   * @return A handle to a new instance of a FrameBufferImage.
+   * @post When the FrameBufferImage is first used as a render target, an exception may be thrown if pixelFormat is not supported on the hardware platform.
+   */
+  static FrameBufferImage New(unsigned int width = 0, unsigned int height = 0, Pixel::Format pixelFormat = Pixel::RGBA8888,
+                              RenderBuffer::Format bufferFormat = RenderBuffer::COLOR);
+
+  /**
+   * @brief Create a new FrameBufferImage.
+   *
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @since_tizen 2.4
+   * @param [in] width       The width in pixels. Setting to zero will use the width of the stage.
+   * @param [in] height      The height in pixels. Setting to zero will use the height of the stage.
+   * @param [in] pixelFormat The pixel format.
+   * @param [in] releasePolicy The ReleasePolicy to apply to the FrameBufferImage.
+   * @param [in] bufferFormat The format of the buffers that are going to be created for the FBO, (COLOR and DEPTH buffer as default)
+   *
+   * Note that there is no need for a LoadPolicy - by definition it is always OnDemand, since there is no point in the FrameBufferImage existing unless someone is rendering to
+   * it, or it is being used as an input (e.g. ShaderEffect / ImageView).
+   *
+   * @return A handle to a new instance of a FrameBufferImage.
+   * @post When the FrameBufferImage is first used as a render target, an exception may be thrown if pixelFormat is not supported on the hardware platform.
+   */
+  static FrameBufferImage New(unsigned int width, unsigned int height, Pixel::Format pixelFormat, ReleasePolicy releasePolicy,
+                              RenderBuffer::Format bufferFormat = RenderBuffer::COLOR);
+
+  /**
+   * @brief Create a new FrameBufferImage.
+   *
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @since_tizen 2.4
+   * @param [in] image       The native image.
+   *
+   * Note that there is no need for a LoadPolicy - by definition it is always OnDemand, since there is no point in the FrameBufferImage existing unless someone is rendering to
+   * it, or it is being used as an input (e.g. ShaderEffect / ImageView).
+   *
+   * @return A handle to a new instance of a FrameBufferImage.
+   * @post When the FrameBufferImage is first used as a render target, an exception may be thrown if the NativeImage cannot be mapped to a texture.
+   */
+  static FrameBufferImage New(NativeImageInterface& image);
+
+  /**
+   * @brief Create a new FrameBufferImage.
+   *
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE.
+   * @since_tizen 2.4
+   * @param [in] image       The native image.
+   * @param [in] releasePolicy The ReleasePolicy to apply to the FrameBufferImage.
+   *
+   * Note that there is no need for a LoadPolicy - by definition it is always OnDemand, since there is no point in the FrameBufferImage existing unless someone is rendering to
+   * it, or it is being used as an input (e.g. ShaderEffect / ImageView).
+   *
+   * @return A handle to a new instance of a FrameBufferImage.
+   * @post When the FrameBufferImage is first used as a render target, an exception may be thrown if the NativeImage cannot be mapped to a texture.
+   */
+  static FrameBufferImage New(NativeImageInterface& image, ReleasePolicy releasePolicy);
+
+  /**
+   * @brief Downcast an Object handle to FrameBufferImage handle.
+   *
+   * If handle points to a FrameBufferImage object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a FrameBufferImage object or an uninitialized handle
+   */
+  static FrameBufferImage DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~FrameBufferImage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  FrameBufferImage(const FrameBufferImage& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  FrameBufferImage& operator=(const FrameBufferImage& rhs);
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL FrameBufferImage(Internal::FrameBufferImage*);
+}; //class FrameBufferImage
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_FRAME_BUFFER_IMAGE_H__
diff --git a/dali/public-api/images/image-operations.h b/dali/public-api/images/image-operations.h
new file mode 100644 (file)
index 0000000..c84d4db
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __DALI_IMAGE_OPERATIONS_H__
+#define __DALI_IMAGE_OPERATIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/uint-16-pair.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+/**
+ * @brief The integer dimensions of an image or a region of an image packed into
+ *        16 bits per component.
+ *
+ * This can only be used for images of up to 65535 x 65535 pixels.
+ * @since_tizen 2.4
+ */
+typedef Uint16Pair ImageDimensions;
+
+/**
+ * @brief Fitting options, used when resizing images to fit desired dimensions.
+ *
+ * A fitting mode controls the region of a loaded image to be mapped to the
+ * desired image rectangle.
+ * All fitting modes preserve the aspect ratio of the image contents.
+ * @since_tizen 2.4
+ */
+namespace FittingMode
+{
+  enum Type
+  {
+    SHRINK_TO_FIT, ///< Fit full image inside desired width & height, potentially not
+                   ///  filling one of either the desired image width or height with
+                   ///  pixels.
+    SCALE_TO_FILL, ///< Image fills whole desired width & height with image data. The
+                   ///  image is centred in the desired dimensions, exactly touching
+                   ///  in one dimension, with image regions outside the other desired
+                   ///  dimension cropped away.
+    FIT_WIDTH,     ///< Image fills whole width. Height is scaled proportionately to
+                   ///  maintain aspect ratio.
+    FIT_HEIGHT     ///< Image fills whole height. Width is scaled proportionately to
+                   ///  maintain aspect ratio.
+  };
+  const Type DEFAULT = SHRINK_TO_FIT;
+}
+
+/**
+ * @brief Filtering options, used when resizing images to sample original pixels.
+ *
+ * A SamplingMode controls how pixels in an input image are sampled and
+ * combined to generate each pixel of a destination image during a scaling.
+ *
+ * NoFilter and Box modes do not guarantee that the output pixel array
+ * exactly matches the rectangle specified by the desired dimensions and
+ * FittingMode, but all other filter modes do if the desired dimensions are
+ * `<=` the raw dimensions of the input image file.
+ * @since_tizen 2.4
+ */
+namespace SamplingMode
+{
+  enum Type
+  {
+    BOX,              ///< Iteratively box filter to generate an image of 1/2, 1/4,
+                      ///  1/8, etc width and height and approximately the desired
+                      ///  size. This is the default.
+    NEAREST,          ///< For each output pixel, read one input pixel.
+    LINEAR,           ///< For each output pixel, read a quad of four input pixels
+                      ///  and write a weighted average of them.
+    BOX_THEN_NEAREST, ///< Iteratively box filter to generate an image of 1/2, 1/4,
+                      ///  1/8 etc width and height and approximately the desired
+                      ///  size, then for each output pixel, read one pixel from the
+                      ///  last level of box filtering.
+    BOX_THEN_LINEAR,  ///< Iteratively box filter to almost the right size, then for
+                      ///  each output pixel, read four pixels from the last level of
+                      ///  box filtering and write their weighted average.
+    NO_FILTER,        ///< No filtering is performed. If the SCALE_TO_FILL scaling mode
+                      ///  is enabled, the borders of the image may be trimmed to
+                      ///  match the aspect ratio of the desired dimensions.
+    DONT_CARE         ///< For caching algorithms where a client strongly prefers a
+                      ///  cache-hit to reuse a cached image.
+  };
+  const Type DEFAULT = BOX;
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_IMAGE_OPERATIONS_H__
diff --git a/dali/public-api/images/image.cpp b/dali/public-api/images/image.cpp
new file mode 100644 (file)
index 0000000..0ab3083
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/image.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/image-impl.h>
+
+
+namespace Dali
+{
+
+Image::Image()
+{
+}
+
+Image::Image(Internal::Image* internal) : BaseHandle(internal)
+{
+}
+
+Image::~Image()
+{
+}
+
+Image::Image(const Image& handle)
+: BaseHandle(handle)
+{
+}
+
+Image& Image::operator=(const Image& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+Image Image::DownCast( BaseHandle handle )
+{
+  return Image( dynamic_cast<Dali::Internal::Image*>(handle.GetObjectPtr()) );
+}
+
+Image::ReleasePolicy Image::GetReleasePolicy() const
+{
+  return GetImplementation(*this).GetReleasePolicy();
+}
+
+unsigned int Image::GetWidth() const
+{
+  return GetImplementation(*this).GetWidth();
+}
+
+unsigned int Image::GetHeight() const
+{
+  return GetImplementation(*this).GetHeight();
+}
+
+Image::ImageSignalType& Image::UploadedSignal()
+{
+  return GetImplementation(*this).UploadedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/image.h b/dali/public-api/images/image.h
new file mode 100644 (file)
index 0000000..dc87c69
--- /dev/null
@@ -0,0 +1,184 @@
+#ifndef __DALI_IMAGE_H__
+#define __DALI_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class Image;
+}
+
+/**
+ * @brief An Image object represents an image resource that can be added to ImageViews.
+ *
+ * Image objects can be shared between ImageViews. This is practical if you have a visual element on screen
+ * which is repeatedly used. An example would be a button background image.
+ * The image resource is discarded when all ImageViews using the Image object are discarded or in case they
+ * were created with ReleasePolicy::Unused, taken off stage.
+ * Note: if a resource was shared between Image objects it exists until its last reference is gone.
+ *
+ * Image objects are responsible for the underlying resource's lifetime.
+ *
+ * <i>ReleasePolicies</i>
+ * - Unused: release resource once ImageView using it is taken off stage.
+ * - Never: keep resource alive until Image object is thrown away.
+ *
+ * <i>Resolution of conflicting policies</i>
+ * If the same image is created more than once with conflicting policies, ReleasePolicy "Never" overrides "Unused".
+ *
+ * Signals
+ * | %Signal Name           | Method                       |
+ * |------------------------|------------------------------|
+ * | uploaded               | @ref UploadedSignal()        |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Image : public BaseHandle
+{
+public:
+  /**
+   * @brief Resource management options.
+   */
+
+  /**
+   * @brief ReleasePolicy controls the way images are deleted from memory.
+   * @since_tizen 2.4
+   */
+  enum ReleasePolicy
+  {
+    UNUSED, ///< release resource once image is not in use anymore (eg. all actors using it become offstage). Reload when resource is required again.
+    NEVER   ///< keep image data for the lifetime of the object. (default)
+  };
+
+  /**
+   * @brief Type of signal for Image Uploaded.
+   * @since_tizen 2.4
+   */
+  typedef Signal< void (Image) > ImageSignalType;
+
+public:
+
+  /**
+   * @brief Constructor which creates an empty Image handle.
+   *
+   * Use Image::New(...) to create an initialised handle.
+   * @since_tizen 2.4
+   */
+  Image();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Image();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  Image(const Image& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Image& operator=(const Image& rhs);
+
+  /**
+   * @brief Downcast an Object handle to Image handle.
+   *
+   * If handle points to a Image object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Image object or an uninitialized handle
+   */
+  static Image DownCast( BaseHandle handle );
+
+  /**
+   * @brief Return resource release policy.
+   *
+   * @since_tizen 2.4
+   * @return resource release policy
+   */
+  ReleasePolicy GetReleasePolicy() const;
+
+  /**
+   * @brief Returns the width of the image.
+   *
+   * Returns either the requested width or the actual loaded width if no specific size was requested.
+   *
+   * @since_tizen 2.4
+   * @return width of the image in pixels.
+   */
+  unsigned int GetWidth() const;
+
+  /**
+   * @brief Returns the height of the image.
+   *
+   * Returns either the requested height or the actual loaded height if no specific size was requested.
+   *
+   * @since_tizen 2.4
+   * @return height of the image in pixels.
+   */
+  unsigned int GetHeight() const;
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when the image data gets uploaded to GL.
+   *
+   * It Will be sent after an actor using the image is added to
+   * the stage, when such a staged image is reloaded, or when a staged
+   * BufferImage calls Update().
+   * @since_tizen 2.4
+   * @return A signal object to Connect() with.
+   */
+  ImageSignalType& UploadedSignal();
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL Image(Internal::Image*);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_IMAGE_H__
diff --git a/dali/public-api/images/native-image-interface.h b/dali/public-api/images/native-image-interface.h
new file mode 100644 (file)
index 0000000..7b3b00b
--- /dev/null
@@ -0,0 +1,141 @@
+#ifndef __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_H__
+#define __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+/**
+ * @brief Abstract interface to provide platform-specific support for handling image data.
+ *
+ * For example, an implementation could use EGL extensions, etc.
+ * @since_tizen 2.4
+ */
+class NativeImageInterface : public Dali::RefObject
+{
+public:
+
+  class Extension; ///< Forward declare future extension interface
+
+  /**
+   * @brief Create the GL resource for the NativeImage.
+   *
+   * e.g. For the EglImageKHR extension, this corresponds to calling eglCreateImageKHR()
+   * @since_tizen 2.4
+   * @return false If the initialization fails.
+   * @pre There is a GL context for the current thread.
+   */
+  virtual bool GlExtensionCreate() = 0;
+
+  /**
+   * @brief Destroy the GL resource for the NativeImage.
+   *
+   * e.g. For the EglImageKHR extension, this corresponds to calling eglDestroyImageKHR()
+   * @since_tizen 2.4
+   * @pre There is a GL context for the current thread.
+   */
+  virtual void GlExtensionDestroy() = 0;
+
+  /**
+   * @brief Use the NativeImage as a texture for rendering.
+   *
+   * @since_tizen 2.4
+   * @return A GL error code
+   * @pre There is a GL context for the current thread.
+   */
+  virtual unsigned int TargetTexture() = 0;
+
+  /**
+   * @brief Called in each NativeTexture::Bind() call to allow implementation specific operations.
+   *
+   * The correct texture sampler has already been bound before the function gets called.
+   * @since_tizen 2.4
+   * @pre glAbstraction is being used by context in current thread
+   */
+  virtual void PrepareTexture() = 0;
+
+  /**
+   * @brief Returns the width of the NativeImage.
+   *
+   * @since_tizen 2.4
+   * @return width
+   */
+  virtual unsigned int GetWidth() const = 0;
+
+  /**
+   * @brief Returns the height of the NativeImage.
+   *
+   * @since_tizen 2.4
+   * @return height
+   */
+  virtual unsigned int GetHeight() const = 0;
+
+ /**
+  * @brief Query whether blending is required
+  * @since_tizen 2.4
+  */
+  virtual bool RequiresBlending() const = 0;
+
+  /**
+   * @brief Retrieve the extension for the interface.
+   *
+   * @since_tizen 2.4
+   * @return The extension if available, NULL otherwise
+   */
+  virtual Extension* GetExtension()
+  {
+    return NULL;
+  }
+
+protected:
+
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference().
+   *
+   * The implementation should destroy the NativeImage resources.
+   * @since_tizen 2.4
+   */
+  virtual ~NativeImageInterface()
+  {
+  }
+
+};
+
+/**
+ * @brief Pointer to Dali::NativeImageInterface
+ * @since_tizen 2.4
+ */
+typedef IntrusivePtr<NativeImageInterface>  NativeImageInterfacePtr;
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_INTEGRATION_NATIVE_IMAGE_INTERFACE_H__
diff --git a/dali/public-api/images/native-image.cpp b/dali/public-api/images/native-image.cpp
new file mode 100644 (file)
index 0000000..fd40713
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/native-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/images/native-image-impl.h>
+
+namespace Dali
+{
+
+NativeImage::NativeImage()
+{
+}
+
+NativeImage::NativeImage(Internal::NativeImage* internal)
+: Image(internal)
+{
+}
+
+NativeImage::~NativeImage()
+{
+}
+
+NativeImage::NativeImage( const NativeImage& handle )
+: Image(handle)
+{
+}
+
+NativeImage& NativeImage::operator=( const NativeImage& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void NativeImage::CreateGlTexture()
+{
+  GetImplementation(*this).CreateGlTexture();
+}
+
+NativeImage NativeImage::New( NativeImageInterface& resourceData )
+{
+  Internal::NativeImagePtr internal = Internal::NativeImage::New( resourceData );
+  return NativeImage(internal.Get());
+}
+
+NativeImage NativeImage::DownCast( BaseHandle handle )
+{
+  return NativeImage( dynamic_cast<Internal::NativeImage*>( handle.GetObjectPtr()) );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/native-image.h b/dali/public-api/images/native-image.h
new file mode 100644 (file)
index 0000000..15e4802
--- /dev/null
@@ -0,0 +1,125 @@
+#ifndef __DALI_NATIVE_IMAGE_H__
+#define __DALI_NATIVE_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/images/native-image-interface.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class NativeImage;
+}
+
+/**
+ * @brief NativeImage represents an image resource that can be added to ImageViews.
+ * Its data is provided by native resources, such as shared bitmap memory or pixmap from X11 or ECORE-X11, etc.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API  NativeImage : public Image
+{
+public:
+
+  /**
+   * @brief Constructor with creates an uninitialized NativeImage object.
+   *
+   * Use NativeImage::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  NativeImage();
+
+  /**
+   * @brief Destructor.
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+   ~NativeImage();
+
+   /**
+    * @brief This copy constructor is required for (smart) pointer semantics.
+    *
+    * @since_tizen 2.4
+    * @param [in] handle A reference to the copied handle
+    */
+   NativeImage( const NativeImage& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs A reference to the copied handle.
+   * @return A reference to this.
+   */
+  NativeImage& operator=( const NativeImage& rhs );
+
+  /**
+   * @brief Trigger asynchronous creation of backing GL texture immediately.
+   *
+   * The normal policy is for a GL texture to created lazily when needed.
+   * This function forces the allocation of a texture to happen at the earliest
+   * opportunity.
+   *
+   * @since_tizen 2.4
+   * @note If the application loses its GL context, native images may lose their
+   * GL textures. This function can be called again after context regain to force
+   * the creation of the GL texture if still needed.
+   */
+  void CreateGlTexture();
+
+  /**
+   * @brief Create a new NativeImage, which used native resources.
+   *
+   * The maximum size of the image is limited by GL_MAX_TEXTURE_SIZE
+   * @since_tizen 2.4
+   * @param [in] nativeImageInterface An reference to the object of the interface implementation.
+   * @return A handle to a newly allocated object.
+   */
+  static NativeImage New( NativeImageInterface& nativeImageInterface );
+
+  /**
+   * @brief Downcast an Object handle to NativeImage handle.
+   *
+   * If handle points to a NativeImage object, the downcast produces valid handle.
+   * If not, the returned handle is left unintialized.
+   * @since_tizen 2.4
+   * @param[in] handle Handle to an object.
+   * @return handle to a NativeImage or an uninitialized handle.
+   */
+  static NativeImage DownCast( BaseHandle handle );
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL NativeImage( Internal::NativeImage* );
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_NATIVE_IMAGE_H__
diff --git a/dali/public-api/images/nine-patch-image.cpp b/dali/public-api/images/nine-patch-image.cpp
new file mode 100644 (file)
index 0000000..e1ba0d8
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/nine-patch-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/image-attributes.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/internal/event/images/nine-patch-image-impl.h>
+
+
+namespace Dali
+{
+
+NinePatchImage::NinePatchImage()
+{
+}
+
+NinePatchImage::NinePatchImage(Internal::NinePatchImage* internal)
+: ResourceImage(internal)
+{
+}
+
+NinePatchImage::~NinePatchImage()
+{
+}
+
+NinePatchImage::NinePatchImage(const NinePatchImage& handle)
+: ResourceImage(handle)
+{
+}
+
+NinePatchImage& NinePatchImage::operator=(const NinePatchImage& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+NinePatchImage NinePatchImage::New( const std::string& filename )
+{
+  Internal::NinePatchImagePtr internal = Internal::NinePatchImage::New( filename, Image::NEVER );
+  return NinePatchImage(internal.Get());
+}
+
+NinePatchImage NinePatchImage::DownCast( BaseHandle handle )
+{
+  return NinePatchImage( dynamic_cast<Dali::Internal::NinePatchImage*>(handle.GetObjectPtr()) );
+}
+
+Vector4 NinePatchImage::GetStretchBorders()
+{
+  return GetImplementation(*this).GetStretchBorders();
+}
+
+Rect<int> NinePatchImage::GetChildRectangle()
+{
+  return GetImplementation(*this).GetChildRectangle();
+}
+
+BufferImage NinePatchImage::CreateCroppedBufferImage()
+{
+  Internal::BufferImagePtr internal = GetImplementation(*this).CreateCroppedBufferImage();
+  return BufferImage(internal.Get());
+}
+
+
+} // namespace Dali
diff --git a/dali/public-api/images/nine-patch-image.h b/dali/public-api/images/nine-patch-image.h
new file mode 100644 (file)
index 0000000..925d2c2
--- /dev/null
@@ -0,0 +1,147 @@
+#ifndef __DALI_NINE_PATCH_IMAGE_H__
+#define __DALI_NINE_PATCH_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/images/resource-image.h>
+#include <dali/public-api/images/buffer-image.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class NinePatchImage;
+}
+
+/**
+ * @brief NinePatchImage represents an image resource that can be added to ImageViews.
+ * It contains a bitmap that is synchronously loaded from the file system that contains
+ * a 9 patch border - a 1 pixel border that describes the stretch borders and the child
+ * area.
+ *
+ * The class offers an API to read the stretch area and child area, but it does not
+ * remove the border from it's bitmap. An API can be used to obtain a BufferImage with
+ * the border removed.
+ *
+ * Adding this image to an ImageView using an Image handle will automatically convert
+ * to use the cropped BufferImage - if you don't retain a handle to this object, it will
+ * be automatically destroyed.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API NinePatchImage : public ResourceImage
+{
+public:
+  /**
+   * @brief Constructor which creates an uninitialized NinePatchImage object.
+   *
+   * Use Image::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  NinePatchImage();
+
+  /**
+   * @brief Create a new NinePatchImage.
+   *
+   * A pixel buffer for image data is allocated and loaded from the filesystem.
+   * Dali has ownership of the buffer.
+   * @note: default resource management policies are Immediate and Never
+   *
+   * @since_tizen 2.4
+   * @param [in] filename    File to load synchronously into buffer
+   * @return a handle to a new instance of NinePatchImage
+   */
+  static NinePatchImage New( const std::string& filename );
+
+  /**
+   * @brief Downcast an Object handle to NinePatchImage.
+   *
+   * If handle points to a NinePatchImage the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a NinePatchImage or an uninitialized handle
+   */
+  static NinePatchImage DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~NinePatchImage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  NinePatchImage(const NinePatchImage& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  NinePatchImage& operator=(const NinePatchImage& rhs);
+
+  /**
+   * @brief Get the stretch borders
+   * @since_tizen 2.4
+   * @return The border in pixels from the left, top, right, and bottom of the image respectively.
+   */
+  Vector4 GetStretchBorders();
+
+  /**
+   * @brief Get the child rectangle
+   * @since_tizen 2.4
+   * @return the position and size of the child rectangle
+   */
+  Rect<int> GetChildRectangle();
+
+  /**
+   * @brief Creates a buffer image from the bitmap with the 1 pixel border cropped off.
+   * This does not change the internal bitmap.
+   *
+   * @since_tizen 2.4
+   * @return The cropped BufferImage
+   */
+  BufferImage CreateCroppedBufferImage();
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL NinePatchImage(Internal::NinePatchImage*);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_NINE_PATCH_IMAGE_H__
diff --git a/dali/public-api/images/pixel.cpp b/dali/public-api/images/pixel.cpp
new file mode 100644 (file)
index 0000000..aae23a9
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/pixel.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+bool Pixel::HasAlpha(Format pixelformat)
+{
+  switch (pixelformat)
+  {
+    case RGBA5551:
+    case RGBA8888:
+    case RGBA4444:
+    case BGRA8888:
+    case BGRA4444:
+    case BGRA5551:
+    case A8:
+    case LA88:
+    // Note, Can be used for alpha if you want: COMPRESSED_R11_EAC,                       ///< ETC2 / EAC single-channel, unsigned
+    // Note, Can be used for alpha if you want: COMPRESSED_SIGNED_R11_EAC,                ///< ETC2 / EAC single-channel, signed
+    case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_RGBA8_ETC2_EAC:
+    case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    {
+      return true;
+    }
+
+    case L8:
+    case RGB565:
+    case RGB888:
+    case RGB8888: // alpha not used
+    case BGR8888: // alpha not used
+    case BGR565:
+    case COMPRESSED_R11_EAC:
+    case COMPRESSED_SIGNED_R11_EAC:
+    case COMPRESSED_RG11_EAC:
+    case COMPRESSED_SIGNED_RG11_EAC:
+    case COMPRESSED_RGB8_ETC2:
+    case COMPRESSED_SRGB8_ETC2:
+    case COMPRESSED_RGB8_ETC1:
+    case COMPRESSED_RGB_PVRTC_4BPPV1:
+    {
+      return false;
+    }
+  }
+  return false;
+}
+
+unsigned int Pixel::GetBytesPerPixel(Format pixelFormat)
+{
+  switch (pixelFormat)
+  {
+    case L8:
+    case A8:
+    {
+      return 1;
+    }
+
+    case LA88:
+    case RGB565:
+    case RGBA4444:
+    case RGBA5551:
+    case BGR565:
+    case BGRA4444:
+    case BGRA5551:
+    {
+      return 2;
+    }
+
+    case RGB888:
+    {
+      return 3;
+    }
+
+    case RGB8888:
+    case BGR8888:
+    case RGBA8888:
+    case BGRA8888:
+    {
+      return 4;
+    }
+
+    case COMPRESSED_R11_EAC:
+    case COMPRESSED_SIGNED_R11_EAC:
+    case COMPRESSED_RG11_EAC:
+    case COMPRESSED_SIGNED_RG11_EAC:
+    case COMPRESSED_RGB8_ETC2:
+    case COMPRESSED_SRGB8_ETC2:
+    case COMPRESSED_RGB8_ETC1:
+    case COMPRESSED_RGB_PVRTC_4BPPV1:
+    case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_RGBA8_ETC2_EAC:
+    case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    {
+      DALI_LOG_ERROR("Pixel formats for compressed images do not have meaningful integer bits per pixel values.\n");
+      return 0;
+    }
+  }
+  return 0;
+}
+
+void Pixel::GetAlphaOffsetAndMask(Format pixelFormat, int& byteOffset, int& bitMask)
+{
+  switch (pixelFormat)
+  {
+    case A8:
+    {
+      byteOffset = 0;
+      bitMask    = 0xFF;
+    }
+    break;
+
+    case L8:
+    case RGB888:
+    case RGB565:
+    case RGB8888:
+    case BGR8888:
+    case BGR565:
+    {
+      byteOffset=0;
+      bitMask=0;
+      break;
+    }
+
+    case LA88:
+    {
+      byteOffset=1;
+      bitMask=0xff;
+      break;
+    }
+
+    case RGBA4444:
+    case BGRA4444:
+    {
+      byteOffset=1;
+      bitMask=0x0f;
+      break;
+    }
+
+    case RGBA5551:
+    case BGRA5551:
+    {
+      byteOffset=1;
+      bitMask=0x01;
+      break;
+    }
+
+    case RGBA8888:
+    case BGRA8888:
+    {
+      byteOffset=3;
+      bitMask=0xff;
+      break;
+    }
+
+    case COMPRESSED_R11_EAC:
+    case COMPRESSED_SIGNED_R11_EAC:
+    case COMPRESSED_RG11_EAC:
+    case COMPRESSED_SIGNED_RG11_EAC:
+    case COMPRESSED_RGB8_ETC2:
+    case COMPRESSED_SRGB8_ETC2:
+    case COMPRESSED_RGB8_ETC1:
+    case COMPRESSED_RGB_PVRTC_4BPPV1:
+    case COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
+    case COMPRESSED_RGBA8_ETC2_EAC:
+    case COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
+    {
+      DALI_LOG_ERROR("Pixel formats for compressed images are not compatible with simple masking-out of per-pixel alpha.\n");
+      byteOffset=0;
+      bitMask=0;
+      break;
+    }
+  }
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/pixel.h b/dali/public-api/images/pixel.h
new file mode 100644 (file)
index 0000000..cf2fe7b
--- /dev/null
@@ -0,0 +1,130 @@
+#ifndef __DALI_PIXEL_H__
+#define __DALI_PIXEL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+  
+/**
+ * @brief Pixel format types and their properties.
+ * @since_tizen 2.4
+ */
+namespace Pixel
+{
+/**
+ * @brief Pixel formats
+ *
+ * @note: BufferImage::Update might not work with BGR/BGRA formats!
+ * @since_tizen 2.4
+ */
+enum Format ///< pixel format, default color depth is RGBA 32 bit with alpha
+{
+  // Start at > 0 to distinguish null data:
+  A8 = 1,          ///< color depth 8-bit, alpha
+  L8,              ///< color depth 8-bit, luminance
+  LA88,            ///< color depth 16-bit, luminance with 8 bit alpha
+  RGB565,          ///< color depth 16 bit, 5-6-5
+  BGR565,          ///< color depth 16 bit, 5-6-5
+  RGBA4444,        ///< color depth 16 bit with alpha, 4-4-4-4
+  BGRA4444,        ///< color depth 16 bit with alpha, 4-4-4-4
+  RGBA5551,        ///< color depth 16 bit with alpha, 5-5-5-1
+  BGRA5551,        ///< color depth 16 bit with alpha, 5-5-5-1
+  RGB888,          ///< color depth 24 bit, 8-8-8
+  RGB8888,         ///< color depth 32 bit, alpha is reserved but not used, 8-8-8-8#
+  BGR8888,         ///< color depth 32 bit, alpha is reserved but not used, 8-8-8-8#
+  RGBA8888,        ///< color depth 32 bit with alpha, 8-8-8-8
+  BGRA8888,        ///< color depth 32 bit with alpha, 8-8-8-8
+  // GLES 3 Standard compressed formats:
+  COMPRESSED_R11_EAC,                       ///< ETC2 / EAC single-channel, unsigned
+  COMPRESSED_SIGNED_R11_EAC,                ///< ETC2 / EAC single-channel, signed
+  COMPRESSED_RG11_EAC,                      ///< ETC2 / EAC dual-channel, unsigned
+  COMPRESSED_SIGNED_RG11_EAC,               ///< ETC2 / EAC dual-channel, signed
+  COMPRESSED_RGB8_ETC2,                     ///< ETC2 / EAC RGB
+  COMPRESSED_SRGB8_ETC2,                    ///< ETC2 / EAC RGB using sRGB colourspace.
+  COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, ///< ETC2 / EAC RGB with single bit per pixel alpha mask.
+  COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,///< ETC2 / EAC RGB using sRGB colourspace, with single bit per pixel alpha mask.
+  COMPRESSED_RGBA8_ETC2_EAC,                ///< ETC2 / EAC RGB plus separate alpha channel.
+  COMPRESSED_SRGB8_ALPHA8_ETC2_EAC,         ///< ETC2 / EAC RGB using sRGB colourspace, plus separate alpha channel.
+  // GLES 2 extension compressed formats:
+  COMPRESSED_RGB8_ETC1,                     ///< ETC1 RGB as defined by GLES 2 extension OES_compressed_ETC1_RGB8_texture: http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
+  COMPRESSED_RGB_PVRTC_4BPPV1               ///< PowerVR 4bpp RGB format (v1) as defined by extension IMG_texture_compression_pvrtc: http://www.khronos.org/registry/gles/extensions/IMG/IMG_texture_compression_pvrtc.txt
+  ///! Update LAST_VALID_PIXEL_FORMAT below if you add an enum value here.
+};
+
+/**
+ * @brief For asserting that a variable has a valid pixel format.
+ *
+ * Sync it to the first value above.
+ */
+const Format FIRST_VALID_PIXEL_FORMAT = A8;
+
+/**
+ * @brief For asserting that a variable has a valid pixel format.
+ *
+ * Sync it to the last value above.
+ */
+const Format LAST_VALID_PIXEL_FORMAT = COMPRESSED_RGB_PVRTC_4BPPV1;
+
+/**
+ * @brief Whether specified pixel format contains an alpha value.
+ *
+ * @since_tizen 2.4
+ * @param [in] pixelformat pixel format
+ * @return true if format has alpha, false otherwise
+ */
+DALI_IMPORT_API bool HasAlpha(Format pixelformat);
+
+/**
+ * @brief Returns The number of bytes per pixel for the specified pixel format.
+ *
+ * @since_tizen 2.4
+ * @param [in] pixelFormat The pixel format
+ * @return The number of bytes per pixel
+ */
+DALI_IMPORT_API unsigned int GetBytesPerPixel(Format pixelFormat);
+
+/**
+ * @brief Returns the offset of the byte containing the alpha value from the start of the pixel data
+ * and the bitmask of that byte to get the alpha value.
+ * For example, in case of RGBA4444, byteOffset value is 1 and bitMask value is 0x0f.
+ * It means the second byte contains the alpha value and the last 4 bits of the byte is the alpha value.
+ *
+ * Bitmask is zero if the pixelFormat does not support alpha
+ * @since_tizen 2.4
+ * @param[in]  pixelFormat the pixel format
+ * @param[out] byteOffset the byte offset of the byte containing the alpha value
+ * @param[out] bitMask the bitmask of the byte to get the alpha value
+ */
+DALI_IMPORT_API void GetAlphaOffsetAndMask(Format pixelFormat, int& byteOffset, int& bitMask);
+
+} //namespace Pixel
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PIXEL_H__
diff --git a/dali/public-api/images/resource-image.cpp b/dali/public-api/images/resource-image.cpp
new file mode 100644 (file)
index 0000000..910c6be
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/images/resource-image.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/common/image-attributes.h>
+#include <dali/internal/event/images/resource-image-impl.h>
+#include <dali/internal/event/common/thread-local-storage.h>
+#include <dali/integration-api/platform-abstraction.h>
+
+namespace Dali
+{
+
+ImageDimensions ResourceImage::GetImageSize( const std::string& url )
+{
+  const Internal::ImageAttributes& attribs = Internal::ImageAttributes::DEFAULT_ATTRIBUTES;
+  const ImageDimensions desiredSize = ImageDimensions( attribs.GetWidth(), attribs.GetHeight() );
+  const ImageDimensions size = Internal::ThreadLocalStorage::Get().GetPlatformAbstraction().GetClosestImageSize( url, desiredSize, attribs.GetScalingMode(), attribs.GetFilterMode(), attribs.GetOrientationCorrection() );
+  return size;
+}
+
+ResourceImage::ResourceImage()
+{
+}
+
+ResourceImage::ResourceImage(Internal::ResourceImage* internal) : Image(internal)
+{
+}
+
+ResourceImage::~ResourceImage()
+{
+}
+
+ResourceImage::ResourceImage( const ResourceImage& handle )
+: Image(handle)
+{
+}
+
+ResourceImage& ResourceImage::operator=( const ResourceImage& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+ResourceImage ResourceImage::New( const std::string& url, bool orientationCorrection )
+{
+  Internal::ImageAttributes attributes = Internal::ImageAttributes::DEFAULT_ATTRIBUTES;
+  attributes.SetOrientationCorrection( orientationCorrection );
+  return ResourceImage( Internal::ResourceImage::New( url, attributes ).Get() );
+}
+
+ResourceImage ResourceImage::New( const std::string& url, LoadPolicy loadPol, ReleasePolicy releasePol, bool orientationCorrection )
+{
+  Internal::ImageAttributes attributes = Internal::ImageAttributes::DEFAULT_ATTRIBUTES;
+  attributes.SetOrientationCorrection( orientationCorrection );
+  return ResourceImage( Internal::ResourceImage::New( url, attributes, loadPol, releasePol ).Get() );
+}
+
+ResourceImage ResourceImage::New( const std::string& url, ImageDimensions size, FittingMode::Type scalingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
+{
+  Internal::ImageAttributes attributes = Internal::ImageAttributes::DEFAULT_ATTRIBUTES;
+  attributes.SetSize( Size( size.GetWidth(), size.GetHeight() ) );
+  attributes.SetScalingMode( scalingMode );
+  attributes.SetFilterMode( samplingMode );
+  attributes.SetOrientationCorrection( orientationCorrection );
+  return ResourceImage( Internal::ResourceImage::New( url, attributes ).Get() );
+}
+
+ResourceImage ResourceImage::New( const std::string& url, LoadPolicy loadPol, ReleasePolicy releasePol, ImageDimensions size, FittingMode::Type scalingMode, SamplingMode::Type samplingMode, bool orientationCorrection )
+{
+  Internal::ImageAttributes attributes = Internal::ImageAttributes::DEFAULT_ATTRIBUTES;
+  attributes.SetSize( Size( size.GetWidth(), size.GetHeight() ) );
+  attributes.SetScalingMode( scalingMode );
+  attributes.SetFilterMode( samplingMode );
+  attributes.SetOrientationCorrection( orientationCorrection );
+  return ResourceImage( Internal::ResourceImage::New( url, attributes, loadPol, releasePol ).Get() );
+}
+
+ResourceImage ResourceImage::DownCast( BaseHandle handle )
+{
+  return ResourceImage( dynamic_cast<Dali::Internal::ResourceImage*>(handle.GetObjectPtr()) );
+}
+
+ResourceImage::LoadPolicy ResourceImage::GetLoadPolicy() const
+{
+  return GetImplementation(*this).GetLoadPolicy();
+}
+
+LoadingState ResourceImage::GetLoadingState() const
+{
+  return GetImplementation(*this).GetLoadingState();
+}
+
+std::string ResourceImage::GetUrl() const
+{
+  return GetImplementation(*this).GetUrl();
+}
+
+void ResourceImage::Reload()
+{
+  GetImplementation(*this).Reload();
+}
+
+ResourceImage::ResourceImageSignal& ResourceImage::LoadingFinishedSignal()
+{
+  return GetImplementation(*this).LoadingFinishedSignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/images/resource-image.h b/dali/public-api/images/resource-image.h
new file mode 100644 (file)
index 0000000..8260241
--- /dev/null
@@ -0,0 +1,308 @@
+#ifndef __DALI_RESOURCE_IMAGE_H__
+#define __DALI_RESOURCE_IMAGE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/loading-state.h>
+#include <dali/public-api/images/image.h>
+#include <dali/public-api/signals/dali-signal.h>
+#include <dali/public-api/images/image-operations.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_images
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class ResourceImage;
+}
+
+/**
+ * @brief ResourceImage is an image loaded using a URL
+ *
+ * <h3>ResourceImage Loading</h3>
+ *
+ * When the ResourceImage is created, resource loading will be attempted unless
+ * the ResourceImage is created with IMMEDIATE loading policy or a compatible resource is found in cache.
+ * In case of loading images ON_DEMAND, resource loading will only be attempted if the associated ImageView
+ * is put on Stage.
+ * Scaling of images to a desired smaller size can be requested by providing desired dimensions,
+ * scaling mode and filter mode to to ResourceImage::New().
+ *
+ * <i>LoadPolicies</i>
+ * - IMMEDIATE: acquire image resource when creating ResourceImage.
+ * - ON_DEMAND: only load in case the associated ImageView is put on Stage
+ *
+ * <i>Resolution of conflicting policies</i>
+ * If the same image is created more than once with conflicting policies, LoadPolicy "IMMEDIATE" overrides "ON_DEMAND".
+ *
+ * <i>Custom load requests</i>
+ * Size, scaling mode, filter mode, and orientation compensation can be set when requesting an image.
+ *
+ * <i>Compatible resources</i>
+ *
+ * Before loading a new ResourceImage the internal image resource cache is checked by dali.
+ * If there is an image already loaded in memory and is deemed "compatible" with the requested image,
+ * that resource is reused.
+ * This happens for example if a loaded image exists with the same URL, scaling and filtering modes,
+ * and the difference between both of the dimensions is less than a few pixels.
+ *
+ * <i>Reloading images</i>
+ *
+ * The same request used on creating the ResourceImage is re-issued when reloading images.
+ * If the file changed since the last load operation, this might result in a different resource.
+ * Reload only takes effect if both of these conditions apply:
+ * - The ResourceImage has already finished loading
+ * - The ResourceImage is either on Stage or using IMMEDIATE load policy
+ *
+ * Signals
+ * | %Signal Name           | Method                       |
+ * |------------------------|------------------------------|
+ * | image-loading-finished | @ref LoadingFinishedSignal() |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ResourceImage : public Image
+{
+public:
+  /**
+   * @brief Resource management options.
+   */
+
+  /**
+   * @brief LoadPolicy controls the way images are loaded into memory.
+   * @since_tizen 2.4
+   */
+  enum LoadPolicy
+  {
+    IMMEDIATE, ///< load image once it is created (default)
+    ON_DEMAND  ///< delay loading until the image is being used (a related actor is added to Stage)
+  };
+
+  /**
+   * @brief Type of signal for LoadingFinished and Uploaded.
+   * @since_tizen 2.4
+   */
+  typedef Signal< void (ResourceImage) > ResourceImageSignal;
+
+public:
+
+  /**
+   * @brief Get the size of an image from disk.
+   *
+   * This function will read the header info from file on disk and is
+   * synchronous, so it should not be used repeatedly or in tight
+   * loops.
+   *
+   * @since_tizen 2.4
+   * @param [in] url The URL of the image file.
+   * @return The width and height in pixels of the image.
+   */
+  static ImageDimensions GetImageSize( const std::string& url );
+
+  /**
+   * @brief Constructor which creates an empty ResourceImage object.
+   *
+   * Use ResourceImage::New(...) to create an initialised object.
+   * @since_tizen 2.4
+   */
+  ResourceImage();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~ResourceImage();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  ResourceImage( const ResourceImage& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  ResourceImage& operator=( const ResourceImage& rhs );
+
+  /**
+   * @name ResourceImageFactoryFunctions
+   * Create ResourceImage object instances using these functions.
+   */
+  ///@{
+
+  /**
+   * @brief Create an initialised ResourceImage object.
+   *
+   * Uses defaults for all options.
+   *
+   * @sa Dali::FittingMode::Type Dali::SamplingMode::Type
+   * @since_tizen 2.4
+   * @privlevel public
+   * @privilege %http://tizen.org/privilege/internet
+   * @remarks %http://tizen.org/privilege/internet is needed if @a url is a http or https address.
+   * @param [in] url The URL of the image file to use (can be a local file path, http or https address).
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @return A handle to a newly allocated object
+   */
+  static ResourceImage New( const std::string& url, bool orientationCorrection = true );
+
+  /**
+   * @brief Create an initialised ResourceImage object.
+   *
+   * @since_tizen 2.4
+   * @privlevel public
+   * @privilege %http://tizen.org/privilege/internet
+   * @remarks %http://tizen.org/privilege/internet is needed if @a url is a http or https address.
+   * @param [in] url The URL of the image file to use (can be a local file path, http or https address).
+   * @param [in] loadPol    The LoadPolicy to apply when loading the image resource.
+   * @param [in] releasePol The ReleasePolicy to apply to Image.
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @return A handle to a newly allocated object
+   */
+  static ResourceImage New( const std::string& url, LoadPolicy loadPol, ReleasePolicy releasePol, bool orientationCorrection = true );
+
+  /**
+   * @brief Create an initialised ResourceImage object.
+   *
+   * @since_tizen 2.4
+   * @privlevel public
+   * @privilege %http://tizen.org/privilege/internet
+   * @remarks %http://tizen.org/privilege/internet is needed if @a url is a http or https address.
+   * @param [in] url The URL of the image file to use (can be a local file path, http or https address).
+   * @param [in] size The width and height to fit the loaded image to.
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @return A handle to a newly allocated object
+   */
+  static ResourceImage New( const std::string& url,
+                            ImageDimensions size,
+                            FittingMode::Type fittingMode = FittingMode::DEFAULT,
+                            SamplingMode::Type samplingMode = SamplingMode::DEFAULT,
+                            bool orientationCorrection = true );
+
+  /**
+   * @brief Create an initialised ResourceImage object.
+   *
+   * @since_tizen 2.4
+   * @privlevel public
+   * @privilege %http://tizen.org/privilege/internet
+   * @remarks %http://tizen.org/privilege/internet is needed if @a url is a http or https address.
+   * @param [in] url The URL of the image file to use (can be a local file path, http or https address).
+   * @param [in] loadPol    The LoadPolicy to apply when loading the image resource.
+   * @param [in] releasePol The ReleasePolicy to apply to Image.
+   * @param [in] size The width and height to fit the loaded image to.
+   * @param [in] fittingMode The method used to fit the shape of the image before loading to the shape defined by the size parameter.
+   * @param [in] samplingMode The filtering method used when sampling pixels from the input image while fitting it to desired size.
+   * @param [in] orientationCorrection Reorient the image to respect any orientation metadata in its header.
+   * @return A handle to a newly allocated object
+   */
+  static ResourceImage New( const std::string& url,
+                            LoadPolicy loadPol,
+                            ReleasePolicy releasePol,
+                            ImageDimensions size,
+                            FittingMode::Type fittingMode = FittingMode::DEFAULT,
+                            SamplingMode::Type samplingMode = SamplingMode::DEFAULT,
+                            bool orientationCorrection = true );
+
+  ///@}
+
+  /**
+   * @brief Downcast an Object handle to ResourceImage handle.
+   *
+   * If handle points to a ResourceImage object the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a Image object or an uninitialized handle
+   */
+  static ResourceImage DownCast( BaseHandle handle );
+
+  /**
+   * @brief Return load policy.
+   *
+   * @since_tizen 2.4
+   * @return resource load policy
+   */
+  LoadPolicy GetLoadPolicy() const;
+
+  /**
+   * @brief Query whether the image data has loaded.
+   *
+   * The asynchronous loading begins when the Image object is created.
+   * After the Image object is discarded, the image data will be released from memory.
+   * @since_tizen 2.4
+   * @return The loading state, either Loading, Success or Failed.
+   */
+  LoadingState GetLoadingState() const;
+
+  /**
+   * @brief Returns the URL of the image.
+   *
+   * @since_tizen 2.4
+   * @return The URL of the image file.
+   */
+  std::string GetUrl() const;
+
+  /**
+   * @brief Reload image from filesystem.
+   *
+   * The original set of image loading attributes (requested dimensions, scaling
+   * mode and filter mode) are used when requesting the image again.
+   * @since_tizen 2.4
+   * @note If image is offstage and OnDemand policy is set, the reload request is
+   * ignored.
+   */
+  void Reload();
+
+public: // Signals
+
+  /**
+   * @brief Emitted when the image data loads successfully, or when the loading fails.
+   *
+   * @since_tizen 2.4
+   * @return A signal object to Connect() with.
+   */
+  ResourceImageSignal& LoadingFinishedSignal();
+
+public: // Not intended for application developers
+
+  explicit DALI_INTERNAL ResourceImage( Internal::ResourceImage* );
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_RESOURCE_IMAGE_H__
diff --git a/dali/public-api/math/angle-axis.h b/dali/public-api/math/angle-axis.h
new file mode 100644 (file)
index 0000000..c62ee0f
--- /dev/null
@@ -0,0 +1,89 @@
+#ifndef __DALI_ANGLE_AXIS_H__
+#define __DALI_ANGLE_AXIS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector3.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+struct Radian;
+
+/**
+ * @brief An angle & axis pair.
+ *
+ * This is slightly easier to understand than quaternions for handling rotations
+ * of objects. Both elements should be non-zero to correctly describe a rotation.
+ * @since_tizen 2.4
+ */
+struct AngleAxis
+{
+  /**
+   * @brief Create an angle-axis pair.
+   * @since_tizen 2.4
+   */
+  AngleAxis()
+  : angle(0.0f),
+    axis(0.0f, 0.0f, 0.0f)
+  { }
+
+  /**
+   * @brief Create an angle-axis pair.
+   *
+   * @since_tizen 2.4
+   * @param[in] initialAngle The initial angle in radians.
+   * @param[in] initialAxis The initial axis.
+   */
+  AngleAxis( Radian initialAngle, const Vector3& initialAxis )
+  : angle( initialAngle ),
+    axis( initialAxis )
+  { }
+
+  Radian angle; ///< The angle in radians
+  Vector3 axis; ///< The axis
+
+};
+
+// compiler generated destructor, copy constructor and assignment operators are ok as this class is POD
+
+/**
+ * @brief Compare two angle axis for equality
+ *
+ * @since_tizen 2.4
+ * @param lhs angle axis
+ * @param rhs angle axis
+ * @return true if they are equal
+ */
+inline bool operator==( const Dali::AngleAxis& lhs, const Dali::AngleAxis& rhs )
+{
+  return (lhs.angle == rhs.angle) && (lhs.axis == rhs.axis);
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ANGLE_AXIS_H__
diff --git a/dali/public-api/math/compile-time-math.cpp b/dali/public-api/math/compile-time-math.cpp
new file mode 100644 (file)
index 0000000..5199323
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/compile-time-math.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/compile-time-assert.h>
+
+namespace Dali
+{
+
+namespace
+{
+  // verification for static asserts, these get removed from final binary by the linker
+  const unsigned int value0 = Power<10,0>::value;
+  DALI_COMPILE_TIME_ASSERT( value0 == 1 ); // cannot have template with , inside macro... macros suck
+  const unsigned int value1 = Power<10,1>::value;
+  DALI_COMPILE_TIME_ASSERT( value1 == 10 );
+  const unsigned int value2 = Power<10,2>::value;
+  DALI_COMPILE_TIME_ASSERT( value2 == 100 );
+  const unsigned int value3 = Power<10,3>::value;
+  DALI_COMPILE_TIME_ASSERT( value3 == 1000 );
+  const unsigned int value4 = Power<4,4>::value;
+  DALI_COMPILE_TIME_ASSERT( value4 == 256 );
+
+  const unsigned int log0 = Log<0, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log0 == 0 );
+  const unsigned int log1 = Log<1, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log1 == 0 );
+  const unsigned int log2 = Log<2, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log2 == 1 );
+  const unsigned int log3 = Log<10, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log3 == 1 );
+  const unsigned int log4 = Log<100, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log4 == 2 );
+  const unsigned int log5 = Log<1000, 10>::value;
+  DALI_COMPILE_TIME_ASSERT( log5 == 3 );
+
+  const unsigned int logpow0 = Log<Power<10,0>::value, 10 >::value;
+  DALI_COMPILE_TIME_ASSERT( logpow0 == 0 );
+  const unsigned int logpow1 = Log<Power<2,0>::value, 2 >::value;
+  DALI_COMPILE_TIME_ASSERT( logpow1 == 0 );
+  const unsigned int logpow2 = Log<Power<10,2>::value, 10 >::value;
+  DALI_COMPILE_TIME_ASSERT( logpow2 == 2 );
+  const unsigned int logpow3 = Log<Power<2,2>::value, 2 >::value;
+  DALI_COMPILE_TIME_ASSERT( logpow3 == 2 );
+
+  const unsigned int powlog0 = Power<10, Log<10,10>::value >::value;
+  DALI_COMPILE_TIME_ASSERT( powlog0 == 10 );
+  const unsigned int powlog1 = Power<10, Log<100,10>::value >::value;
+  DALI_COMPILE_TIME_ASSERT( powlog1 == 100 );
+
+  // TODO unfortunately cannot static assert floats so cannot test EPSILON here...
+
+} // namespace
+
+} // namespace Dali
diff --git a/dali/public-api/math/compile-time-math.h b/dali/public-api/math/compile-time-math.h
new file mode 100644 (file)
index 0000000..570be1b
--- /dev/null
@@ -0,0 +1,176 @@
+#ifndef __DALI_COMPILE_TIME_MATH_H__
+#define __DALI_COMPILE_TIME_MATH_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdlib.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief Compile time template to calculate base to the power of N.
+ *
+ * Note! values need to be compile time constants
+ * Usage: <code>Power< 10, 2 >::value; // value=100</code>
+ * @since_tizen 2.4
+ * @param mantissa to raise to exponent
+ * @param N exponent to use for mantissa
+ */
+template< size_t mantissa, size_t exponent >
+struct Power
+{
+  enum { value = mantissa * Power< mantissa, exponent - 1 >::value };
+};
+
+/**
+ * @brief Compile time template to calculate base to the power of N.
+ *
+ * Specialisation for power of 1
+ * @since_tizen 2.4
+ * @param mantissa to raise to exponent
+ */
+template< size_t mantissa >
+struct Power< mantissa, 1 >
+{
+  enum { value = mantissa };
+};
+
+/**
+ * @brief Compile time template to calculate base to the power of N.
+ *
+ * Specialisation for power of 0
+ * @since_tizen 2.4
+ * @param mantissa to raise to exponent
+ */
+template< size_t mantissa >
+struct Power< mantissa, 0 >
+{
+  enum { value = 1 };
+};
+
+/**
+ * @brief Compile time template to calculate base logarithm of N.
+ *
+ * Note! values need to be compile time constants
+ * Usage: <code>Log< 100, 10 >::value; value equals 2</code>
+ * @since_tizen 2.4
+ * @param number for which to calculate the logarithm
+ * @param base logarithm to calculate
+ */
+template< size_t number, size_t base = 2 >
+struct Log
+{
+  enum { value = 1 + Log< number / base, base >::value };
+};
+
+/**
+ * @brief Compile time template to calculate base logarithm of N.
+ *
+ * Specialisation for logarithm of 1
+ * @since_tizen 2.4
+ * @param base logarithm to calculate
+ */
+template< size_t base >
+struct Log< 1, base >
+{
+  enum { value = 0 };
+};
+
+/**
+ * @brief Compile time template to calculate base logarithm of N.
+ *
+ * Specialisation for logarithm of 0
+ * @since_tizen 2.4
+ * @param base logarithm to calculate
+ */
+template< size_t base >
+struct Log< 0, base >
+{
+  enum { value = 0 };
+};
+
+
+/**
+ * @brief Compile time template to calculate the machine epsilon for a given floating point number.
+ *
+ * Note! value needs to be compile time constant
+ * Usage: <code>Epsilon<1000>::value; value equals 0.000119209</code>
+ * @since_tizen 2.4
+ * @param N the number for which to calculate the machine epsilon
+ */
+template< size_t N >
+struct Epsilon
+{
+  // take log10 of the number to get to the nearest power of 10 number and divide that by 10
+  // template recursion will take care of the rest
+#ifdef _CPP11
+  static constexpr float value = 10.0f * Epsilon< Power< 10, Log< N, 10 >::value >::value / 10 >::value;
+#else
+  static const float value = 10.0f * Epsilon< Power< 10, Log< N, 10 >::value >::value / 10 >::value;
+#endif
+};
+
+/**
+ * @brief Compile time template to calculate the machine epsilon for a given floating point number.
+ *
+ * Specialisation for epsilon of 1
+ * predefined value calculated on ARM Cortex A9 target
+ * @since_tizen 2.4
+ */
+template<>
+struct Epsilon< 1 >
+{
+#ifdef _CPP11
+  static constexpr float value = 1.19209e-07f;
+#else
+  static const float value = 1.19209e-07f;
+#endif
+};
+
+/**
+ * @brief Compile time template to calculate the machine epsilon for a given floating point number.
+ *
+ * Specialisation for epsilon of 0
+ * predefined value calculated on ARM Cortex A9 target
+ * @since_tizen 2.4
+ */
+template<>
+struct Epsilon< 0 >
+{
+#ifdef _CPP11
+  static constexpr float value = 1.4013e-45f;
+#else
+  static const float value = 1.4013e-45f;
+#endif
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_COMPILE_TIME_MATH_H__
diff --git a/dali/public-api/math/degree.cpp b/dali/public-api/math/degree.cpp
new file mode 100644 (file)
index 0000000..3e56ea3
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/degree.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/radian.h>
+
+namespace Dali
+{
+
+Degree::Degree( Radian radian )
+: degree( radian * Math::ONE80_OVER_PI )
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/degree.h b/dali/public-api/math/degree.h
new file mode 100644 (file)
index 0000000..4341f5d
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef __DALI_DEGREE_H__
+#define __DALI_DEGREE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/math-utils.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+struct Radian;
+
+/**
+ * @brief An angle in degrees.
+ *
+ * This reduces ambiguity when using methods which accept angles in degrees or radians.
+ * @since_tizen 2.4
+ */
+struct Degree
+{
+  /**
+   * @brief default constructor, initialises to 0.
+   * @since_tizen 2.4
+   */
+  Degree()
+  : degree( 0.f )
+  { }
+
+  /**
+   * @brief Create an angle in degrees.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The initial value in degrees.
+   */
+  explicit Degree( float value )
+  : degree( value )
+  { }
+
+  /**
+   * @brief Create an angle in degrees from a Radian.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The initial value in Radians.
+   */
+  DALI_EXPORT_API Degree( Radian value );
+
+public:
+
+  // member data
+  float degree; ///< The value in degrees
+
+};
+
+// compiler generated destructor, copy constructor and assignment operators are ok as this class is POD
+
+/**
+ * @brief Compare equality between two degrees.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Degree to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if the values are identical
+ */
+inline bool operator==( const Degree& lhs, const Degree& rhs )
+{
+  return fabsf( lhs.degree - rhs.degree ) < Math::MACHINE_EPSILON_1000; // expect degree angles to be between 0 and 1000
+}
+
+/**
+ * @brief Compare inequality between two degrees.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Degree to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if the values are not identical
+ */
+inline bool operator!=( const Degree& lhs, const Degree& rhs )
+{
+  return !( operator==( lhs, rhs ) );
+}
+
+/**
+ * @brief Clamp a radian value
+ * @since_tizen 2.4
+ * @param angle to clamp
+ * @param min value
+ * @param max value
+ * @return the resulting radian
+ */
+inline Degree Clamp( Degree angle, float min, float max )
+{
+  return Degree( Clamp<float>( angle.degree, min, max ) );
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_DEGREE_H__
diff --git a/dali/public-api/math/math-utils.h b/dali/public-api/math/math-utils.h
new file mode 100644 (file)
index 0000000..65fd3e6
--- /dev/null
@@ -0,0 +1,330 @@
+#ifndef __DALI_MATH_UTILS_H__
+#define __DALI_MATH_UTILS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/constants.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief Returns the next power of two.
+ *
+ * In case of numbers which are already a power of two this function returns the original number.
+ * If i is zero returns 1
+ * @since_tizen 2.4
+ * @param[in] i input number
+ * @return    next power of two or i itself in case it's a power of two
+ */
+inline unsigned int NextPowerOfTwo( unsigned int i )
+{
+  DALI_ASSERT_ALWAYS(i <= 1u << (sizeof(unsigned) * 8 - 1) && "Return type cannot represent the next power of two greater than the argument.");
+  if(i==0u)
+  {
+    return 1u;
+  }
+
+  i--;
+  i |= i >> 1;
+  i |= i >> 2;
+  i |= i >> 4;
+  i |= i >> 8;
+  i |= i >> 16;
+  i++;
+  return i;
+}
+
+/**
+ * @brief Whether a number is power of two.
+ *
+ * @since_tizen 2.4
+ * @param[in] i input number
+ * @return    true if i is power of two
+ */
+inline bool IsPowerOfTwo( unsigned int i )
+{
+  return (i != 0u) && ((i & (i - 1u)) == 0u);
+}
+
+/**
+ * @brief Clamp a value.
+ *
+ * @since_tizen 2.4
+ * @param[in] value The value to clamp.
+ * @param[in] min The minimum allowed value.
+ * @param[in] max The maximum allowed value.
+ * @return T the clamped value
+ */
+template< typename T >
+inline const T& Clamp( const T& value, const T& min, const T& max )
+{
+  const T& constrainedUpper = value < max ? value : max;
+  const T& constrainedUpperAndLower = constrainedUpper > min ? constrainedUpper : min;
+  return  constrainedUpperAndLower;
+}
+
+/**
+ * @brief Clamp a value directly.
+ *
+ * @since_tizen 2.4
+ * @param[in,out] value The value that will be clamped.
+ * @param[in] min The minimum allowed value.
+ * @param[in] max The maximum allowed value.
+ */
+template< typename T >
+inline void ClampInPlace( T& value, const T& min, const T& max )
+{
+  const T& constrainedUpper = value < max ? value : max;
+  const T& constrainedUpperAndLower = constrainedUpper > min ? constrainedUpper : min;
+  value = constrainedUpperAndLower;
+}
+
+
+/**
+ * @brief Linear interpolation between two values.
+ *
+ * @since_tizen 2.4
+ * @param[in] offset The offset through the range @p low to @p high.
+ *                   This value is clamped between 0 and 1
+ * @param[in] low    Lowest value in range
+ * @param[in] high   Highest value in range
+ * @return A value between low and high.
+ */
+template< typename T >
+inline const T Lerp( const float offset, const T& low, const T& high )
+{
+  return low + ((high - low) * Clamp(offset, 0.0f, 1.0f));
+}
+
+/**
+ * @brief Get an epsilon that is valid for the given range.
+ *
+ * @since_tizen 2.4
+ * @param[in] a the first value in the range
+ * @param[in] b the second value in the range.
+ * @return a suitable epsilon
+ */
+inline float GetRangedEpsilon( float a, float b )
+{
+  const float absA = fabsf( a );
+  const float absB = fabsf( b );
+  const float absF = absA > absB ? absA : absB;
+  const int absI = absF;
+
+  float epsilon = Math::MACHINE_EPSILON_10000;
+  if (absF < 0.1f)
+  {
+    return Math::MACHINE_EPSILON_0;
+  }
+  else if (absI < 2)
+  {
+    return Math::MACHINE_EPSILON_1;
+  }
+  else if (absI < 20)
+  {
+    return Math::MACHINE_EPSILON_10;
+  }
+  else if (absI < 200)
+  {
+    return Math::MACHINE_EPSILON_100;
+  }
+  else if (absI < 2000)
+  {
+    return Math::MACHINE_EPSILON_1000;
+  }
+  return epsilon;
+}
+
+/**
+ * @brief Helper function to compare equality of a floating point value with zero.
+ *
+ * @since_tizen 2.4
+ * @param[in] value the value to compare
+ * @return true if the value is equal to zero
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wfloat-equal"
+inline bool EqualsZero( float value )
+{
+  return value == 0.0f;
+}
+#pragma GCC diagnostic pop
+
+/**
+ * @brief Helper function to compare equality of two floating point values.
+ *
+ * @since_tizen 2.4
+ * @param[in] a the first value to compare
+ * @param[in] b the second value to compare
+ * @return true if the values are equal within a minimal epsilon for their values
+ */
+inline bool Equals( float a, float b )
+{
+  return ( fabsf( a - b ) <= GetRangedEpsilon( a, b ) );
+}
+
+/**
+ * @brief Helper function to compare equality of two floating point values.
+ *
+ * @since_tizen 2.4
+ * @param[in] a the first value to compare
+ * @param[in] b the second value to compare
+ * @param[in] epsilon the minimum epsilon value that will be used to consider the values different
+ * @return true if the difference between the values is less than the epsilon
+ */
+inline bool Equals( float a, float b, float epsilon )
+{
+  return ( fabsf( a - b ) <= epsilon );
+}
+
+/**
+ * @brief Get an float that is rounded at specified place of decimals.
+ *
+ * @since_tizen 2.4
+ * @param[in] value float value
+ * @param[in] pos decimal place
+ * @return a rounded float
+ */
+inline float Round(float value, int pos)
+{
+  float temp;
+  temp = value * powf( 10, pos );
+  temp = floorf( temp + 0.5 );
+  temp *= powf( 10, -pos );
+  return temp;
+}
+
+/**
+ * @brief Wrap x in domain (start) to (end).
+ *
+ * This works like a floating point version
+ * of the % modulo operation. But with an offset (start).
+ *
+ * For instance a domain is specified as:
+ * start: 2
+ * end: 8
+ *
+ *   2                         8
+ * (\ / start)               (\ / end)
+ *   |----x                    |
+ *
+ * The value x will be confined to this domain.
+ * If x is below 2 e.g. 0, then it is wraped to 6.
+ * If x is above or equal to 8 e.g. 8.1 then it is
+ * wrapped to 2.1
+ *
+ * Domain wrapping is useful for various problems from
+ * calculating positions in a space that repeats, to
+ * computing angles that range from 0 to 360.
+ *
+ * @since_tizen 2.4
+ * @param[in] x the point to be wrapped within the domain
+ * @param[in] start The start of the domain
+ * @param[in] end The end of the domain
+ *
+ * @return the wrapped value over the domain (start) (end)
+ * @note if start = end (i.e. size of domain 0), then wrapping will not occur
+ * and result will always be equal to start.
+ *
+ */
+inline float WrapInDomain(float x, float start, float end)
+{
+  float domain = end - start;
+  x -= start;
+
+  if(fabsf(domain) > Math::MACHINE_EPSILON_1)
+  {
+    return start + (x - floorf(x / domain) * domain);
+  }
+
+  return start;
+}
+
+
+/**
+ * @brief Find the shortest distance (magnitude) and direction (sign)
+ * from (a) to (b) in domain (start) to (end).
+ *
+ * (\ / start)               (\ / end)
+ *   |-a                 b<----|
+ *
+ * Knowing the shortest distance is useful with wrapped domains
+ * to solve problems such as determing the closest object to
+ * a given point, or determing whether turning left or turning
+ * right is the shortest route to get from angle 10 degrees
+ * to angle 350 degrees (clearly in a 0-360 degree domain, turning
+ * left 20 degrees is quicker than turning right 340 degrees).
+ *
+ * The value returned holds the distance and the direction from
+ * value a to value b. For instance in the above example it would
+ * return -20. i.e. subtract 20 from current value (10) to reach
+ * target wrapped value (350).
+ *
+ * @since_tizen 2.4
+ * @param a the current value
+ * @param b the target value
+ * @param start the start of the domain
+ * @param end the end of the domain
+ * @return the shortest direction (the sign) and distance (the magnitude)
+ * @note assumes both (a) and (b) are already within the domain
+ * (start) to (end)
+ *
+ */
+inline float ShortestDistanceInDomain( float a, float b, float start, float end )
+{
+  //  (a-start + end-b)
+  float size = end-start;
+  float vect = b-a;
+
+  if(vect > 0)
+  {
+    // +ve vector, let's try perspective 1 domain to the right,
+    // and see if closer.
+    float aRight = a+size;
+    if( aRight-b < vect )
+    {
+      return b-aRight;
+    }
+  }
+  else
+  {
+    // -ve vector, let's try perspective 1 domain to the left,
+    // and see if closer.
+    float aLeft = a-size;
+    if( aLeft-b > vect )
+    {
+      return b-aLeft;
+    }
+  }
+
+  return vect;
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_MATH_UTILS_H__
diff --git a/dali/public-api/math/matrix.cpp b/dali/public-api/math/matrix.cpp
new file mode 100644 (file)
index 0000000..67ade79
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADERS
+#include <dali/public-api/math/matrix.h>
+
+// EXTERNAL INCLUDES
+#include <cmath>
+#include <cstring> // for memcpy
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace
+{
+const float ROTATION_EPSILON = 0.003f; // Deliberately large
+
+const size_t NUM_BYTES_IN_ROW_OF_3( 3 * sizeof( float ) );
+const size_t NUM_BYTES_IN_ROW( 4 * sizeof( float ) );
+const size_t NUM_BYTES_IN_MATRIX( 16 * sizeof( float ) );
+const size_t ROW1_OFFSET( 4 );
+const size_t ROW2_OFFSET( 8 );
+const size_t ROW3_OFFSET( 12 );
+
+/**
+ * Helper to convert to Quaternion to float16 array
+ */
+void Convert( float*& m, const Dali::Quaternion& rotation )
+{
+  const float xx = rotation.mVector.x * rotation.mVector.x;
+  const float yy = rotation.mVector.y * rotation.mVector.y;
+  const float zz = rotation.mVector.z * rotation.mVector.z;
+  const float xy = rotation.mVector.x * rotation.mVector.y;
+  const float xz = rotation.mVector.x * rotation.mVector.z;
+  const float wx = rotation.mVector.w * rotation.mVector.x;
+  const float wy = rotation.mVector.w * rotation.mVector.y;
+  const float wz = rotation.mVector.w * rotation.mVector.z;
+  const float yz = rotation.mVector.y * rotation.mVector.z;
+
+  m[0] = 1.0f - 2.0f * (yy + zz);
+  m[1] =        2.0f * (xy + wz);
+  m[2] =        2.0f * (xz - wy);
+  m[3] = 0.0f;
+
+  m[4] =        2.0f * (xy - wz);
+  m[5] = 1.0f - 2.0f * (xx + zz);
+  m[6] =        2.0f * (yz + wx);
+  m[7] = 0.0f;
+
+  m[8] =        2.0f * (xz + wy);
+  m[9] =        2.0f * (yz - wx);
+  m[10]= 1.0f - 2.0f * (xx + yy);
+  m[11]= 0.0f;
+
+  m[12]= 0.0f;
+  m[13]= 0.0f;
+  m[14]= 0.0f;
+  m[15]= 1.0f;
+}
+}
+
+namespace Dali
+{
+
+using Internal::PerformanceMonitor;
+
+const float identityArray[] = {1.0f, 0.0f, 0.0f, 0.0f,
+                               0.0f, 1.0f, 0.0f, 0.0f,
+                               0.0f, 0.0f, 1.0f, 0.0f,
+                               0.0f, 0.0f, 0.0f, 1.0f};
+
+const Matrix Matrix::IDENTITY(identityArray);
+
+Matrix::Matrix()
+{
+  memset( mMatrix, 0, NUM_BYTES_IN_MATRIX );
+}
+
+Matrix::Matrix( bool initialize )
+{
+  if( initialize )
+  {
+    memset( mMatrix, 0, NUM_BYTES_IN_MATRIX );
+  }
+}
+
+Matrix::Matrix(const float* array)
+{
+  memcpy( mMatrix, array, NUM_BYTES_IN_MATRIX );
+}
+
+Matrix::Matrix( const Quaternion& rotation )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,18);
+
+  float* matrixPtr = &mMatrix[0];
+  Convert( matrixPtr, rotation );
+}
+
+Matrix::Matrix( const Matrix& matrix )
+{
+  memcpy( mMatrix, matrix.mMatrix, NUM_BYTES_IN_MATRIX );
+}
+
+Matrix& Matrix::operator=( const Matrix& matrix )
+{
+  // no point copying if self assigning
+  if( this != &matrix )
+  {
+    memcpy( mMatrix, matrix.mMatrix, NUM_BYTES_IN_MATRIX );
+  }
+  return *this;
+}
+
+void Matrix::InvertTransform(Matrix& result) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,12);
+
+  float* m1 = result.AsFloat();
+
+  DALI_ASSERT_ALWAYS( EqualsZero( mMatrix[3] ) && EqualsZero( mMatrix[7] ) && EqualsZero( mMatrix[11] ) && Equals( mMatrix[15], 1.0f ) && "Must be a transform matrix" );
+
+  m1[0] = mMatrix[0];
+  m1[1] = mMatrix[4];
+  m1[2] = mMatrix[8];
+  m1[3] = 0.0f;
+
+  m1[4] = mMatrix[1];
+  m1[5] = mMatrix[5];
+  m1[6] = mMatrix[9];
+  m1[7] = 0.0f;
+
+  m1[8] = mMatrix[2];
+  m1[9] = mMatrix[6];
+  m1[10] = mMatrix[10];
+  m1[11] = 0.0f;
+
+  m1[12] = -( ( mMatrix[0] * mMatrix[12] ) + ( mMatrix[1] * mMatrix[13] ) + ( mMatrix[2] * mMatrix[14] ) + ( mMatrix[3] * mMatrix[15] ) );
+  m1[13] = -( ( mMatrix[4] * mMatrix[12] ) + ( mMatrix[5] * mMatrix[13] ) + ( mMatrix[6] * mMatrix[14] ) + ( mMatrix[7] * mMatrix[15] ) );
+  m1[14] = -( ( mMatrix[8] * mMatrix[12] ) + ( mMatrix[9] * mMatrix[13] ) + ( mMatrix[10] * mMatrix[14] ) + ( mMatrix[11] * mMatrix[15] ) );
+  m1[15] = 1.0f;
+}
+
+static bool InvertMatrix(const float* m, float* out)
+{
+  float inv[16];
+
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,192);  // 12 x 16 multiples
+
+  inv[0] =   m[5]*m[10]*m[15] - m[5]*m[11]*m[14] - m[9]*m[6]*m[15] + m[9]*m[7]*m[14] + m[13]*m[6]*m[11] - m[13]*m[7]*m[10];
+  inv[4] =  -m[4]*m[10]*m[15] + m[4]*m[11]*m[14] + m[8]*m[6]*m[15] - m[8]*m[7]*m[14] - m[12]*m[6]*m[11] + m[12]*m[7]*m[10];
+  inv[8] =   m[4]*m[9]*m[15] - m[4]*m[11]*m[13] - m[8]*m[5]*m[15] + m[8]*m[7]*m[13] + m[12]*m[5]*m[11] - m[12]*m[7]*m[9];
+  inv[12] = -m[4]*m[9]*m[14] + m[4]*m[10]*m[13] + m[8]*m[5]*m[14] - m[8]*m[6]*m[13] - m[12]*m[5]*m[10] + m[12]*m[6]*m[9];
+  inv[1] =  -m[1]*m[10]*m[15] + m[1]*m[11]*m[14] + m[9]*m[2]*m[15] - m[9]*m[3]*m[14] - m[13]*m[2]*m[11] + m[13]*m[3]*m[10];
+  inv[5] =   m[0]*m[10]*m[15] - m[0]*m[11]*m[14] - m[8]*m[2]*m[15] + m[8]*m[3]*m[14] + m[12]*m[2]*m[11] - m[12]*m[3]*m[10];
+  inv[9] =  -m[0]*m[9]*m[15] + m[0]*m[11]*m[13] + m[8]*m[1]*m[15] - m[8]*m[3]*m[13] - m[12]*m[1]*m[11] + m[12]*m[3]*m[9];
+  inv[13] =  m[0]*m[9]*m[14] - m[0]*m[10]*m[13] - m[8]*m[1]*m[14] + m[8]*m[2]*m[13] + m[12]*m[1]*m[10] - m[12]*m[2]*m[9];
+  inv[2] =   m[1]*m[6]*m[15] - m[1]*m[7]*m[14] - m[5]*m[2]*m[15] + m[5]*m[3]*m[14] + m[13]*m[2]*m[7] - m[13]*m[3]*m[6];
+  inv[6] =  -m[0]*m[6]*m[15] + m[0]*m[7]*m[14] + m[4]*m[2]*m[15] - m[4]*m[3]*m[14] - m[12]*m[2]*m[7] + m[12]*m[3]*m[6];
+  inv[10] =  m[0]*m[5]*m[15] - m[0]*m[7]*m[13] - m[4]*m[1]*m[15] + m[4]*m[3]*m[13] + m[12]*m[1]*m[7] - m[12]*m[3]*m[5];
+  inv[14] = -m[0]*m[5]*m[14] + m[0]*m[6]*m[13] + m[4]*m[1]*m[14] - m[4]*m[2]*m[13] - m[12]*m[1]*m[6] + m[12]*m[2]*m[5];
+  inv[3] =  -m[1]*m[6]*m[11] + m[1]*m[7]*m[10] + m[5]*m[2]*m[11] - m[5]*m[3]*m[10] - m[9]*m[2]*m[7] + m[9]*m[3]*m[6];
+  inv[7] =   m[0]*m[6]*m[11] - m[0]*m[7]*m[10] - m[4]*m[2]*m[11] + m[4]*m[3]*m[10] + m[8]*m[2]*m[7] - m[8]*m[3]*m[6];
+  inv[11] = -m[0]*m[5]*m[11] + m[0]*m[7]*m[9] + m[4]*m[1]*m[11] - m[4]*m[3]*m[9] - m[8]*m[1]*m[7] + m[8]*m[3]*m[5];
+  inv[15] =  m[0]*m[5]*m[10] - m[0]*m[6]*m[9] - m[4]*m[1]*m[10] + m[4]*m[2]*m[9] + m[8]*m[1]*m[6] - m[8]*m[2]*m[5];
+
+  float det = m[0]*inv[0] + m[1]*inv[4] + m[2]*inv[8] + m[3]*inv[12];
+
+  // In the case where the determinant is exactly zero, the matrix is non-invertible
+  if ( EqualsZero( det ) )
+  {
+    return false;
+  }
+
+  det = 1.0 / det;
+
+  for (int i = 0; i < 16; i++)
+  {
+    out[i] = inv[i] * det;
+  }
+
+  return true;
+}
+
+bool Matrix::Invert()
+{
+  Matrix temp(*this);
+
+  return InvertMatrix(temp.AsFloat(), mMatrix);
+}
+
+void Matrix::Transpose()
+{
+  float temp = mMatrix[1];
+  mMatrix[1] = mMatrix[4];
+  mMatrix[4] = temp;
+
+  temp = mMatrix[2];
+  mMatrix[2] = mMatrix[8];
+  mMatrix[8] = temp;
+
+  temp = mMatrix[3];
+  mMatrix[3] = mMatrix[12];
+  mMatrix[12] = temp;
+
+  temp = mMatrix[6];
+  mMatrix[6] = mMatrix[9];
+  mMatrix[9] = temp;
+
+  temp = mMatrix[7];
+  mMatrix[7] = mMatrix[13];
+  mMatrix[13] = temp;
+
+  temp = mMatrix[11];
+  mMatrix[11] = mMatrix[14];
+  mMatrix[14] = temp;
+}
+
+void Matrix::SetIdentity()
+{
+  memcpy( mMatrix, identityArray, NUM_BYTES_IN_MATRIX );
+}
+
+void Matrix::SetIdentityAndScale( const Vector3& scale )
+{
+  // initialize to zeros
+  memset( mMatrix, 0, NUM_BYTES_IN_MATRIX );
+
+  // just apply scale on the diagonal
+  mMatrix[0]  = scale.x;
+  mMatrix[5]  = scale.y;
+  mMatrix[10] = scale.z;
+  mMatrix[15] = 1.0f;
+}
+
+void Matrix::SetTranslation(const Vector4& translation)
+{
+  memcpy( mMatrix + ROW3_OFFSET, &translation, NUM_BYTES_IN_ROW );
+}
+void Matrix::SetTranslation(const Vector3& other)
+{
+  memcpy( mMatrix + ROW3_OFFSET, &other, NUM_BYTES_IN_ROW_OF_3 );
+  mMatrix[15] = 1.0f;
+}
+
+void Matrix::Multiply( Matrix& result, const Matrix& lhs, const Matrix& rhs )
+{
+  MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,64); // 64 = 16*4
+
+  float* temp = result.AsFloat();
+  const float* rhsPtr  = rhs.AsFloat();
+  const float* lhsPtr = lhs.AsFloat();
+
+#ifndef  __ARM_NEON__
+
+  for( int i=0; i < 4; i++ )
+  {
+    // i<<2 gives the first vector / column
+    int loc = i<<2;
+    int loc1 = loc + 1;
+    int loc2 = loc + 2;
+    int loc3 = loc + 3;
+    float value0 = lhsPtr[loc];
+    float value1 = lhsPtr[loc1];
+    float value2 = lhsPtr[loc2];
+    float value3 = lhsPtr[loc3];
+    temp[loc]  = (value0 * rhsPtr[0]) +
+                 (value1 * rhsPtr[4]) +
+                 (value2 * rhsPtr[8]) +
+                 (value3 * rhsPtr[12]);
+
+    temp[loc1] = (value0 * rhsPtr[1]) +
+                 (value1 * rhsPtr[5]) +
+                 (value2 * rhsPtr[9]) +
+                 (value3 * rhsPtr[13]);
+
+    temp[loc2] = (value0 * rhsPtr[2]) +
+                 (value1 * rhsPtr[6]) +
+                 (value2 * rhsPtr[10])+
+                 (value3 * rhsPtr[14]);
+
+    temp[loc3] = (value0 * rhsPtr[3]) +
+                 (value1 * rhsPtr[7]) +
+                 (value2 * rhsPtr[11])+
+                 (value3 * rhsPtr[15]);
+  }
+
+#else
+
+  // 64 32bit registers,
+  // aliased to
+  // d = 64 bit double-word d0 -d31
+  // q =128 bit quad-word   q0 -q15  (enough to handle a column of 4 floats in a matrix)
+  // e.g. q0 = d0 and d1
+
+  // load and stores interleaved as NEON can load and store while calculating
+  asm volatile ( "VLDM         %1,  {q0-q3}        \n\t"   // load matrix 1 (lhsPtr) q[0..q3]
+                 "VLDM         %0,  {q8-q11}       \n\t"   // load matrix 2 (rhsPtr) q[q8-q11]
+                 "VMUL.F32     q12, q8, d0[0]      \n\t"   // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
+                 "VMUL.F32     q13, q8, d2[0]      \n\t"   // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
+                 "VMUL.F32     q14, q8, d4[0]      \n\t"   // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
+                 "VMUL.F32     q15, q8, d6[0]      \n\t"   // column 3 = rhsPtr[0..3] * lhsPtr[12..15]
+
+                 "VMLA.F32     q12, q9, d0[1]      \n\t"   // column 0 += rhsPtr[4..7] * lhsPtr[0..3]
+                 "VMLA.F32     q13, q9, d2[1]      \n\t"   // column 1 += rhsPtr[4..7] * lhsPtr[4..7]
+                 "VMLA.F32     q14, q9, d4[1]      \n\t"   // column 2 += rhsPtr[4..7] * lhsPtr[8..11]
+                 "VMLA.F32     q15, q9, d6[1]      \n\t"   // column 3 += rhsPtr[4..7] * lhsPtr[12..15]
+
+                 "VMLA.F32     q12, q10, d1[0]     \n\t"   // column 0 += rhsPtr[8..11] * lhsPtr[0..3]
+                 "VMLA.F32     q13, q10, d3[0]     \n\t"   // column 1 += rhsPtr[8..11] * lhsPtr[4..7]
+                 "VMLA.F32     q14, q10, d5[0]     \n\t"   // column 2 += rhsPtr[8..11] * lhsPtr[8..11]
+                 "VMLA.F32     q15, q10, d7[0]     \n\t"   // column 3 += rhsPtr[8..11] * lhsPtr[12..15]
+
+                 "VMLA.F32     q12, q11, d1[1]     \n\t"   // column 0 += rhsPtr[12..15] * lhsPtr[0..3]
+                 "VMLA.F32     q13, q11, d3[1]     \n\t"   // column 1 += rhsPtr[12..15] * lhsPtr[4..7]
+                 "VMLA.F32     q14, q11, d5[1]     \n\t"   // column 2 += rhsPtr[12..15] * lhsPtr[8..11]
+                 "VMLA.F32     q15, q11, d7[1]     \n\t"   // column 3 += rhsPtr[12..15] * lhsPtr[12..15]
+                 "VSTM         %2,  {q12-q15}      \n\t"   // store entire output matrix.
+                 : "+r"(rhsPtr), "+r"(lhsPtr), "+r"(temp)
+                 :
+                 : "q0", "q1", "q2", "q3", "q8", "q9", "q10", "q11", "q12", "q13", "q14", "q15", "memory" );
+
+#endif
+}
+
+void Matrix::Multiply( Matrix& result, const Matrix& lhs, const Quaternion& rhs )
+{
+  MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,54); // 54 = 36+18
+
+  float matrix[16];
+  float* rhsPtr = &matrix[0];
+  Convert( rhsPtr, rhs );
+
+  // quaternion contains just rotation so it really only needs 3x3 matrix
+
+  float* temp = result.AsFloat();
+  const float* lhsPtr = lhs.AsFloat();
+
+#ifndef  __ARM_NEON__
+
+  for( int i=0; i < 4; i++ )
+  {
+    // i<<2 gives the first vector / column
+    int loc = i<<2;
+    int loc1 = loc + 1;
+    int loc2 = loc + 2;
+    int loc3 = loc + 3;
+    float value0 = lhsPtr[loc];
+    float value1 = lhsPtr[loc1];
+    float value2 = lhsPtr[loc2];
+    float value3 = lhsPtr[loc3];
+    temp[loc]  = (value0 * rhsPtr[0]) +
+                 (value1 * rhsPtr[4]) +
+                 (value2 * rhsPtr[8]) +
+                 (0.0f); //value3 * rhsPtr[12] is 0.0f
+
+    temp[loc1] = (value0 * rhsPtr[1]) +
+                 (value1 * rhsPtr[5]) +
+                 (value2 * rhsPtr[9]) +
+                 (0.0f); //value3 * rhsPtr[13] is 0.0f
+
+    temp[loc2] = (value0 * rhsPtr[2]) +
+                 (value1 * rhsPtr[6]) +
+                 (value2 * rhsPtr[10])+
+                 (0.0f); //value3 * rhsPtr[14] is 0.0f
+
+    temp[loc3] = (0.0f) + //value0 * rhsPtr[3] is 0.0f
+                 (0.0f) + //value1 * rhsPtr[7] is 0.0f
+                 (0.0f) + //value2 * rhsPtr[11] is 0.0f
+                 (value3); // rhsPtr[15] is 1.0f
+  }
+
+#else
+
+  // 64 32bit registers,
+  // aliased to
+  // d = 64 bit double-word d0 -d31
+  // q =128 bit quad-word   q0 -q15  (enough to handle a column of 4 floats in a matrix)
+  // e.g. q0 = d0 and d1
+  // load and stores interleaved as NEON can load and store while calculating
+  asm volatile ( "VLDM         %1,   {q4-q6}       \n\t" // load matrix 1 (lhsPtr)
+                 "VLD1.F32     {q7}, [%2]!         \n\t" // load matrix 2 (rhsPtr) [0..3]
+                 "VMUL.F32     q0,   q7,   d8[0]   \n\t" // column 0 = rhsPtr[0..3] * lhsPtr[0..3]
+                 "VMUL.F32     q1,   q7,   d10[0]  \n\t" // column 1 = rhsPtr[0..3] * lhsPtr[4..7]
+                 "VMUL.F32     q2,   q7,   d12[0]  \n\t" // column 2 = rhsPtr[0..3] * lhsPtr[8..11]
+                 "VLD1.F32     {q7}, [%2]!         \n\t" // load matrix 2 (rhsPtr) [4..7]
+                 "VMLA.F32     q0,   q7,   d8[1]   \n\t" // column 0+= rhsPtr[4..7] * lhsPtr[0..3]
+                 "VMLA.F32     q1,   q7,   d10[1]  \n\t" // column 1+= rhsPtr[4..7] * lhsPtr[4..7]
+                 "VMLA.F32     q2,   q7,   d12[1]  \n\t" // column 2+= rhsPtr[4..7] * lhsPtr[8..11]
+                 "VLD1.F32     {q7}, [%2]!         \n\t" // load matrix 2 (rhsPtr) [8..11]
+                 "VMLA.F32     q0,   q7,   d9[0]   \n\t" // column 0+= rhsPtr[8..11] * lhsPtr[0..3]
+                 "VMLA.F32     q1,   q7,   d11[0]  \n\t" // column 1+= rhsPtr[8..11] * lhsPtr[4..7]
+                 "VMLA.F32     q2,   q7,   d13[0]  \n\t" // column 2+= rhsPtr[8..11] * lhsPtr[8..11]
+                 "VSTM         %0,   {q0-q2}       \n\t" // store entire output matrix.
+                 :
+                 : "r"(temp), "r"(lhsPtr), "r" (rhsPtr)
+                 : "%r0", "%q0", "%q1", "%q2", "%q4", "%q5", "%q6", "%q7", "memory" );
+
+  temp[ 12 ] = 0.0f;
+  temp[ 13 ] = 0.0f;
+  temp[ 14 ] = 0.0f;
+  temp[ 15 ] = 1.0f;
+#endif
+}
+
+Vector4 Matrix::operator*(const Vector4& rhs) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,16);
+
+  Vector4 temp;
+
+#ifndef  __ARM_NEON__
+
+  temp.x = rhs.x * mMatrix[0] + rhs.y * mMatrix[4] + rhs.z * mMatrix[8]  +  rhs.w * mMatrix[12];
+  temp.y = rhs.x * mMatrix[1] + rhs.y * mMatrix[5] + rhs.z * mMatrix[9]  +  rhs.w * mMatrix[13];
+  temp.z = rhs.x * mMatrix[2] + rhs.y * mMatrix[6] + rhs.z * mMatrix[10] +  rhs.w * mMatrix[14];
+  temp.w = rhs.x * mMatrix[3] + rhs.y * mMatrix[7] + rhs.z * mMatrix[11] +  rhs.w * mMatrix[15];
+
+#else
+
+  // 64 32bit registers,
+  // aliased to
+  // d = 64 bit double-word d0 -d31
+  // q =128 bit quad-word   q0 -q15  (enough to handle a column of 4 floats in a matrix)
+  // e.g. q0 = d0 and d1
+  // load and stores interleaved as NEON can load and store while calculating
+  asm volatile ( "VLD1.F32     {q0}, [%1]        \n\t"   //q0 = rhs
+                 "VLD1.F32     {q9}, [%0]!       \n\t"
+                 "VMUL.F32     q10,  q9,   d0[0] \n\t"
+                 "VLD1.F32     {q9}, [%0]!       \n\t"
+                 "VMLA.F32     q10,  q9,   d0[1] \n\t"   //q10 = mMatrix[0..3] * rhs + mMatrix[4..7] * rhs
+                 "VLD1.F32     {q9}, [%0]!       \n\t"
+                 "VMUL.F32     q11,  q9,   d1[0] \n\t"
+                 "VLD1.F32     {q9}, [%0]!       \n\t"
+                 "VMLA.F32     q11,  q9,   d1[1] \n\t"   //q11 = mMatrix[8..11] * rhs + mMatrix[12..15] * rhs
+                 "VADD.F32     q10,  q10,  q11   \n\t"
+                 "VST1.F32     {q10},[%2]        \n\t"   //temp = q10 + q11
+                 :
+                 : "r"(mMatrix), "r"(&rhs), "r"(&temp)
+                 : "q0", "q9", "q10", "q11", "memory" );
+#endif
+  return temp;
+}
+
+bool Matrix::operator==(const Matrix& rhs) const
+{
+  return (
+  ( fabsf( mMatrix[0] - rhs.mMatrix[0] ) <= GetRangedEpsilon( mMatrix[0], rhs.mMatrix[0] ) ) &&
+  ( fabsf( mMatrix[1] - rhs.mMatrix[1] ) <= GetRangedEpsilon( mMatrix[1], rhs.mMatrix[1] ) ) &&
+  ( fabsf( mMatrix[2] - rhs.mMatrix[2] ) <= GetRangedEpsilon( mMatrix[2], rhs.mMatrix[2] ) ) &&
+  ( fabsf( mMatrix[3] - rhs.mMatrix[3] ) <= GetRangedEpsilon( mMatrix[3], rhs.mMatrix[3] ) ) &&
+  ( fabsf( mMatrix[4] - rhs.mMatrix[4] ) <= GetRangedEpsilon( mMatrix[4], rhs.mMatrix[4] ) ) &&
+  ( fabsf( mMatrix[5] - rhs.mMatrix[5] ) <= GetRangedEpsilon( mMatrix[5], rhs.mMatrix[5] ) ) &&
+  ( fabsf( mMatrix[6] - rhs.mMatrix[6] ) <= GetRangedEpsilon( mMatrix[6], rhs.mMatrix[6] ) ) &&
+  ( fabsf( mMatrix[7] - rhs.mMatrix[7] ) <= GetRangedEpsilon( mMatrix[7], rhs.mMatrix[7] ) ) &&
+  ( fabsf( mMatrix[8] - rhs.mMatrix[8] ) <= GetRangedEpsilon( mMatrix[8], rhs.mMatrix[8] ) ) &&
+  ( fabsf( mMatrix[9] - rhs.mMatrix[9] ) <= GetRangedEpsilon( mMatrix[9], rhs.mMatrix[9] ) ) &&
+  ( fabsf( mMatrix[10] - rhs.mMatrix[10] ) <= GetRangedEpsilon( mMatrix[10], rhs.mMatrix[10] ) ) &&
+  ( fabsf( mMatrix[11] - rhs.mMatrix[11] ) <= GetRangedEpsilon( mMatrix[11], rhs.mMatrix[11] ) ) &&
+  ( fabsf( mMatrix[12] - rhs.mMatrix[12] ) <= GetRangedEpsilon( mMatrix[12], rhs.mMatrix[12] ) ) &&
+  ( fabsf( mMatrix[13] - rhs.mMatrix[13] ) <= GetRangedEpsilon( mMatrix[13], rhs.mMatrix[13] ) ) &&
+  ( fabsf( mMatrix[14] - rhs.mMatrix[14] ) <= GetRangedEpsilon( mMatrix[14], rhs.mMatrix[14] ) ) &&
+  ( fabsf( mMatrix[15] - rhs.mMatrix[15] ) <= GetRangedEpsilon( mMatrix[15], rhs.mMatrix[15] ) ) );
+}
+
+bool Matrix::operator!=(const Matrix& rhs) const
+{
+  if (*this == rhs)
+  {
+    return false;
+  }
+
+  return true;
+}
+
+void Matrix::OrthoNormalize()
+{
+  Vector4 vector0(GetXAxis());
+  Vector4 vector1(GetYAxis());
+  Vector4 vector2(GetZAxis());
+
+  vector0.Normalize();
+  vector1.Normalize();
+  vector2 = vector0.Cross( vector1 );
+  vector1 = vector2.Cross( vector0 );
+
+  memcpy( mMatrix, &vector0, NUM_BYTES_IN_ROW );
+  memcpy( mMatrix + ROW1_OFFSET, &vector1, NUM_BYTES_IN_ROW );
+  memcpy( mMatrix + ROW2_OFFSET, &vector2, NUM_BYTES_IN_ROW );
+}
+
+Vector3 Matrix::GetXAxis() const
+{
+  return Vector3(mMatrix[0], mMatrix[1], mMatrix[2]);
+}
+
+Vector3 Matrix::GetYAxis() const
+{
+  return Vector3(mMatrix[4], mMatrix[5], mMatrix[6]);
+}
+
+Vector3 Matrix::GetZAxis() const
+{
+  return Vector3(mMatrix[8], mMatrix[9], mMatrix[10]);
+}
+
+void Matrix::SetXAxis(const Vector3& axis)
+{
+  mMatrix[0] = axis.x;
+  mMatrix[1] = axis.y;
+  mMatrix[2] = axis.z;
+}
+
+void Matrix::SetYAxis(const Vector3& axis)
+{
+  mMatrix[4] = axis.x;
+  mMatrix[5] = axis.y;
+  mMatrix[6] = axis.z;
+}
+
+void Matrix::SetZAxis(const Vector3& axis)
+{
+  mMatrix[8] = axis.x;
+  mMatrix[9] = axis.y;
+  mMatrix[10] = axis.z;
+}
+
+void Matrix::SetTransformComponents(const Vector3&    scale,
+                                    const Quaternion& rotation,
+                                    const Vector3&    translation )
+{
+  if( rotation.IsIdentity() )
+  {
+    mMatrix[0] = scale.x;
+    mMatrix[1] = 0.0f;
+    mMatrix[2] = 0.0f;
+    mMatrix[3] = 0.0f;
+
+    mMatrix[4] = 0.0f;
+    mMatrix[5] = scale.y;
+    mMatrix[6] = 0.0f;
+    mMatrix[7] = 0.0f;
+
+    mMatrix[8] = 0.0f;
+    mMatrix[9] = 0.0f;
+    mMatrix[10]= scale.z;
+    mMatrix[11]= 0.0f;
+  }
+  else
+  {
+    MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,27); // 27 = 9+18
+
+    const float xx = rotation.mVector.x * rotation.mVector.x;
+    const float yy = rotation.mVector.y * rotation.mVector.y;
+    const float zz = rotation.mVector.z * rotation.mVector.z;
+    const float xy = rotation.mVector.x * rotation.mVector.y;
+    const float xz = rotation.mVector.x * rotation.mVector.z;
+    const float wx = rotation.mVector.w * rotation.mVector.x;
+    const float wy = rotation.mVector.w * rotation.mVector.y;
+    const float wz = rotation.mVector.w * rotation.mVector.z;
+    const float yz = rotation.mVector.y * rotation.mVector.z;
+
+    mMatrix[0] = (scale.x * (1.0f - 2.0f * (yy + zz)));
+    mMatrix[1] = (scale.x * (       2.0f * (xy + wz)));
+    mMatrix[2] = (scale.x * (       2.0f * (xz - wy)));
+    mMatrix[3] = 0.0f;
+
+    mMatrix[4] = (scale.y * (       2.0f * (xy - wz)));
+    mMatrix[5] = (scale.y * (1.0f - 2.0f * (xx + zz)));
+    mMatrix[6] = (scale.y * (       2.0f * (yz + wx)));
+    mMatrix[7] = 0.0f;
+
+    mMatrix[8] = (scale.z * (       2.0f * (xz + wy)));
+    mMatrix[9] = (scale.z * (       2.0f * (yz - wx)));
+    mMatrix[10]= (scale.z * (1.0f - 2.0f * (xx + yy)));
+    mMatrix[11]= 0.0f;
+  }
+  // apply translation
+  mMatrix[12] = translation.x;
+  mMatrix[13] = translation.y;
+  mMatrix[14] = translation.z;
+  mMatrix[15] = 1.0f;
+}
+
+void Matrix::SetInverseTransformComponents(const Vector3&    scale,
+                                           const Quaternion& rotation,
+                                           const Vector3&    translation )
+{
+  Vector3 inverseTranslation = -translation;
+  Vector3 inverseScale( 1.0f/scale.x, 1.0f/scale.y, 1.0f/scale.z);
+  Quaternion inverseRotation(rotation);
+  bool isRotated = ! inverseRotation.IsIdentity();
+
+  // Order of application is translation, rotation, scale.
+  // Ensure translation is relative to scale & rotation:
+
+  if( isRotated )
+  {
+    inverseRotation.Invert();
+    inverseTranslation = inverseRotation.Rotate(inverseTranslation);
+  }
+
+  inverseTranslation *= inverseScale;
+
+  if( isRotated )
+  {
+    MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,27); // 27 = 9+18
+
+    const float xx = inverseRotation.mVector.x * inverseRotation.mVector.x;
+    const float yy = inverseRotation.mVector.y * inverseRotation.mVector.y;
+    const float zz = inverseRotation.mVector.z * inverseRotation.mVector.z;
+    const float xy = inverseRotation.mVector.x * inverseRotation.mVector.y;
+    const float xz = inverseRotation.mVector.x * inverseRotation.mVector.z;
+    const float wx = inverseRotation.mVector.w * inverseRotation.mVector.x;
+    const float wy = inverseRotation.mVector.w * inverseRotation.mVector.y;
+    const float wz = inverseRotation.mVector.w * inverseRotation.mVector.z;
+    const float yz = inverseRotation.mVector.y * inverseRotation.mVector.z;
+
+    mMatrix[0] = (inverseScale.x * (1.0f - 2.0f * (yy + zz)));
+    mMatrix[1] = (inverseScale.y * (2.0f * (xy + wz)));
+    mMatrix[2] = (inverseScale.z * (2.0f * (xz - wy)));
+    mMatrix[3] = 0.0f;
+
+    mMatrix[4] = (inverseScale.x * (2.0f * (xy - wz)));
+    mMatrix[5] = (inverseScale.y * (1.0f - 2.0f * (xx + zz)));
+    mMatrix[6] = (inverseScale.z * (2.0f * (yz + wx)));
+    mMatrix[7] = 0.0f;
+
+    mMatrix[8] = (inverseScale.x * (2.0f * (xz + wy)));
+    mMatrix[9] = (inverseScale.y * (2.0f * (yz - wx)));
+    mMatrix[10]= (inverseScale.z * (1.0f - 2.0f * (xx + yy)));
+    mMatrix[11]= 0.0f;
+  }
+  else
+  {
+    mMatrix[0] = inverseScale.x;
+    mMatrix[1] = 0.0f;
+    mMatrix[2] = 0.0f;
+    mMatrix[3] = 0.0f;
+
+    mMatrix[4] = 0.0f;
+    mMatrix[5] = inverseScale.y;
+    mMatrix[6] = 0.0f;
+    mMatrix[7] = 0.0f;
+
+    mMatrix[8] = 0.0f;
+    mMatrix[9] = 0.0f;
+    mMatrix[10]= inverseScale.z;
+    mMatrix[11]= 0.0f;
+  }
+
+  // apply translation
+  mMatrix[12] = inverseTranslation.x;
+  mMatrix[13] = inverseTranslation.y;
+  mMatrix[14] = inverseTranslation.z;
+  mMatrix[15] = 1.0f;
+}
+
+void Matrix::SetInverseTransformComponents(const Vector3&    xAxis,
+                                           const Vector3&    yAxis,
+                                           const Vector3&    zAxis,
+                                           const Vector3&    translation )
+{
+  // x, y, z axis parameters represent a orthonormal basis with no scaling, i.e. a rotation matrix.
+  // Invert rotation by transposing in place
+
+  // Order of application is translation, rotation
+
+  mMatrix[0]  = xAxis.x;
+  mMatrix[1]  = yAxis.x;
+  mMatrix[2]  = zAxis.x;
+  mMatrix[3]  = 0.0f;
+
+  mMatrix[4]  = xAxis.y;
+  mMatrix[5]  = yAxis.y;
+  mMatrix[6]  = zAxis.y;
+  mMatrix[7]  = 0.0f;
+
+  mMatrix[8]  = xAxis.z;
+  mMatrix[9]  = yAxis.z;
+  mMatrix[10] = zAxis.z;
+  mMatrix[11] = 0.0f;
+  mMatrix[12] = 0.0f;
+  mMatrix[13] = 0.0f;
+  mMatrix[14] = 0.0f;
+  mMatrix[15] = 1.0f;
+
+  // Ensure translation is relative to scale & rotation:
+
+  Vector4 inverseTranslation( -translation.x, -translation.y, -translation.z, 1.0f);
+  inverseTranslation = *this * inverseTranslation; // Rotate inverse translation
+  inverseTranslation.w = 1.0f;
+  SetTranslation(inverseTranslation);
+}
+
+
+void Matrix::GetTransformComponents(Vector3&     position,
+                                    Quaternion&  rotation,
+                                    Vector3&     scale) const
+{
+  position = GetTranslation3();
+
+  // Derive scale from axis lengths.
+  Vector3 theScale(GetXAxis().Length(), GetYAxis().Length(), GetZAxis().Length());
+  scale = theScale;
+
+  if( ! ( fabs(theScale.x - Vector3::ONE.x) < ROTATION_EPSILON &&
+          fabs(theScale.y - Vector3::ONE.y) < ROTATION_EPSILON &&
+          fabs(theScale.z - Vector3::ONE.z) < ROTATION_EPSILON ) )
+  {
+    MATH_INCREASE_COUNTER(PerformanceMonitor::MATRIX_MULTIPLYS);
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,9);
+
+    // Non-identity scale is embedded into rotation matrix. Remove it first:
+    Matrix m(*this);
+    Vector3 inverseScale(1.0f/theScale.x, 1.0f/theScale.y, 1.0f/theScale.z);
+    m.mMatrix[0] *= inverseScale.x;
+    m.mMatrix[1] *= inverseScale.x;
+    m.mMatrix[2] *= inverseScale.x;
+    m.mMatrix[4] *= inverseScale.y;
+    m.mMatrix[5] *= inverseScale.y;
+    m.mMatrix[6] *= inverseScale.y;
+    m.mMatrix[8] *= inverseScale.z;
+    m.mMatrix[9] *= inverseScale.z;
+    m.mMatrix[10] *= inverseScale.z;
+
+    Quaternion theRotation(m);
+
+    // If the imaginary components are close to zero, then use null quaternion instead.
+    if( fabs(theRotation.mVector.x) < ROTATION_EPSILON &&
+        fabs(theRotation.mVector.y) < ROTATION_EPSILON &&
+        fabs(theRotation.mVector.z) < ROTATION_EPSILON )
+    {
+      theRotation = Quaternion();
+    }
+    rotation = theRotation;
+  }
+  else
+  {
+    Quaternion theRotation(*this);
+
+    // If the imaginary components are close to zero, then use null quaternion instead.
+    if( fabs(theRotation.mVector.x) < ROTATION_EPSILON &&
+        fabs(theRotation.mVector.y) < ROTATION_EPSILON &&
+        fabs(theRotation.mVector.z) < ROTATION_EPSILON )
+    {
+      theRotation = Quaternion();
+    }
+    rotation = theRotation;
+  }
+}
+
+
+
+std::ostream& operator<< (std::ostream& o, const Matrix& matrix)
+{
+  return o << "[ [" << matrix.mMatrix[0] << ", " << matrix.mMatrix[1] << ", " << matrix.mMatrix[2]  << ", " << matrix.mMatrix[3] << "], "
+             << "[" << matrix.mMatrix[4] << ", " << matrix.mMatrix[5] << ", " << matrix.mMatrix[6]  << ", " << matrix.mMatrix[7] << "], "
+             << "[" << matrix.mMatrix[8] << ", " << matrix.mMatrix[9] << ", " << matrix.mMatrix[10] << ", " << matrix.mMatrix[11] << "], "
+             << "[" << matrix.mMatrix[12] << ", " << matrix.mMatrix[13] << ", " << matrix.mMatrix[14] << ", " << matrix.mMatrix[15] << "] ]";
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/matrix.h b/dali/public-api/math/matrix.h
new file mode 100644 (file)
index 0000000..ad60d9a
--- /dev/null
@@ -0,0 +1,411 @@
+#ifndef __DALI_MATRIX_H__
+#define __DALI_MATRIX_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+class Quaternion;
+
+/**
+ * @brief The Matrix class represents transformations and projections.
+ * It is agnostic w.r.t. row/column major notation - it operates on a flat array.
+ * Each axis is contiguous in memory, so the x axis corresponds to elements 0, 1, 2 and 3, the y axis dorresponds to elements 4, 5, 6, 7, etc.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Matrix
+{
+public:
+
+  friend std::ostream& operator<< (std::ostream& o, const Matrix& matrix);
+
+  /**
+   * @brief Constructor.
+   *
+   * Zero initialises the matrix
+   * @since_tizen 2.4
+   */
+  Matrix();
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param initialize to zero or leave uninitialized
+   */
+  explicit Matrix( bool initialize );
+
+  /**
+   * @brief Constructor
+   *
+   * The matrix is initialised with the contents of 'array' which must contain 16 floats.
+   * The order of the values for a transform matrix is:
+   *
+   *   xAxis.x xAxis.y xAxis.z 0.0f
+   *   yAxis.x yAxis.y yAxis.z 0.0f
+   *   zAxis.x zAxis.y zAxis.z 0.0f
+   *   trans.x trans.y trans.z 1.0f
+   *
+   * @since_tizen 2.4
+   * @param [in] array     16 floats
+   */
+  explicit Matrix(const float* array);
+
+  /**
+   * @brief Constructs a matrix from quaternion.
+   *
+   * @since_tizen 2.4
+   * @param rotation as quaternion
+   */
+  explicit Matrix( const Quaternion& rotation );
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] matrix to copy values from
+   */
+  Matrix( const Matrix& matrix );
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param [in] matrix to copy values from
+   * @return a reference to this
+   */
+  Matrix& operator=( const Matrix& matrix );
+
+  /**
+   * @brief The identity matrix.
+   */
+  static const Matrix IDENTITY;
+
+  /**
+   * @brief Sets this matrix to be an identity matrix.
+   * @since_tizen 2.4
+   */
+  void SetIdentity();
+
+  /**
+   * @brief Sets this matrix to be an identity matrix with scale.
+   *
+   * @since_tizen 2.4
+   * @param scale to set on top of identity matrix
+   */
+  void SetIdentityAndScale( const Vector3& scale );
+
+  /**
+   * @brief Invert a transform Matrix.
+   *
+   * Any Matrix representing only a rotation and/or translation
+   * can be inverted using this function. It is faster and more accurate then using Invert().
+   * @since_tizen 2.4
+   * @param [out] result     returns the inverse of this matrix
+   */
+  void InvertTransform(Matrix& result) const;
+
+  /**
+   * @brief Generic brute force Matrix Invert.
+   *
+   * Using the Matrix invert function for the specific type
+   * of matrix you are dealing with is faster, more accurate.
+   * @since_tizen 2.4
+   * @return true if successful
+   */
+  bool Invert();
+
+  /**
+   * @brief Swaps the rows to columns.
+   * @since_tizen 2.4
+   */
+  void Transpose();
+
+  /**
+   * @brief Returns the xAxis from a Transform matrix.
+   *
+   * @since_tizen 2.4
+   * @return the x axis
+   */
+  Vector3 GetXAxis() const;
+
+  /**
+   * @brief Returns the yAxis from a Transform matrix.
+   *
+   * @since_tizen 2.4
+   * @return the y axis
+   */
+  Vector3 GetYAxis() const;
+
+  /**
+   * @brief Returns the zAxis from a Transform matrix.
+   *
+   * @since_tizen 2.4
+   * @return the z axis
+   */
+  Vector3 GetZAxis() const;
+
+  /**
+   * @brief Sets the x axis.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @param [in] axis     the values to set the axis to
+   */
+  void SetXAxis(const Vector3& axis);
+
+  /**
+   * @brief Sets the y axis.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @param [in] axis     the values to set the axis to
+   */
+  void SetYAxis(const Vector3& axis);
+
+  /**
+   * @brief Sets the z axis.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @param [in] axis     the values to set the axis to
+   */
+  void SetZAxis(const Vector3& axis);
+
+  /**
+   * @brief Gets the translation.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @return the translation
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const Vector4& GetTranslation() const { return reinterpret_cast<const Vector4&>(mMatrix[12]); }
+
+  /**
+   * @brief Gets the x,y and z components of the translation as a Vector3.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @return the translation
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const Vector3& GetTranslation3() const { return reinterpret_cast<const Vector3&>(mMatrix[12]); }
+
+  /**
+   * @brief Sets the translation.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @param [in] translation   the translation
+   */
+  void SetTranslation(const Vector4& translation);
+
+  /**
+   * @brief Sets the x,y and z components of the translation from a Vector3.
+   *
+   * This assumes the matrix is a transform matrix.
+   * @since_tizen 2.4
+   * @param [in] translation   the translation
+   */
+  void SetTranslation(const Vector3& translation);
+
+  /**
+   * @brief Makes the axes of the matrix orthogonal to each other and of unit length.
+   *
+   * This function is used to correct floating point errors which would otherwise accumulate
+   * as operations are applied to the matrix. This function assumes the matrix is a transform
+   * matrix.
+   * @since_tizen 2.4
+   */
+  void OrthoNormalize();
+
+  /**
+   * @brief Returns the contents of the matrix as an array of 16 floats.
+   *
+   * The order of the values for a transform matrix is:
+   *   xAxis.x xAxis.y xAxis.z 0.0f
+   *   yAxis.x yAxis.y yAxis.z 0.0f
+   *   zAxis.x zAxis.y zAxis.z 0.0f
+   *   trans.x trans.y trans.z 1.0f
+   * @since_tizen 2.4
+   * @return the matrix contents as an array of 16 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const float* AsFloat() const {return mMatrix;}
+
+  /**
+   * @brief Returns the contents of the matrix as an array of 16 floats.
+   *
+   * The order of the values for a transform matrix is:
+   *
+   *   xAxis.x xAxis.y xAxis.z 0.0f
+   *   yAxis.x yAxis.y yAxis.z 0.0f
+   *   zAxis.x zAxis.y zAxis.z 0.0f
+   *   trans.x trans.y trans.z 1.0f
+   * @since_tizen 2.4
+   * @return the matrix contents as an array of 16 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  float* AsFloat() {return mMatrix;}
+
+  /**
+   * @brief Function to multiply two matrices and store the result onto third.
+   *
+   * Use this method in time critical path as it does not require temporaries
+   * @since_tizen 2.4
+   * @param result of the multiplication
+   * @param lhs matrix, this can be same matrix as result
+   * @param rhs matrix, this cannot be same matrix as result
+   */
+  static void Multiply( Matrix& result, const Matrix& lhs, const Matrix& rhs );
+
+  /**
+   * @brief Function to multiply a matrix and quaternion and store the result onto third.
+   *
+   * Use this method in time critical path as it does not require temporaries
+   * @since_tizen 2.4
+   * @param result of the multiplication
+   * @param lhs matrix, this can be same matrix as result
+   * @param rhs quaternion
+   */
+  static void Multiply( Matrix& result, const Matrix& lhs, const Quaternion& rhs );
+
+  /**
+   * @brief The multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs    the Matrix to multiply this by
+   * @return A matrix containing the result
+   */
+  Vector4 operator*(const Vector4& rhs) const;
+
+  /**
+   * @brief The equality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs    the Matrix to compare this to
+   * @return true if the matrices are equal
+   */
+  bool operator==(const Matrix & rhs) const;
+
+  /**
+   * @brief The inequality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   * @since_tizen 2.4
+   * @param [in] rhs    the Matrix to compare this to
+   * @return true if the matrices are not equal.
+   */
+  bool operator!=(const Matrix & rhs) const;
+
+  /**
+   * @brief Sets this matrix to contain the position, scale and rotation components.
+   *
+   * Performs scale, rotation, then translation
+   * @since_tizen 2.4
+   * @param[in] scale to apply
+   * @param[in] rotation to apply
+   * @param[in] translation to apply
+   */
+  void SetTransformComponents(const Vector3& scale,
+                              const Quaternion& rotation,
+                              const Vector3& translation );
+
+  /**
+   * @brief Sets this matrix to contain the inverse of the position, scale and rotation components.
+   *
+   * Performs translation, then rotation, then scale.
+   * @since_tizen 2.4
+   * @param[in] scale to apply
+   * @param[in] rotation to apply
+   * @param[in] translation to apply
+   */
+  void SetInverseTransformComponents(const Vector3&    scale,
+                                     const Quaternion& rotation,
+                                     const Vector3&    translation );
+
+
+  /**
+   * @brief Sets this matrix to contain the inverse of the orthonormal basis and position components.
+   *
+   * Performs translation, then rotation.
+   * @since_tizen 2.4
+   * @param[in] xAxis The X axis of the basis
+   * @param[in] yAxis The Y axis of the basis
+   * @param[in] zAxis The Z axis of the basis
+   * @param[in] translation to apply
+   */
+  void SetInverseTransformComponents(const Vector3&    xAxis,
+                                     const Vector3&    yAxis,
+                                     const Vector3&    zAxis,
+                                     const Vector3&    translation );
+
+  /**
+   * @brief Gets the position, scale and rotation components from the given transform matrix.
+   *
+   * @since_tizen 2.4
+   * @param[out] position to set
+   * @param[out] rotation to set - only valid if the transform matrix has not been skewed or sheared
+   * @param[out] scale to set - only valid if the transform matrix has not been skewed or sheared
+   * @pre This matrix must not contain skews or shears.
+   */
+  void GetTransformComponents(Vector3& position,
+                              Quaternion& rotation,
+                              Vector3& scale) const;
+
+private:
+
+  float mMatrix[16]; ///< The elements of the matrix
+};
+
+/**
+ * @brief Print a matrix.
+ *
+ * It is printed in memory order, i.e. each printed row is contiguous in memory.
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] matrix The matrix to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<< (std::ostream& o, const Matrix& matrix);
+
+// Allow Matrix to be treated as a POD type
+template <> struct TypeTraits< Matrix > : public BasicTypes< Matrix > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_MATRIX_H__
diff --git a/dali/public-api/math/matrix3.cpp b/dali/public-api/math/matrix3.cpp
new file mode 100644 (file)
index 0000000..3273a31
--- /dev/null
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/matrix3.h>
+
+// EXTERNAL INCLUDES
+#include <cstring> // for memcpy
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/math-utils.h>
+
+#define S00 0
+#define S01 1
+#define S02 2
+#define S10 3
+#define S11 4
+#define S12 5
+#define S20 6
+#define S21 7
+#define S22 8
+
+/*
+ * S00 S01 S02
+ * S10 S11 S12
+ * S20 S21 S22
+ */
+
+namespace
+{
+const size_t NUM_BYTES_IN_ROW    = 3*sizeof(float);
+const size_t NUM_BYTES_IN_MATRIX = 9*sizeof(float);
+}
+
+namespace Dali
+{
+
+const Matrix3 Matrix3::IDENTITY(1.0f, 0.0f, 0.0f,
+                                0.0f, 1.0f, 0.0f,
+                                0.0f, 0.0f, 1.0f);
+
+Matrix3::Matrix3()
+{
+  float* m = AsFloat();
+  memset(m, 0, NUM_BYTES_IN_MATRIX);
+}
+
+Matrix3::Matrix3(const Matrix3& m)
+{
+  memcpy( mElements, m.mElements, NUM_BYTES_IN_MATRIX );
+}
+
+Matrix3::Matrix3(const Matrix& matrix)
+{
+  const float* m4 = matrix.AsFloat();
+  memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
+  memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
+  memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
+}
+
+Matrix3::Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22)
+{
+  mElements[S00] = s00;
+  mElements[S01] = s01;
+  mElements[S02] = s02;
+  mElements[S10] = s10;
+  mElements[S11] = s11;
+  mElements[S12] = s12;
+  mElements[S20] = s20;
+  mElements[S21] = s21;
+  mElements[S22] = s22;
+}
+
+
+void Matrix3::SetIdentity()
+{
+  memset(mElements, 0, NUM_BYTES_IN_MATRIX);
+  mElements[S00]=1.0f;
+  mElements[S11]=1.0f;
+  mElements[S22]=1.0f;
+}
+
+Matrix3& Matrix3::operator=( const Matrix3& matrix )
+{
+  // no point copying if self assigning
+  if( this != &matrix )
+  {
+    memcpy( AsFloat(), matrix.AsFloat(), NUM_BYTES_IN_MATRIX );
+  }
+  return *this;
+}
+
+Matrix3& Matrix3::operator=( const Matrix& matrix )
+{
+  const float* m4 = matrix.AsFloat();
+  memcpy(&mElements[S00], m4,   NUM_BYTES_IN_ROW);
+  memcpy(&mElements[S10], m4+4, NUM_BYTES_IN_ROW);
+  memcpy(&mElements[S20], m4+8, NUM_BYTES_IN_ROW);
+  return *this;
+}
+
+bool Matrix3::Invert()
+{
+  bool succeeded = false;
+
+  float cof[9];
+  cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
+  cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
+  cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
+
+  cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
+  cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
+  cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
+
+  cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
+  cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
+  cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
+
+  float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
+
+  // In the case where the determinant is exactly zero, the matrix is non-invertible
+  if( ! EqualsZero( det ) )
+  {
+    det = 1.0 / det;
+    for (int i = 0; i < 9; i++)
+    {
+      mElements[i] = cof[i] * det;
+    }
+    succeeded = true;
+  }
+  return succeeded;
+}
+
+bool Matrix3::Transpose()
+{
+  float tmp;
+  tmp = mElements[S01]; mElements[S01] = mElements[S10]; mElements[S10]=tmp;
+  tmp = mElements[S02]; mElements[S02] = mElements[S20]; mElements[S20]=tmp;
+  tmp = mElements[S21]; mElements[S21] = mElements[S12]; mElements[S12]=tmp;
+  return true;
+}
+
+bool Matrix3::ScaledInverseTranspose()
+{
+  bool succeeded = false;
+
+  float cof[9];
+  cof[S00] = (mElements[S11] * mElements[S22] - mElements[S12] * mElements[S21]);
+  cof[S01] = (mElements[S02] * mElements[S21] - mElements[S01] * mElements[S22]);
+  cof[S02] = (mElements[S01] * mElements[S12] - mElements[S02] * mElements[S11]);
+
+  cof[S10] = (mElements[S12] * mElements[S20] - mElements[S10] * mElements[S22]);
+  cof[S11] = (mElements[S00] * mElements[S22] - mElements[S02] * mElements[S20]);
+  cof[S12] = (mElements[S02] * mElements[S10] - mElements[S00] * mElements[S12]);
+
+  cof[S20] = (mElements[S10] * mElements[S21] - mElements[S11] * mElements[S20]);
+  cof[S21] = (mElements[S01] * mElements[S20] - mElements[S00] * mElements[S21]);
+  cof[S22] = (mElements[S00] * mElements[S11] - mElements[S01] * mElements[S10]);
+
+  float det = mElements[S00] * cof[S00] + mElements[S01] * cof[S10] + mElements[S02] * cof[S20];
+
+  // In the case where the determinant is exactly zero, the matrix is non-invertible
+  if( ! EqualsZero( det ) )
+  {
+    // Use average rather than determinant to remove rounding to zero errors in further multiplication
+    float sum=0;
+    for(size_t i=0;i<9;i++)
+    {
+      sum+=fabsf(cof[i]);
+    }
+    float scale = 9.0f/sum; // Inverse of the average values
+    if (det < 0)
+    {
+      // Ensure the signs of the inverse are correct
+      scale = -scale;
+    }
+
+    mElements[S00] = cof[S00] * scale;
+    mElements[S01] = cof[S10] * scale;
+    mElements[S02] = cof[S20] * scale;
+
+    mElements[S10] = cof[S01] * scale;
+    mElements[S11] = cof[S11] * scale;
+    mElements[S12] = cof[S21] * scale;
+
+    mElements[S20] = cof[S02] * scale;
+    mElements[S21] = cof[S12] * scale;
+    mElements[S22] = cof[S22] * scale;
+
+    succeeded = true;
+  }
+  return succeeded;
+}
+
+void Matrix3::Scale(float scale)
+{
+  mElements[S00] *= scale;
+  mElements[S01] *= scale;
+  mElements[S02] *= scale;
+  mElements[S10] *= scale;
+  mElements[S11] *= scale;
+  mElements[S12] *= scale;
+  mElements[S20] *= scale;
+  mElements[S21] *= scale;
+  mElements[S22] *= scale;
+}
+
+float Matrix3::Magnitude() const
+{
+  float avg=0;
+  for(size_t i=0;i<9;i++)
+  {
+    avg+=fabsf(mElements[i]);
+  }
+  return avg/3.0f;
+}
+
+
+void Matrix3::Multiply( Matrix3& result, const Matrix3& lhs, const Matrix3& rhs )
+{
+  float* temp = result.AsFloat();
+  const float* rhsPtr  = rhs.AsFloat();
+  const float* lhsPtr = lhs.AsFloat();
+
+  for( int i=0; i < 3; i++ )
+  {
+    int loc = i * 3;
+    int loc1 = loc + 1;
+    int loc2 = loc + 2;
+
+    float value0 = lhsPtr[loc];
+    float value1 = lhsPtr[loc1];
+    float value2 = lhsPtr[loc2];
+    temp[loc]  = (value0 * rhsPtr[0]) +
+                 (value1 * rhsPtr[3]) +
+                 (value2 * rhsPtr[6]);
+
+    temp[loc1] = (value0 * rhsPtr[1]) +
+                 (value1 * rhsPtr[4]) +
+                 (value2 * rhsPtr[7]);
+
+    temp[loc2] = (value0 * rhsPtr[2]) +
+                 (value1 * rhsPtr[5]) +
+                 (value2 * rhsPtr[8]);
+  }
+}
+
+bool Matrix3::operator==(const Matrix3 & rhs) const
+{
+  return (
+    Equals( mElements[0], rhs.mElements[0]) &&
+    Equals( mElements[1], rhs.mElements[1]) &&
+    Equals( mElements[2], rhs.mElements[2]) &&
+    Equals( mElements[3], rhs.mElements[3]) &&
+    Equals( mElements[4], rhs.mElements[4]) &&
+    Equals( mElements[5], rhs.mElements[5]) &&
+    Equals( mElements[6], rhs.mElements[6]) &&
+    Equals( mElements[7], rhs.mElements[7]) &&
+    Equals( mElements[8], rhs.mElements[8]));
+}
+
+bool Matrix3::operator!=(const Matrix3& rhs) const
+{
+  return !(*this == rhs);
+}
+
+std::ostream& operator<< (std::ostream& o, const Matrix3& matrix)
+{
+  return o << "[ [" << matrix.mElements[0] << ", " << matrix.mElements[1] << ", " << matrix.mElements[2]  << "], "
+             << "[" << matrix.mElements[3] << ", " << matrix.mElements[4] << ", " << matrix.mElements[5]  << "], "
+             << "[" << matrix.mElements[6] << ", " << matrix.mElements[7] << ", " << matrix.mElements[8]  << "] ]";
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/matrix3.h b/dali/public-api/math/matrix3.h
new file mode 100644 (file)
index 0000000..683eb0f
--- /dev/null
@@ -0,0 +1,246 @@
+#ifndef __DALI_MATRIX3_H__
+#define __DALI_MATRIX3_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/common/type-traits.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+class Matrix;
+struct Vector2;
+
+/**
+ * @brief A 3x3 matrix.
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Matrix3
+{
+public:
+
+  friend std::ostream& operator<< (std::ostream& o, const Matrix3& matrix);
+
+  /**
+   * @brief The identity matrix
+   */
+  static const Matrix3 IDENTITY;
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  Matrix3();
+
+  /**
+   * @brief Copy Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] m Another 3x3 matrix
+   */
+  Matrix3(const Matrix3& m);
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] m A 4x4 matrix. The translation and shear components are ignored.
+   */
+  Matrix3(const Matrix& m);
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] s00 First element
+   * @param[in] s01 Second element
+   * @param[in] s02 Third element
+   * @param[in] s10 Fourth element
+   * @param[in] s11 Fifth element
+   * @param[in] s12 Sixth element
+   * @param[in] s20 Seventh element
+   * @param[in] s21 Eighth element
+   * @param[in] s22 Ninth element
+   */
+  Matrix3(float s00, float s01, float s02, float s10, float s11, float s12, float s20, float s21, float s22);
+
+  /**
+   * @brief Assignment Operator
+   * @since_tizen 2.4
+   * @param matrix from which to copy values
+   * @return reference to this object
+   */
+  Matrix3& operator=( const Matrix3& matrix );
+
+  /**
+   * @brief Assignment Operator
+   * @since_tizen 2.4
+   * @param matrix from which to copy values
+   * @return reference to this object
+   */
+  Matrix3& operator=( const Matrix& matrix );
+
+  /**
+   * @brief The equality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs    the Matrix to compare this to
+   * @return true if the matrices are equal
+   */
+  bool operator==(const Matrix3 & rhs) const;
+
+  /**
+   * @brief The inequality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs    the Matrix to compare this to
+   * @return true if the matrices are equal
+   */
+  bool operator!=(const Matrix3 & rhs) const;
+
+  /**
+   * @brief Destructor.
+   * @since_tizen 2.4
+   */
+  ~Matrix3()
+  {
+  }
+
+  /**
+   * @brief Sets the matrix to the identity matrix.
+   * @since_tizen 2.4
+   */
+  void SetIdentity();
+
+  /**
+   * @brief Returns the contents of the matrix as an array of 9 floats.
+   *
+   * The order of the values for a matrix is:
+   *   xAxis.x yAxis.x zAxis.x
+   *   xAxis.y yAxis.y zAxis.y
+   *   xAxis.z yAxis.z zAxis.z
+   * @since_tizen 2.4
+   * @return the matrix contents as an array of 9 floats.
+   */
+  const float* AsFloat() const {return &mElements[0];}
+
+  /**
+   * @brief Returns the contents of the matrix as an array of 9 floats.
+   *
+   * The order of the values for a matrix is:
+   *   xAxis.x yAxis.x zAxis.x
+   *   xAxis.y yAxis.y zAxis.y
+   *   xAxis.z yAxis.z zAxis.z
+   * @since_tizen 2.4
+   * @return the matrix contents as an array of 9 floats.
+   */
+  float* AsFloat() {return &mElements[0];}
+
+  /**
+   * @brief Inverts the matrix.
+   *
+   * @since_tizen 2.4
+   * @return true if successful
+   */
+  bool Invert();
+
+  /**
+   * @brief Swaps the rows to columns
+   * @since_tizen 2.4
+   * @return true
+   */
+  bool Transpose();
+
+  /**
+   * @brief Multiplies all elements of the matrix by the scale value.
+   *
+   * @since_tizen 2.4
+   * @param scale - the value by which to scale the whole matrix.
+   *
+   */
+  void Scale(float scale);
+
+  /**
+   * @brief Magnitude returns the average of the absolute values of the
+   * elements * 3.
+   *
+   * (The Magnitude of the unit matrix is therefore 1)
+   * @since_tizen 2.4
+   * @return the magnitude - always positive.
+   */
+  float Magnitude() const;
+
+  /**
+   * @brief If the matrix is invertible, then this method inverts, transposes
+   * and scales the matrix such that the resultant element values
+   * average 1.
+   *
+   * If the matrix is not invertible, then the matrix is left unchanged.
+   *
+   * @since_tizen 2.4
+   * @return true if the matrix is invertible, otherwise false
+   */
+  bool ScaledInverseTranspose();
+
+  /**
+   * @brief Function to multiply two matrices and store the result onto third.
+   *
+   * Use this method in time critical path as it does not require temporaries
+   * @since_tizen 2.4
+   * @param result of the multiplication
+   * @param lhs matrix, this can be same matrix as result
+   * @param rhs matrix, this cannot be same matrix as result
+   */
+  static void Multiply( Matrix3& result, const Matrix3& lhs, const Matrix3& rhs );
+
+private:
+
+  float mElements[9]; ///< The elements of the matrix
+};
+
+/**
+ * @brief Print a 3x3 matrix.
+ *
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] matrix The matrix to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<< (std::ostream& o, const Matrix3& matrix);
+
+// Allow Matrix3 to be treated as a POD type
+template <> struct TypeTraits< Matrix3 > : public BasicTypes< Matrix3 > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif //__DALI_MATRIX3_H__
diff --git a/dali/public-api/math/quaternion.cpp b/dali/public-api/math/quaternion.cpp
new file mode 100644 (file)
index 0000000..49d7ae0
--- /dev/null
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/quaternion.h>
+
+// EXTERNAL INCLUDES
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+using Internal::PerformanceMonitor;
+
+const Quaternion Quaternion::IDENTITY;
+
+
+/**
+ * Default Constructor
+ */
+Quaternion::Quaternion()
+ : mVector( 0.0f, 0.0f, 0.0f, 1.0f )
+{
+}
+
+Quaternion::Quaternion( float cosThetaBy2, float iBySineTheta, float jBySineTheta, float kBySineTheta ) :
+  mVector( iBySineTheta, jBySineTheta, kBySineTheta, cosThetaBy2 )
+{
+}
+
+Quaternion::Quaternion( const Vector4& vector )
+{
+  mVector = vector;
+}
+
+Quaternion::Quaternion( Radian angle, const Vector3& axis )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4);
+
+  Vector3 tmpAxis = axis;
+  tmpAxis.Normalize();
+  const float halfAngle = angle.radian * 0.5f;
+  const float sinThetaByTwo = sinf(halfAngle);
+  const float cosThetaByTwo = cosf(halfAngle);
+  mVector.x = tmpAxis.x * sinThetaByTwo;
+  mVector.y = tmpAxis.y * sinThetaByTwo;
+  mVector.z = tmpAxis.z * sinThetaByTwo;
+  mVector.w = cosThetaByTwo;
+}
+
+Quaternion::Quaternion( Radian pitch, Radian yaw, Radian roll )
+{
+  SetEuler( pitch, yaw, roll );
+}
+
+Quaternion::Quaternion( const Matrix& matrix )
+{
+  Vector3 xAxis( matrix.GetXAxis() );
+  Vector3 yAxis( matrix.GetYAxis() );
+  Vector3 zAxis( matrix.GetZAxis() );
+
+  SetFromAxes( xAxis, yAxis, zAxis );
+}
+
+Quaternion::Quaternion( const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis )
+{
+  SetFromAxes( xAxis, yAxis, zAxis );
+}
+
+Quaternion::Quaternion( const Vector3& v0, const Vector3& v1 )
+{
+  float dot = v0.Dot(v1);
+  if( dot > 1.0f - Math::MACHINE_EPSILON_1 )
+  {
+    //Identity quaternion
+    mVector.x = mVector.y = mVector.z = 0.0f;
+    mVector.w = 1.0f;
+  }
+  else if( dot < -1.0f + Math::MACHINE_EPSILON_1)
+  {
+    //180 degree rotation across the Z axis
+    mVector.x = mVector.y = mVector.w = 0.0f;
+    mVector.z = 1.0f;
+  }
+  else
+  {
+    Vector3 w = v0.Cross(v1);
+    mVector.w = 1.0f + dot;
+    mVector.x = w.x;
+    mVector.y = w.y;
+    mVector.z = w.z;
+    Normalize();
+  }
+}
+
+Quaternion::~Quaternion()
+{
+}
+
+bool Quaternion::IsIdentity() const
+{
+  // start from w as its unlikely that any real rotation has w == 1
+  // Uses a relaxed epsilon, as composition of rotation introduces error
+  return ( ( fabsf( mVector.w - 1.0f ) < Math::MACHINE_EPSILON_10 )&&
+           ( fabsf( mVector.x ) < Math::MACHINE_EPSILON_10 )&&
+           ( fabsf( mVector.y ) < Math::MACHINE_EPSILON_10 )&&
+           ( fabsf( mVector.z ) < Math::MACHINE_EPSILON_10 ) );
+}
+
+bool Quaternion::ToAxisAngle(Vector3& axis, Radian& angle) const
+{
+  angle = acosf(mVector.w);
+  bool converted = false;
+  // pre-compute to save time
+  const float sine = sinf( angle.radian );
+
+  // If sine(angle) is zero, conversion is not possible
+
+  if ( ! EqualsZero( sine ) )
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+    float sinf_theta_inv = 1.0f / sine;
+
+    axis.x = mVector.x*sinf_theta_inv;
+    axis.y = mVector.y*sinf_theta_inv;
+    axis.z = mVector.z*sinf_theta_inv;
+    angle.radian *= 2.0f;
+    converted = true;
+  }
+  return converted;
+}
+
+const Vector4& Quaternion::AsVector() const
+{
+  return mVector;
+}
+
+void Quaternion::SetEuler( Radian pitch, Radian yaw, Radian roll )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,19);
+
+  const float halfX = 0.5f * pitch.radian;
+  const float halfY = 0.5f * yaw.radian;
+  const float halfZ = 0.5f * roll.radian;
+
+  float cosX2 = cosf(halfX);
+  float cosY2 = cosf(halfY);
+  float cosZ2 = cosf(halfZ);
+
+  float sinX2 = sinf(halfX);
+  float sinY2 = sinf(halfY);
+  float sinZ2 = sinf(halfZ);
+
+  mVector.w = cosZ2 * cosY2 * cosX2 + sinZ2 * sinY2 * sinX2;
+  mVector.x = cosZ2 * cosY2 * sinX2 - sinZ2 * sinY2 * cosX2;
+  mVector.y = cosZ2 * sinY2 * cosX2 + sinZ2 * cosY2 * sinX2;
+  mVector.z = sinZ2 * cosY2 * cosX2 - cosZ2 * sinY2 * sinX2;
+}
+
+Vector4 Quaternion::EulerAngles() const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,13);
+
+  float sqw = mVector.w*mVector.w;
+  float sqx = mVector.x*mVector.x;
+  float sqy = mVector.y*mVector.y;
+  float sqz = mVector.z*mVector.z;
+
+  Vector4 euler;
+  euler.x = atan2f(2.0f * (mVector.y*mVector.z + mVector.x*mVector.w), -sqx - sqy + sqz + sqw);
+  euler.y = asinf(-2.0f * (mVector.x*mVector.z - mVector.y*mVector.w));
+  euler.z = atan2f(2.0f * (mVector.x*mVector.y + mVector.z*mVector.w), sqx - sqy - sqz + sqw);
+  return euler;
+}
+
+const Quaternion Quaternion::operator+( const Quaternion& other ) const
+{
+  return Quaternion(mVector + other.mVector);
+}
+
+const Quaternion Quaternion::operator-( const Quaternion& other ) const
+{
+  return Quaternion(mVector - other.mVector);
+}
+
+const Quaternion Quaternion::operator*( const Quaternion& other ) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,12);
+
+  return Quaternion(mVector.w * other.mVector.w - mVector.Dot(other.mVector),
+                    mVector.y * other.mVector.z - mVector.z * other.mVector.y + mVector.w * other.mVector.x + mVector.x * other.mVector.w,
+                    mVector.z * other.mVector.x - mVector.x * other.mVector.z + mVector.w * other.mVector.y + mVector.y * other.mVector.w,
+                    mVector.x * other.mVector.y - mVector.y * other.mVector.x + mVector.w * other.mVector.z + mVector.z * other.mVector.w);
+}
+
+Vector3 Quaternion::operator*( const Vector3& other ) const
+{
+  Vector3 qvec(mVector.x, mVector.y, mVector.z);
+  Vector3 uv = qvec.Cross( other );
+  Vector3 uuv = qvec.Cross(uv);
+  uv *= (2.0f * mVector.w);
+  uuv *= 2.0f;
+
+  return other + uv + uuv;
+}
+
+const Quaternion Quaternion::operator/( const Quaternion& q ) const
+{
+  Quaternion p(q);
+  p.Invert();
+  return *this * p;
+}
+
+const Quaternion Quaternion::operator*( float scale ) const
+{
+  return Quaternion(mVector*scale);
+}
+
+const Quaternion Quaternion::operator/( float scale ) const
+{
+  return Quaternion(mVector/scale);
+}
+
+Quaternion Quaternion::operator-() const
+{
+  return Quaternion(-mVector.w, -mVector.x, -mVector.y, -mVector.z);
+}
+
+const Quaternion& Quaternion::operator+=( const Quaternion& q )
+{
+  mVector += q.mVector; return *this;
+}
+
+const Quaternion& Quaternion::operator-=( const Quaternion& q )
+{
+  mVector -= q.mVector; return *this;
+}
+
+const Quaternion& Quaternion::operator*=( const Quaternion& q )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,12);
+
+  float x = mVector.x, y = mVector.y, z = mVector.z, w = mVector.w;
+
+  mVector.w = mVector.w * q.mVector.w - mVector.Dot(q.mVector);
+  mVector.x = y*q.mVector.z - z*q.mVector.y + w*q.mVector.x + x*q.mVector.w;
+  mVector.y = z*q.mVector.x - x*q.mVector.z + w*q.mVector.y + y*q.mVector.w;
+  mVector.z = x*q.mVector.y - y*q.mVector.x + w*q.mVector.z + z*q.mVector.w;
+  return *this;
+}
+
+const Quaternion& Quaternion::operator*=( float scale )
+{
+  mVector*=scale; return *this;
+}
+
+const Quaternion& Quaternion::operator/=( float scale )
+{
+  mVector/=scale; return *this;
+}
+
+bool Quaternion::operator==( const Quaternion& rhs ) const
+{
+  return ( ( fabsf(mVector.x - rhs.mVector.x) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.y - rhs.mVector.y) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.z - rhs.mVector.z) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.w - rhs.mVector.w) < Math::MACHINE_EPSILON_1 ) ||
+           // Or equal to negation of rhs
+           ( fabsf(mVector.x + rhs.mVector.x) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.y + rhs.mVector.y) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.z + rhs.mVector.z) < Math::MACHINE_EPSILON_1 &&
+             fabsf(mVector.w + rhs.mVector.w) < Math::MACHINE_EPSILON_1 )
+         );
+}
+
+bool Quaternion::operator!=( const Quaternion& rhs ) const
+{
+  return !operator==(rhs);
+}
+
+float Quaternion::Length() const
+{
+  return (float)sqrt(mVector.w * mVector.w + mVector.Dot(mVector));
+}
+
+float Quaternion::LengthSquared() const
+{
+  return (float)(mVector.w * mVector.w + mVector.Dot(mVector));
+}
+
+void Quaternion::Normalize()
+{
+  *this/=Length();
+}
+
+Quaternion Quaternion::Normalized() const
+{
+  return  *this/Length();
+}
+
+void Quaternion::Conjugate()
+{
+  mVector.x = -mVector.x;
+  mVector.y = -mVector.y;
+  mVector.z = -mVector.z;
+}
+
+void Quaternion::Invert()
+{
+  Conjugate();
+  *this/=LengthSquared();
+}
+
+Quaternion Quaternion::Log() const
+{
+  float a = acosf(mVector.w);
+  float sina = sinf(a);
+  Quaternion ret;
+
+  ret.mVector.w = 0;
+  if (fabsf(sina) >= Math::MACHINE_EPSILON_1)
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4);
+
+    float angleBySinAngle = a * (1.0f / sina);
+    ret.mVector.x = mVector.x * angleBySinAngle;
+    ret.mVector.y = mVector.y * angleBySinAngle;
+    ret.mVector.z = mVector.z * angleBySinAngle;
+  }
+  else
+  {
+    ret.mVector.x= ret.mVector.y= ret.mVector.z= 0;
+  }
+  return ret;
+}
+
+Quaternion Quaternion::Exp() const
+{
+  DALI_ASSERT_ALWAYS( EqualsZero( mVector.w ) && "Cannot perform Exponent" );
+
+  float a = mVector.Length();
+  float sina = sinf(a);
+  Quaternion ret;
+
+  ret.mVector.w = cosf(a);
+
+  if (a >= Math::MACHINE_EPSILON_1)
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4);
+
+    float sinAOverA = sina * (1.0f / a);
+    ret.mVector.x = mVector.x * sinAOverA;
+    ret.mVector.y = mVector.y * sinAOverA;
+    ret.mVector.z = mVector.z * sinAOverA;
+  }
+  else
+  {
+    ret.mVector.x = ret.mVector.y = ret.mVector.z = 0.0f;
+  }
+  return ret;
+}
+
+float Quaternion::Dot( const Quaternion& q1, const Quaternion& q2 )
+{
+  return q1.mVector.Dot4(q2.mVector);
+}
+
+Quaternion Quaternion::Lerp(const Quaternion& q1, const Quaternion& q2, float t )
+{
+  return (q1*(1.0f-t) + q2*t).Normalized();
+}
+
+Quaternion Quaternion::Slerp( const Quaternion& q1, const Quaternion& q2, float progress )
+{
+  Quaternion q3;
+  float cosTheta = Quaternion::Dot(q1, q2);
+
+  /**
+   * If cos(theta) < 0, q1 and q2 are more than 90 degrees apart,
+   * so invert one to reduce spinning.
+   */
+  if (cosTheta < 0.0f)
+  {
+    cosTheta = -cosTheta;
+    q3 = -q2;
+  }
+  else
+  {
+    q3 = q2;
+  }
+
+  if (fabsf(cosTheta) < 0.95f)
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,5);
+
+    // Normal SLERP
+    float sine = sqrtf(1.0f - cosTheta*cosTheta);
+    float angle = atan2f(sine, cosTheta);
+    float invSine = 1.0f / sine;
+    float coeff0 = sinf((1.0f - progress) * angle) * invSine;
+    float coeff1 = sinf(progress * angle) * invSine;
+
+    return q1*coeff0 + q3*coeff1;
+  }
+  else
+  {
+    // If the angle is small, use linear interpolation
+    Quaternion result = q1*(1.0f - progress) + q3*progress;
+
+    return result.Normalized();
+  }
+}
+
+Quaternion Quaternion::SlerpNoInvert( const Quaternion& q1, const Quaternion& q2, float t )
+{
+  float cosTheta = Quaternion::Dot(q1, q2);
+
+  if (cosTheta > -0.95f && cosTheta < 0.95f)
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,2);
+
+    float theta = acosf(cosTheta);
+    return (q1*sinf(theta*(1.0f-t)) + q2*sinf(theta*t))/sinf(theta);
+  }
+  else
+  {
+    return Lerp(q1, q2, t);
+  }
+}
+
+Quaternion Quaternion::Squad( const Quaternion& start, const Quaternion& end,  const Quaternion& ctrl1,  const Quaternion& ctrl2, float t )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,2);
+
+  Quaternion c = SlerpNoInvert( start, end, t );
+  Quaternion d = SlerpNoInvert( ctrl1, ctrl2, t );
+  return SlerpNoInvert( c, d, 2*t*(1-t) );
+}
+
+float Quaternion::AngleBetween( const Quaternion& q1, const Quaternion& q2 )
+{
+  Quaternion from(q1);
+  Quaternion to(q2);
+
+  from.Normalize();
+  to.Normalize();
+
+  //Formula for angle Î¸ between two quaternion is:
+  //θ = cos^−1 (2⟨q1,q2⟩^2 âˆ’ 1), Where (q1,q2) is inner product of the quaternions.
+  float X = from.mVector.Dot4(to.mVector);
+  float theta = acos( (2 * X * X) - 1);
+
+  return theta;
+}
+
+Vector4 Quaternion::Rotate( const Vector4& vector ) const
+{
+  Quaternion V(0.0f, vector.x, vector.y, vector.z);
+  Quaternion conjugate(*this);
+  conjugate.Conjugate();
+  return (*this * V * conjugate).mVector;
+}
+
+Vector3 Quaternion::Rotate( const Vector3& vector ) const
+{
+  Quaternion V(0.0f, vector.x, vector.y, vector.z);
+  Quaternion conjugate(*this);
+  conjugate.Conjugate();
+  return Vector3((*this * V * conjugate).mVector);
+}
+
+void Quaternion::SetFromAxes( const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis )
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4);
+
+  float t = xAxis.x + yAxis.y + zAxis.z;
+  if ( t > 0.0f )                                      // w is largest
+  {
+    float root = sqrtf( t + 1.0f );
+    float one_over_4w = 0.5f / root;
+    mVector.x = ( yAxis.z - zAxis.y ) * one_over_4w;
+    mVector.y = ( zAxis.x - xAxis.z ) * one_over_4w;
+    mVector.z = ( xAxis.y - yAxis.x ) * one_over_4w;
+    mVector.w = root * 0.5f;
+  }
+  else if( zAxis.z > xAxis.x && zAxis.z > yAxis.y )    // z is largest
+  {
+    float root = sqrtf( zAxis.z - xAxis.x - yAxis.y + 1.0f );
+    float one_over_4w = 0.5f / root;
+    mVector.x = ( xAxis.z + zAxis.x ) * one_over_4w;
+    mVector.y = ( yAxis.z + zAxis.y ) * one_over_4w;
+    mVector.z = root * 0.5f;
+    mVector.w = ( xAxis.y - yAxis.x ) * one_over_4w;
+  }
+  else if( yAxis.y > xAxis.x )                         // y is largest
+  {
+    float root = sqrtf(yAxis.y - zAxis.z - xAxis.x + 1.0f );
+    float one_over_4w = 0.5f / root;
+
+    mVector.x = ( xAxis.y + yAxis.x ) * one_over_4w;
+    mVector.y = root * 0.5f;
+    mVector.z = ( zAxis.y + yAxis.z ) * one_over_4w;
+    mVector.w = ( zAxis.x - xAxis.z ) * one_over_4w;
+  }
+  else                                                 // x is largest
+  {
+    float root = sqrtf( xAxis.x - yAxis.y - zAxis.z + 1.0f );
+    float one_over_4w = 0.5f / root;
+    mVector.x = root * 0.5f;
+    mVector.y = ( yAxis.x + xAxis.y ) * one_over_4w;
+    mVector.z = ( zAxis.x + xAxis.z ) * one_over_4w;
+    mVector.w = ( yAxis.z - zAxis.y ) * one_over_4w;
+  }
+
+  Normalize();
+}
+
+std::ostream& operator<<( std::ostream& o, const Quaternion& quaternion )
+{
+  Vector3 axis;
+  Radian angleRadians;
+
+  quaternion.ToAxisAngle( axis, angleRadians );
+  Degree degrees( angleRadians );
+
+  return o << "[ Axis: [" << axis.x << ", " << axis.y << ", " << axis.z << "], Angle: " << degrees.degree << " degrees ]";
+}
+
+} // namespace Dali
+
diff --git a/dali/public-api/math/quaternion.h b/dali/public-api/math/quaternion.h
new file mode 100644 (file)
index 0000000..4bfff41
--- /dev/null
@@ -0,0 +1,491 @@
+#ifndef __DALI_QUATERNION_H__
+#define __DALI_QUATERNION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+// Forward declaration
+class Matrix;
+
+/**
+ * @brief The Quaternion class encapsulates the mathematics of the quaternion.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Quaternion
+{
+public:
+
+  /**
+   * @brief Default Constructor
+   * @since_tizen 2.4
+   */
+  Quaternion();
+
+  /**
+   * @brief Construct from a quaternion represented by floats.
+   *
+   * @since_tizen 2.4
+   * @param[in] cosThetaBy2
+   * @param[in] iBySineTheta
+   * @param[in] jBySineTheta
+   * @param[in] kBySineTheta
+   */
+  Quaternion( float cosThetaBy2, float iBySineTheta, float jBySineTheta, float kBySineTheta );
+
+  /**
+   * @brief Construct from a quaternion represented by a vector.
+   *
+   * @since_tizen 2.4
+   * @param[in] vector - x,y,z fields represent i,j,k coefficients, w represents cos(theta/2)
+   */
+  explicit Quaternion( const Vector4& vector );
+
+  /**
+   * @brief Constructor from an axis and angle.
+   *
+   * @since_tizen 2.4
+   * @param[in] angle - the angle around the axis
+   * @param[in] axis  - the vector of the axis
+   */
+  Quaternion( Radian angle, const Vector3& axis );
+
+  /**
+   * @brief Construct from Euler angles.
+   *
+   * @since_tizen 2.4
+   * @param[in] pitch
+   * @param[in] yaw
+   * @param[in] roll
+   */
+  Quaternion( Radian pitch, Radian yaw, Radian roll );
+
+  /**
+   * @brief Construct from a matrix.
+   *
+   * @since_tizen 2.4
+   * @param[in] matrix
+   */
+  explicit Quaternion(const Matrix& matrix);
+
+  /**
+   * @brief Construct from 3 orthonormal axes.
+   *
+   * @since_tizen 2.4
+   * @param[in] xAxis The X axis
+   * @param[in] yAxis The Y axis
+   * @param[in] zAxis The Z axis
+   */
+  explicit Quaternion( const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis );
+
+  /**
+   * @brief Construct quaternion which describes minimum rotation to align v0 with v1
+   * @since_tizen 2.4
+   * @param[in] v0 First normalized vector
+   * @param[in] v1 Second normalized vector
+   * @pre v0 and v1 should be normalized
+   *
+   */
+  explicit Quaternion( const Vector3& v0, const Vector3& v1 );
+
+  /**
+   * @brief Destructor, nonvirtual as this is not a base class.
+   *
+   * @since_tizen 2.4
+   */
+  ~Quaternion();
+
+// Constants
+
+  static const Quaternion IDENTITY; ///< (0.0f,0.0f,0.0f,1.0f)
+
+  /**
+   * @brief Helper to check if this is an identity quaternion
+   *
+   * @since_tizen 2.4
+   * @return true if this is identity quaternion
+   */
+  bool IsIdentity() const;
+
+  /**
+   * @brief Convert the quaternion to an axis/angle pair.
+   *
+   * @since_tizen 2.4
+   * @param[out] axis
+   * @param[out] angle in radians
+   * @return true if converted correctly
+   */
+  bool ToAxisAngle( Vector3& axis, Radian& angle ) const;
+
+  /**
+   * @brief Return the quaternion as a vector.
+   *
+   * @since_tizen 2.4
+   * @return the vector representation of the quaternion
+   */
+  const Vector4& AsVector() const;
+
+  /**
+   * @brief SetEuler sets the quaternion from the Euler angles applied in x, y, z order.
+   *
+   * @since_tizen 2.4
+   * @param[in] pitch
+   * @param[in] yaw
+   * @param[in] roll
+   */
+  void SetEuler( Radian pitch, Radian yaw, Radian roll );
+
+  /**
+   * @brief returns the Euler angles from a rotation Quaternion.
+   *
+   * @since_tizen 2.4
+   * @return a vector of Euler angles (x == pitch, y == yaw, z == roll)
+   */
+  Vector4 EulerAngles() const;
+
+  /**
+   * @brief Addition operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to add
+   * @return A quaternion containing the result of the addition
+   */
+  const Quaternion operator+( const Quaternion& other ) const;
+
+  /**
+   * @brief Subtraction operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to subtract
+   * @return A quaternion containing the result of the subtract
+   */
+  const Quaternion operator-( const Quaternion& other ) const;
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to multiply
+   * @return A quaternion containing the result
+   */
+  const Quaternion operator*( const Quaternion& other ) const;
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The vector to multiply
+   * @return A vector containing the result of the multiplication
+   */
+  Vector3 operator*( const Vector3& other ) const;
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other a quaternion to divide by
+   * @return A quaternion containing the result
+   */
+  const Quaternion operator/( const Quaternion& other ) const;
+
+  /**
+   * @brief Scale operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] scale A value to scale by
+   * @return A quaternion containing the result
+   */
+  const Quaternion operator*( float scale ) const;
+
+  /**
+   * @brief Scale operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] scale A value to scale by
+   * @return A quaternion containing the result
+   */
+  const Quaternion operator/( float scale ) const;
+
+  /**
+   * @brief Unary Negation operator.
+   *
+   * @since_tizen 2.4
+   * @return A quaternion containing the negated result
+   */
+  Quaternion operator-() const;
+
+  /**
+   * @brief Addition with Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to add
+   * @return itself
+   */
+  const Quaternion& operator+=( const Quaternion& other );
+
+  /**
+   * @brief Subtraction with Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to subtract
+   * @return itself
+   */
+  const Quaternion& operator-=( const Quaternion& other );
+
+  /**
+   * @brief Multiplication with Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The quaternion to multiply
+   * @return itself
+   */
+  const Quaternion& operator*=( const Quaternion& other );
+
+  /**
+   * @brief Scale with Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] scale the value to scale by
+   * @return itself
+   */
+  const Quaternion& operator*=( float scale );
+
+  /**
+   * @brief Scale with Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] scale the value to scale by
+   * @return itself
+   */
+  const Quaternion& operator/=( float scale );
+
+  /**
+   * @brief Equality operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The quaterion to compare with.
+   * @return True if the quaternions are equal.
+   */
+  bool operator==( const Quaternion& rhs ) const;
+
+  /**
+   * @brief Inequality operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The quaterion to compare with.
+   * @return True if the quaternions are not equal.
+   */
+  bool operator!=( const Quaternion& rhs ) const;
+
+  /**
+   * @brief Return the length of the quaternion.
+   *
+   * @since_tizen 2.4
+   * @return the length of the quaternion
+   */
+  float Length() const;
+
+  /**
+   * @brief Return the squared length of the quaternion.
+   *
+   * @since_tizen 2.4
+   * @return the squared length of the quaternion
+   */
+  float LengthSquared() const;
+
+  /**
+   * @brief Normalize this to unit length.
+   *
+   * @since_tizen 2.4
+   */
+  void Normalize();
+
+  /**
+   * @brief Normalized.
+   *
+   * @since_tizen 2.4
+   * @return a normalized version of this quaternion
+   */
+  Quaternion Normalized() const;
+
+  /**
+   * @brief Conjugate this quaternion.
+   *
+   * @since_tizen 2.4
+   */
+  void Conjugate();
+
+  /**
+   * @brief Invert this quaternion.
+   *
+   * @since_tizen 2.4
+   */
+  void Invert();
+
+  /**
+   * @brief Performs the logarithm of a Quaternion = v*a where q = (cos(a),v*sin(a)).
+   *
+   * @since_tizen 2.4
+   * @return a quaternion representing the logarithm
+   */
+  Quaternion Log() const;
+
+  /**
+   * @brief Performs an exponent e^Quaternion = Exp(v*a) = (cos(a),vsin(a)).
+   *
+   * @since_tizen 2.4
+   * @return a quaternion representing the exponent
+   */
+  Quaternion Exp() const;
+
+  /**
+   * @brief Return the dot product of two quaternions.
+   *
+   * @since_tizen 2.4
+   * @param[in] q1 - the first quaternion
+   * @param[in] q2 - the second quaternion
+   * @return the dot product of the two quaternions
+   */
+  static float Dot( const Quaternion &q1, const Quaternion &q2 );
+
+  /**
+   * @brief Linear Interpolation (using a straight line between the two quaternions).
+   *
+   * @since_tizen 2.4
+   * @param[in] q1 - the start quaternion
+   * @param[in] q2 - the end quaternion
+   * @param[in] t  - a progress value between 0 and 1
+   * @return the interpolated quaternion
+   */
+  static Quaternion Lerp( const Quaternion &q1, const Quaternion &q2, float t );
+
+  /**
+   * @brief Spherical Linear Interpolation (using the shortest arc of a great circle between
+   * the two quaternions).
+   *
+   * @since_tizen 2.4
+   * @param[in] q1 - the start quaternion
+   * @param[in] q2 - the end quaternion
+   * @param[in] progress  - a progress value between 0 and 1
+   * @return the interpolated quaternion
+   */
+  static Quaternion Slerp( const Quaternion &q1, const Quaternion &q2, float progress );
+
+  /**
+   * @brief This version of Slerp, used by Squad, does not check for theta > 90.
+   *
+   * @since_tizen 2.4
+   * @param[in] q1 - the start quaternion
+   * @param[in] q2 - the end quaternion
+   * @param[in] t  - a progress value between 0 and 1
+   * @return the interpolated quaternion
+   */
+  static Quaternion SlerpNoInvert( const Quaternion &q1, const Quaternion &q2, float t );
+
+  /**
+   * @brief Spherical Cubic Interpolation.
+   *
+   * @since_tizen 2.4
+   * @param[in] start - the start quaternion
+   * @param[in] end - the end quaternion
+   * @param[in] ctrl1  - the control quaternion for q1
+   * @param[in] ctrl2  - the control quaternion for q2
+   * @param[in] t  - a progress value between 0 and 1
+   * @return the interpolated quaternion
+   */
+  static Quaternion Squad( const Quaternion& start, const Quaternion& end,  const Quaternion& ctrl1,  const Quaternion& ctrl2, float t );
+
+  /**
+   * @brief Returns the shortest angle between two quaternions in Radians.
+   *
+   * @since_tizen 2.4
+   * @param[in] q1 - the first quaternion
+   * @param[in] q2 - the second quaternion
+   * @return the angle between the two quaternions.
+   */
+  static float AngleBetween( const Quaternion& q1, const Quaternion& q2 );
+
+  /**
+   * @brief Rotate v by this Quaternion (Quaternion must be unit).
+   *
+   * @since_tizen 2.4
+   * @param[in] vector a vector to rotate
+   * @return the rotated vector
+   */
+  Vector4 Rotate( const Vector4& vector ) const;
+
+  /**
+   * @brief Rotate v by this Quaternion (Quaternion must be unit).
+   *
+   * @since_tizen 2.4
+   * @param[in] vector a vector to rotate
+   * @return the rotated vector
+   */
+  Vector3 Rotate( const Vector3& vector ) const;
+
+private:
+
+  /**
+   * @brief Set the quaternion from 3 orthonormal axes.
+   *
+   * @since_tizen 2.4
+   * @param[in] xAxis The X axis
+   * @param[in] yAxis The Y axis
+   * @param[in] zAxis The Z axis
+   */
+  DALI_INTERNAL void SetFromAxes( const Vector3& xAxis, const Vector3& yAxis, const Vector3& zAxis );
+
+public:
+
+  Vector4 mVector;   ///< w component is s ( = cos(theta/2.0) )
+};
+
+/**
+ * @brief Print a Quaternion.
+ *
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] quaternion The quaternion to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<< (std::ostream& o, const Quaternion& quaternion);
+
+// Allow Quaternion to be treated as a POD type
+template <> struct TypeTraits< Quaternion > : public BasicTypes< Quaternion > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_QUATERNION_H__
diff --git a/dali/public-api/math/radian.h b/dali/public-api/math/radian.h
new file mode 100644 (file)
index 0000000..aad9160
--- /dev/null
@@ -0,0 +1,326 @@
+#ifndef __DALI_RADIAN_H__
+#define __DALI_RADIAN_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/public-api/math/degree.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief An angle in radians.
+ *
+ * This reduces ambiguity when using methods which accept angles in degrees or radians.
+ * @since_tizen 2.4
+ */
+struct Radian
+{
+  /**
+   * @brief default constructor, initialises to 0.
+   * @since_tizen 2.4
+   */
+  Radian()
+  : radian( 0.f )
+  { }
+
+  /**
+   * @brief Create an angle in radians.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The initial value in radians.
+   */
+  explicit Radian( float value )
+  : radian( value )
+  { }
+
+  /**
+   * @brief Create an angle in radians from an angle in degrees.
+   *
+   * @since_tizen 2.4
+   * @param[in] degree The initial value in degrees.
+   */
+  Radian( Degree degree )
+  : radian( degree.degree * Math::PI_OVER_180 )
+  { }
+
+  /**
+   * @brief Assign an angle from a float value.
+   *
+   * @since_tizen 2.4
+   * @param[in] value Float value in radians
+   * @return a reference to this object
+   */
+  Radian& operator=( float value )
+  {
+    radian = value;
+    return *this;
+  }
+
+  /**
+   * @brief Assign an angle from a Degree value.
+   *
+   * @since_tizen 2.4
+   * @param[in] degree The value in degrees.
+   * @return a reference to this object
+   */
+  Radian& operator=( Degree degree )
+  {
+    radian = degree.degree * Math::PI_OVER_180;
+    return *this;
+  }
+
+  /**
+   * @brief Conversion to float
+   * @since_tizen 2.4
+   * @return the float value of this Radian
+   */
+  operator float() const
+  {
+    return radian;
+  }
+
+public:
+
+  // member data
+  float radian; ///< The value in radians
+
+};
+
+// compiler generated destructor, copy constructor and assignment operators are ok as this class is POD
+
+// useful constant angles
+static const Radian ANGLE_360 = Radian( Math::PI * 2.f     ); ///< 360 degree turn in radians
+static const Radian ANGLE_315 = Radian( Math::PI * 1.75f   ); ///< 315 degree turn in radians
+static const Radian ANGLE_270 = Radian( Math::PI * 1.50f   ); ///< 270 degree turn in radians
+static const Radian ANGLE_225 = Radian( Math::PI * 1.25f   ); ///< 225 degree turn in radians
+static const Radian ANGLE_180 = Radian( Math::PI           ); ///< 180 degree turn in radians
+static const Radian ANGLE_135 = Radian( Math::PI * 0.75f   ); ///< 135 degree turn in radians
+static const Radian ANGLE_120 = Radian( Math::PI * 2.f/3.f ); ///< 120 degree turn in radians
+static const Radian ANGLE_90  = Radian( Math::PI_2         ); ///< 90 degree turn in radians
+static const Radian ANGLE_45  = Radian( Math::PI_4         ); ///< 45 degree turn in radians
+static const Radian ANGLE_60  = Radian( Math::PI / 3.f     ); ///< 60 degree turn in radians
+static const Radian ANGLE_30  = Radian( Math::PI / 6.f     ); ///< 30 degree turn in radians
+static const Radian ANGLE_0   = Radian( 0.0f               ); ///< 0 degree turn in radians
+
+/**
+ * @brief Compare equality between two radians.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if the values are identical
+ */
+inline bool operator==( Radian lhs, Radian rhs )
+{
+  return fabsf( lhs.radian - rhs.radian ) < Math::MACHINE_EPSILON_10; // expect Radian angles to be between 0 and 10 (multiplies of Math::PI)
+}
+
+/**
+ * @brief Compare inequality between two radians.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if the values are not identical
+ */
+inline bool operator!=( Radian lhs, Radian rhs )
+{
+  return !( operator==( lhs, rhs ) );
+}
+
+/**
+ * @brief Compare equality between a radian and degree.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if the values are identical
+ */
+inline bool operator==( Radian lhs, Degree rhs )
+{
+  return fabsf( lhs.radian - Radian( rhs ).radian ) < Math::MACHINE_EPSILON_100; // expect Degree angles to be between 0 and 999
+}
+
+/**
+ * @brief Compare inequality between a radian and a degree.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if the values are not identical
+ */
+inline bool operator!=( Radian lhs, Degree rhs )
+{
+  return !( operator==( lhs, rhs ) );
+}
+
+/**
+ * @brief Compare equality between a degree and a radian.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Degree to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if the values are identical
+ */
+inline bool operator==( Degree lhs, Radian rhs )
+{
+  return fabsf( Radian( lhs ).radian - rhs.radian ) < Math::MACHINE_EPSILON_100; // expect Degree angles to be between 0 and 999
+}
+
+/**
+ * @brief Compare inequality between a degree and a radian.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Degree to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if the values are not identical
+ */
+inline bool operator!=( Degree lhs, Radian rhs )
+{
+  return !( operator==( lhs, rhs ) );
+}
+
+/**
+ * @brief Compare greater than between two radians
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if lhs is greater than rhs
+ */
+inline bool operator>( Radian lhs, Radian rhs )
+{
+  return lhs.radian > rhs.radian;
+}
+
+/**
+ * @brief Compare greater than between a radian and a degree.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if lhs is greater than rhs
+ */
+inline bool operator>( Radian lhs, Degree rhs )
+{
+  return lhs.radian > Radian(rhs).radian;
+}
+
+/**
+ * @brief Compare greater than between a radian and a degree.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if lhs is greater than rhs
+ */
+inline bool operator>( Degree lhs, Radian rhs )
+{
+  return Radian(lhs).radian > rhs.radian;
+}
+
+/**
+ * @brief Compare less than between two radians.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if lhs is less than rhs
+ */
+inline bool operator<( Radian lhs, Radian rhs )
+{
+  return lhs.radian < rhs.radian;
+}
+
+/**
+ * @brief Compare less than between a radian and a degree.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to compare
+ * @param[in] rhs Degree to compare to
+ * @return true if lhs is less than rhs
+ */
+inline bool operator<( Radian lhs, Degree rhs )
+{
+  return lhs.radian < Radian(rhs).radian;
+}
+
+/**
+ * @brief Compare less than between a degree and a radian.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Degree to compare
+ * @param[in] rhs Radian to compare to
+ * @return true if lhs is less than rhs
+ */
+inline bool operator<( Degree lhs, Radian rhs )
+{
+  return Radian(lhs).radian < rhs.radian;
+}
+
+/**
+ * @brief Multiply Radian with a float
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs Radian to multiply
+ * @param[in] rhs float to multiply
+ * @return result of the multiplication
+ */
+inline Radian operator*( Radian lhs, float rhs )
+{
+  return Radian( lhs.radian * rhs );
+}
+
+/**
+ * @brief Negate the radian
+ * @since_tizen 2.4
+ * @return The negative angle
+ */
+inline Radian operator-( Radian in )
+{
+   return Radian( -in.radian );
+}
+
+/**
+ * @brief Clamp a radian value
+ * @since_tizen 2.4
+ * @param angle to clamp
+ * @param min value
+ * @param max value
+ * @return the resulting radian
+ */
+inline Radian Clamp( Radian angle, float min, float max )
+{
+  return Radian( Clamp<float>( angle.radian, min, max ) );
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_RADIAN_H__
diff --git a/dali/public-api/math/random.h b/dali/public-api/math/random.h
new file mode 100644 (file)
index 0000000..730687a
--- /dev/null
@@ -0,0 +1,83 @@
+#ifndef __DALI_RANDOM_H__
+#define __DALI_RANDOM_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/vector4.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief Provides methods to generate and use random values.
+ * @since_tizen 2.4
+ */
+namespace Random
+{
+
+/**
+ * @brief Returns a random number between f0 and f1.
+ *
+ * Note, uses a limited number of values.
+ * @since_tizen 2.4
+ * @param[in] f0 the lower bound
+ * @param[in] f1 the upper bound
+ * @return a random value between the lower and upper bound
+ */
+inline float Range(float f0, float f1)
+{
+  float min = std::min(f0, f1);
+  float max = std::max(f0, f1);
+  return min + (rand() & 0xfff) * (max-min) * (1.0f/4095.0f);
+}
+
+/**
+ * @brief Function to return a normalized axis in a random direction.
+ *
+ * @since_tizen 2.4
+ * @return the axis
+ */
+inline Vector4 Axis()
+{
+  Vector4 axis;
+  // This function needs to return a vector with direction, that is to say a non-zero vector
+  // There is a possibility that a random vector will be a zero vector, so a loop is needed to ensure that a non-zero vector is returned
+  do
+  {
+    axis.x = Range(-1.0f, 1.0f);
+    axis.y = Range( 0.0f, 1.0f);
+    axis.z = Range( 0.0f, 1.0f);
+    axis.w = 0.0f;
+  } while (axis == Vector4::ZERO);
+  axis.Normalize();
+  return axis;
+}
+
+} // namespace Random
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_RANDOM_H__
diff --git a/dali/public-api/math/rect.h b/dali/public-api/math/rect.h
new file mode 100644 (file)
index 0000000..a38b324
--- /dev/null
@@ -0,0 +1,329 @@
+#ifndef __DALI_RECT_H__
+#define __DALI_RECT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <math.h>
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/math-utils.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief Template class to create and operate on rectangles.
+ * @since_tizen 2.4
+ */
+
+template< typename T = float >
+struct Rect
+{
+// Methods
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  Rect()
+  : x(0),
+    y(0),
+    width(0),
+    height(0)
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] x       x coordinate (or left)
+   * @param [in] y       y coordinate (or right)
+   * @param [in] width   width (or bottom)
+   * @param [in] height  height (or top)
+   */
+  Rect(T x, T y, T width, T height)
+  : x(x),
+    y(y),
+    width(width),
+    height(height)
+  {
+  }
+
+  /**
+   * @brief Copy constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  The original object
+   */
+  Rect(const Rect<T>& rhs)
+  {
+    x = rhs.x;
+    y = rhs.y;
+    width = rhs.width;
+    height = rhs.height;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  The original object
+   * @return reference to this
+   */
+  Rect<T>& operator= (const Rect<T>& rhs)
+  {
+    if (this != &rhs)
+    {
+      x = rhs.x;
+      y = rhs.y;
+      width = rhs.width;
+      height = rhs.height;
+    }
+
+    return *this;
+  }
+
+  /**
+   * @brief Assignment from individual values.
+   *
+   * @since_tizen 2.4
+   * @param[in] newX      x coordinate
+   * @param[in] newY      y coordinate
+   * @param[in] newWidth  width
+   * @param[in] newHeight height
+   */
+  void Set(T newX, T newY, T newWidth, T newHeight)
+  {
+    x = newX;
+    y = newY;
+    width = newWidth;
+    height = newHeight;
+  }
+
+  /**
+   * @brief Determines whether or not this Rectangle is empty.
+   *
+   * @since_tizen 2.4
+   * @return true if width or height are zero
+   */
+  bool IsEmpty() const
+  {
+    return width  == 0 ||
+      height == 0;
+  }
+
+  /**
+   * @brief Get the left of the rectangle.
+   *
+   * @since_tizen 2.4
+   * @return The left edge of the rectangle
+   */
+  T Left() const
+  {
+    return x;
+  }
+  /**
+   * @brief Get the right of the rectangle.
+   *
+   * @since_tizen 2.4
+   * @return The right edge of the rectangle
+   */
+  T Right() const
+  {
+    return x + width;
+  }
+
+  /**
+   * @brief Get the top of the rectangle.
+   *
+   * @since_tizen 2.4
+   * @return The top of the rectangle
+   */
+  T Top() const
+  {
+    return y;
+  }
+
+  /**
+   * @brief Get the bottom of the rectangle.
+   *
+   * @since_tizen 2.4
+   * @return The bottom of the rectangle
+   */
+  T Bottom() const
+  {
+    return y + height;
+  }
+
+  /**
+   * @brief Get the area of the rectangle.
+   *
+   * @since_tizen 2.4
+   * @return The area of the rectangle
+   */
+  T Area() const
+  {
+    return width * height;
+  }
+
+  /**
+   * @brief Determines whether or not this rectangle and the specified rectangle intersect.
+   *
+   * @since_tizen 2.4
+   * @param[in] other  The other rectangle to test against this rectangle
+   * @return           true if the rectangles intersect
+   */
+  bool Intersects(const Rect<T>& other) const
+  {
+    return (other.x + other.width)  > x           &&
+      other.x                 < (x + width) &&
+                                (other.y + other.height) > y           &&
+      other.y                 < (y + height);
+  }
+
+  /**
+   * @brief Determines whether or not this Rectangle contains the specified rectangle.
+   *
+   * @since_tizen 2.4
+   * @param[in] other  The other rectangle to test against this rectangle
+   * @return           true if the specified rectangle is contained
+   */
+  bool Contains(const Rect<T>& other) const
+  {
+    return other.x                  >= x           &&
+      (other.x + other.width)  <= (x + width) &&
+      other.y                  >= y           &&
+      (other.y + other.height) <= (y + height);
+  }
+
+public:   // Data
+
+  union
+  {
+    T x;      ///< X position of the rectangle
+    T left;   ///< The left value
+  };
+
+  union
+  {
+    T y;      ///< Y position of the rectangle
+    T right;  ///< The right value
+  };
+
+  union
+  {
+    T width;  ///< width of the rectangle
+    T bottom; ///< The bottom value
+  };
+
+  union
+  {
+    T height; ///< height of the rectangle
+    T top;    ///< The top value
+  };
+};
+
+/**
+ * @brief Equality operator.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs First operand
+ * @param[in] rhs Second operand
+ * @return true if boxes are exactly same
+ */
+template< typename T >
+inline bool operator==( const Rect<T>& lhs, const Rect<T>& rhs )
+{
+  return ( lhs.x == rhs.x )&&
+    ( lhs.y == rhs.y )&&
+    ( lhs.width == rhs.width )&&
+    ( lhs.height == rhs.height );
+}
+
+/**
+ * @brief Inequality operator.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs The first rectangle
+ * @param[in] rhs The second rectangle
+ * @return true if rectangles are not identical
+ */
+template< typename T >
+inline bool operator!=( const Rect<T>& lhs, const Rect<T>& rhs )
+{
+  return !(lhs == rhs);
+}
+
+/**
+ * @brief Equality operator specialization for float.
+ *
+ * @since_tizen 2.4
+ * @param[in] lhs The first rectangle
+ * @param[in] rhs The second rectangle
+ * @return true if rectangles are exactly same
+ */
+template<>
+inline bool operator==( const Rect<float>& lhs, const Rect<float>& rhs )
+{
+  return ( fabsf( lhs.x - rhs.x ) < GetRangedEpsilon(lhs.x, rhs.x) )&&
+    ( fabsf( lhs.y - rhs.y ) < GetRangedEpsilon(lhs.y, rhs.y) )&&
+    ( fabsf( lhs.width - rhs.width ) < GetRangedEpsilon(lhs.width, rhs.width) )&&
+    ( fabsf( lhs.height - rhs.height ) < GetRangedEpsilon(lhs.height, rhs.height) );
+}
+
+/**
+ * @brief IsEmpty specialization for float.
+ *
+ * @since_tizen 2.4
+ * @return true if the rectangle has zero size.
+ */
+template<>
+inline bool Rect<float>::IsEmpty() const
+{
+  return (fabsf(width)  <= GetRangedEpsilon(width, width)
+          ||
+          fabsf(height) <= GetRangedEpsilon(height, height));
+}
+
+/**
+ * @brief Convert the value of the rectangle into a string and insert in to an output stream.
+ *
+ * @since_tizen 2.4
+ * @param [in] stream The output stream operator.
+ * @param [in] rectangle the rectangle to output
+ * @return The output stream operator.
+ */
+template< typename T >
+inline std::ostream& operator<< (std::ostream& stream, const Rect<T>& rectangle)
+{
+  return stream << "[" << rectangle.x << ", " << rectangle.y << ", " << rectangle.width << ", " << rectangle.height << "]";
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_RECT_H__
diff --git a/dali/public-api/math/uint-16-pair.h b/dali/public-api/math/uint-16-pair.h
new file mode 100644 (file)
index 0000000..c9db70f
--- /dev/null
@@ -0,0 +1,203 @@
+#ifndef __DALI_UINT_16_PAIR_H__
+#define __DALI_UINT_16_PAIR_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief Simple class for passing around pairs of small unsigned integers.
+ *
+ * Use this for integer dimensions and points with limited range such as image
+ * sizes and pixel coordinates where a pair of floating point numbers is
+ * inefficient and illogical (i.e. the data is inherently integer).
+ * These are immutable. If you want to change a value, make a whole new object.
+ * One of these can be passed in a single 32 bit integer register on
+ * common architectures.
+ * @since_tizen 2.4
+ */
+class Uint16Pair
+{
+public:
+  /**
+   * @brief Default constructor for the (0, 0) vector.
+   * @since_tizen 2.4
+   */
+  Uint16Pair() : mData(0) {}
+
+  /**
+   * @brief Constructor taking separate x and y (width and height) parameters.
+   * @since_tizen 2.4
+   * @param[in] width The width or X dimension of the vector. Make sure it is less than 65536,
+   * @param[in] height The height or Y dimension of the vector. Make sure it is less than 65536,
+   */
+  Uint16Pair( uint32_t width, uint32_t height )
+  {
+    DALI_ASSERT_DEBUG( width < ( 1u << 16 ) && "Width parameter not representable." );
+    DALI_ASSERT_DEBUG( height < ( 1u << 16 ) && "Height parameter not representable." );
+
+    /* Do equivalent of the code below with one aligned memory access:
+     * mComponents[0] = width;
+     * mComponents[1] = height;
+     * Unit tests make sure this is equivalent.
+     **/
+    mData = (height << 16u) + width;
+  }
+
+  /**
+   * @brief Copy constructor.
+   * @since_tizen 2.4
+   */
+  Uint16Pair( const Uint16Pair& rhs )
+  {
+    mData = rhs.mData;
+  }
+
+  /**
+   * @brief @returns the x dimension stored in this 2-tuple.
+   * @since_tizen 2.4
+   */
+  uint16_t GetWidth() const
+  {
+    return mComponents[0];
+  }
+
+  /**
+   * @brief @returns the y dimension stored in this 2-tuple.
+   * @since_tizen 2.4
+   */
+  uint16_t GetHeight() const
+  {
+    return mComponents[1];
+  }
+
+  /**
+   * @brief @returns the x dimension stored in this 2-tuple.
+   * @since_tizen 2.4
+   */
+  uint16_t GetX()  const
+  {
+    return mComponents[0];
+  }
+
+  /**
+   * @brief @returns the y dimension stored in this 2-tuple.
+   * @since_tizen 2.4
+   */
+  uint16_t GetY() const
+  {
+    return mComponents[1];
+  }
+
+  /**
+   * @brief Equality operator.
+   * @since_tizen 2.4
+   */
+  bool operator==( const Uint16Pair& rhs ) const
+  {
+    return mData == rhs.mData;
+  }
+
+  /**
+   * @brief Inequality operator.
+   * @since_tizen 2.4
+   */
+  bool operator!=( const Uint16Pair& rhs ) const
+  {
+    return mData != rhs.mData;
+  }
+
+  /**
+   * @brief Less than comparison operator for storing in collections (not geometrically
+   * meaningful).
+   * @since_tizen 2.4
+   */
+  bool operator<( const Uint16Pair& rhs ) const
+  {
+    return mData < rhs.mData;
+  }
+
+  /**
+   * @brief Greater than comparison operator for storing in collections (not
+   * geometrically meaningful).
+   * @since_tizen 2.4
+   */
+  bool operator>( const Uint16Pair& rhs ) const
+  {
+    return mData > rhs.mData;
+  }
+
+  /**
+   * @brief Create an instance by rounding a floating point vector to closest
+   * integers.
+   *
+   * Uses a template for loose coupling, to save a header include, and allow any
+   * vector type with .x and .y members to be converted.
+   * @since_tizen 2.4
+   */
+  template<typename FLOAT_VECTOR_N_TYPE>
+  static Uint16Pair FromFloatVec2( const FLOAT_VECTOR_N_TYPE& from )
+  {
+    DALI_ASSERT_DEBUG( from.x + 0.5f < 65536.0f );
+    DALI_ASSERT_DEBUG( from.y + 0.5f < 65536.0f );
+    return Uint16Pair( from.x + 0.5f, from.y + 0.5f );
+  }
+
+  /**
+   * @brief Create an instance by rounding a floating point array to closest
+   * integers.
+   *
+   * Uses a template to allow any vector type with operator [] to be converted
+   * in addition to plain arrays.
+   * @since_tizen 2.4
+   */
+  template<typename FLOAT_ARRAY>
+  static Uint16Pair FromFloatArray( const FLOAT_ARRAY& from )
+  {
+    DALI_ASSERT_DEBUG( from[0] + 0.5f < 65536.0f );
+    DALI_ASSERT_DEBUG( from[1] + 0.5f < 65536.0f );
+    return Uint16Pair( from[0] + 0.5f, from[1] + 0.5f );
+  }
+
+private:
+  union
+  {
+    // Addressable view of X and Y:
+    uint16_t mComponents[2];
+    // Packed view of X and Y to force alignment and allow a faster copy:
+    uint32_t mData;
+  };
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_UINT_16_PAIR_H__
diff --git a/dali/public-api/math/vector2.cpp b/dali/public-api/math/vector2.cpp
new file mode 100644 (file)
index 0000000..6e4b07a
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/vector2.h>
+
+// EXTERNAL INCLUDES
+#include <math.h>
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+
+const Vector2 Vector2::ONE(1.0f, 1.0f);
+const Vector2 Vector2::XAXIS(1.0f, 0.0f);
+const Vector2 Vector2::YAXIS(0.0f, 1.0f);
+const Vector2 Vector2::NEGATIVE_XAXIS(-1.0f, 0.0f);
+const Vector2 Vector2::NEGATIVE_YAXIS(0.0f, -1.0f);
+const Vector2 Vector2::ZERO(0.0f, 0.0f);
+
+Vector2::Vector2(const Vector3& vec3)
+: x(vec3.x),
+  y(vec3.y)
+{
+}
+
+Vector2::Vector2(const Vector4& vec4)
+: x(vec4.x),
+  y(vec4.y)
+{
+}
+
+Vector2& Vector2::operator=(const Vector3& rhs)
+{
+  x = rhs.x;
+  y = rhs.y;
+
+  return *this;
+}
+
+Vector2& Vector2::operator=(const Vector4& rhs)
+{
+  x = rhs.x;
+  y = rhs.y;
+
+  return *this;
+}
+
+
+bool Vector2::operator==(const Vector2& rhs) const
+{
+  if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x))
+  {
+    return false;
+  }
+  if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y))
+  {
+    return false;
+  }
+
+  return true;
+}
+
+float Vector2::Length() const
+{
+  return sqrtf(LengthSquared());
+}
+
+float Vector2::LengthSquared() const
+{
+  return (x*x) + (y*y);
+}
+
+void Vector2::Normalize()
+{
+  float length = Length();
+  if( ! EqualsZero(length) )
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,2);
+
+    const float inverseLength = 1.0f / length;
+    x *= inverseLength;
+    y *= inverseLength;
+  }
+}
+
+void Vector2::Clamp( const Vector2& min, const Vector2& max )
+{
+  Dali::ClampInPlace<float>( x, min.x, max.x );
+  Dali::ClampInPlace<float>( y, min.y, max.y );
+}
+
+std::ostream& operator<< (std::ostream& o, const Vector2& vector)
+{
+  return o << "[" << vector.x << ", " << vector.y << "]";
+}
+
+Vector2 Clamp( const Vector2& v, const float& min, const float& max )
+{
+  Vector2 result( v );
+  result.Clamp( Vector2( min, min ) , Vector2( max, max ) );
+
+  return result;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/vector2.h b/dali/public-api/math/vector2.h
new file mode 100644 (file)
index 0000000..0bb1c53
--- /dev/null
@@ -0,0 +1,520 @@
+#ifndef __DALI_VECTOR_2_H__
+#define __DALI_VECTOR_2_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+struct Vector3;
+struct Vector4;
+
+/**
+ * @brief A two dimensional vector.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API Vector2
+{
+// (x width) and (y height) must be consecutive in memory.
+// No other data must be added before (x width) member.
+// No virtual methods must be added to this struct.
+
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  Vector2()
+  : x(0.0f),
+    y(0.0f)
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] x x or width component
+   * @param[in] y y or height component
+   */
+  explicit Vector2(float x, float y)
+  : x(x), y(y)
+  {
+  }
+
+  /**
+   * @brief Conversion constructor from an array of two floats.
+   *
+   * @since_tizen 2.4
+   * @param [in] array of xy
+   */
+  explicit Vector2(const float* array)
+  : x(array[0]),
+    y(array[1])
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec3 Vector3 to create this vector from
+   */
+  explicit Vector2(const Vector3& vec3);
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec4 Vector4 to create this vector from
+   */
+  explicit Vector2(const Vector4& vec4);
+
+// Constants
+
+  static const Vector2 ONE;               ///< (1.0f,1.0f)
+  static const Vector2 XAXIS;             ///< Vector representing the X axis
+  static const Vector2 YAXIS;             ///< Vector representing the Y axis
+  static const Vector2 NEGATIVE_XAXIS;    ///< Vector representing the negative X axis
+  static const Vector2 NEGATIVE_YAXIS;    ///< Vector representing the negative Y axis
+  static const Vector2 ZERO;              ///< (0.0f, 0.0f)
+
+// API
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] array of floats
+   * @return itself
+   */
+  Vector2& operator=(const float* array)
+  {
+    x = array[0];
+    y = array[1];
+
+    return *this;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to assign.
+   * @return itself
+   */
+  Vector2& operator=(const Vector3& rhs);
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to assign.
+   * @return itself
+   */
+  Vector2& operator=(const Vector4& rhs);
+
+  /**
+   * @brief Addition operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return A vector containing the result of the addition
+   */
+  Vector2 operator+(const Vector2& rhs) const
+  {
+    Vector2 temp(*this);
+
+    return temp += rhs;
+  }
+
+  /**
+   * @brief Addition assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return itself
+   */
+  Vector2& operator+=(const Vector2& rhs)
+  {
+    x += rhs.x;
+    y += rhs.y;
+
+    return *this;
+  }
+
+  /**
+   * @brief Subtraction operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs  the vector to subtract
+   * @return A vector containing the result of the subtraction
+   */
+  Vector2 operator-(const Vector2& rhs) const
+  {
+    Vector2 temp(*this);
+
+    return temp -= rhs;
+  }
+
+  /**
+   * @brief Subtraction assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to subtract
+   * @return itself
+   */
+  Vector2& operator-=(const Vector2& rhs)
+  {
+    x -= rhs.x;
+    y -= rhs.y;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return A vector containing the result of the multiplication
+   */
+  Vector2 operator*(const Vector2& rhs) const
+  {
+    return Vector2(x * rhs.x, y * rhs.y);
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return A vector containing the result of the scaling
+   */
+  Vector2 operator*(float rhs) const
+  {
+    return Vector2(x * rhs, y * rhs);
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return itself
+   */
+  Vector2& operator*=(const Vector2& rhs)
+  {
+    x *= rhs.x;
+    y *= rhs.y;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return itself
+   */
+  Vector2& operator*=(float rhs)
+  {
+    x *= rhs;
+    y *= rhs;
+
+    return *this;
+  }
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return A vector containing the result of the division
+   */
+  Vector2 operator/(const Vector2& rhs) const
+  {
+    return Vector2(x / rhs.x, y / rhs.y);
+  }
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The float value to scale the vector by
+   * @return A vector containing the result of the scaling
+   */
+  Vector2 operator/(float rhs) const
+  {
+    return Vector2(x / rhs, y / rhs);
+  }
+
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return itself
+   */
+  Vector2& operator/=(const Vector2& rhs)
+  {
+    x /= rhs.x;
+    y /= rhs.y;
+
+    return *this;
+  }
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector by
+   * @return itself
+   */
+  Vector2& operator/=(float rhs)
+  {
+    x /= rhs;
+    y /= rhs;
+
+    return *this;
+  }
+
+  /**
+   * @brief Unary negation operator.
+   *
+   * @since_tizen 2.4
+   * @return A vector containg the negation
+   */
+  Vector2 operator-() const
+  {
+    Vector2 temp(-x, -y);
+
+    return temp;
+  }
+
+  /**
+   * @brief Equality operator.
+   *
+   * utilises appropriate machine epsilon values;
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are equal
+   */
+  bool operator==(const Vector2& rhs) const;
+
+  /**
+   * @brief Inequality operator.
+   *
+   * utilises appropriate machine epsilon values;
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are not equal
+   */
+  bool operator!=(const Vector2& rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /**
+   * @brief Const array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0 or 1
+   * @since_tizen 2.4
+   * @param[in] index Subscript
+   * @return    The float at the given index
+   */
+  const float& operator[](const unsigned int index) const
+  {
+    DALI_ASSERT_ALWAYS( index < 2 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Mutable array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0 or 1
+   * @since_tizen 2.4
+   * @param[in] index Subscript index
+   * @return    The float at the given index.
+   */
+  float& operator[](const unsigned int index)
+  {
+    DALI_ASSERT_ALWAYS( index < 2 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Returns the length of the vector.
+   *
+   * @since_tizen 2.4
+   * @return the length of the vector
+   */
+  float Length() const;
+
+  /**
+   * @brief Returns the length of the vector squared.
+   *
+   * This is more efficient than Length() for threshold
+   * testing as it avoids the use of a square root.
+   * @since_tizen 2.4
+   * @return the length of the vector squared.
+   */
+  float LengthSquared() const;
+
+  /**
+   * @brief Sets the vector to be unit length, whilst maintaining its direction.
+   *
+   * @since_tizen 2.4
+   */
+  void Normalize();
+
+  /**
+    * @brief Clamps the vector between minimum and maximum vectors.
+    *
+    * @since_tizen 2.4
+    * @param [in] min the minimum vector
+    * @param [in] max the maximum vector
+   */
+  void Clamp( const Vector2& min, const Vector2& max );
+
+  /**
+   * @brief Returns the contents of the vector as an array of 2 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or width)
+   * 1: y (or height)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 2 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const float* AsFloat() const {return &x;}
+
+  /**
+   * @brief Returns the contents of the vector as an array of 2 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or width)
+   * 1: y (or height)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 2 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  float* AsFloat() {return &x;}
+
+public: // Data
+
+  // NOTE
+  // (x width) and (y height) must be consecutive in memory.
+  // No other data must be added before (x width) member.
+  // No virtual methods must be added to this struct.
+  union
+  {
+    float x;     ///< x component
+    float width; ///< width
+  };
+
+  union
+  {
+    float y;      ///< y component
+    float height; ///< height
+  };
+
+};
+
+/**
+ * @brief Size is an alias of Dali::Vector2
+ * @since_tizen 2.4
+ */
+typedef Vector2 Size;
+
+/**
+ * @brief Print a Vector2.
+ *
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] vector The vector to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<< (std::ostream& o, const Vector2& vector);
+
+/**
+ * @brief Returns a vector with components set to the minimum of the corresponding component in a and b.
+ *
+ * If a=0,1 and b=1,0  returns a vector of 0,0.
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the minimum of each component from a and b
+ */
+inline Vector2 Min( const Vector2& a, const Vector2& b )
+{
+  return Vector2( a.x < b.x ? a.x : b.x , a.y < b.y ? a.y : b.y );
+}
+
+/**
+ * @brief Returns a vector with components set to the maximum of the corresponding component in a and b.
+ *
+ * If a=0,1 and b=1,0  returns a vector of 1,1
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the maximum of each component from a and b
+ */
+inline Vector2 Max( const Vector2& a, const Vector2& b )
+{
+  return Vector2( a.x > b.x ? a.x : b.x , a.y > b.y ? a.y : b.y );
+}
+
+/**
+ * @brief Clamps each of vector v's components between minimum and maximum values.
+ *
+ * @since_tizen 2.4
+ * @param [in] v     a vector
+ * @param [in] min the minimum value
+ * @param [in] max the maximum value
+ * @return     a vector containing the clamped components of v
+ */
+DALI_IMPORT_API Vector2 Clamp( const Vector2& v, const float& min, const float& max );
+
+// Allow Vector2 to be treated as a POD type
+template <> struct TypeTraits< Vector2 > : public BasicTypes< Vector2 > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_VECTOR_2_H__
diff --git a/dali/public-api/math/vector3.cpp b/dali/public-api/math/vector3.cpp
new file mode 100644 (file)
index 0000000..2b410d0
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/quaternion.h>
+
+// EXTERNAL INCLUDES
+#include <math.h>
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+using Internal::PerformanceMonitor;
+
+const Vector3 Vector3::ONE(1.0f, 1.0f, 1.0f);
+const Vector3 Vector3::XAXIS(1.0f, 0.0f, 0.0f);
+const Vector3 Vector3::YAXIS(0.0f, 1.0f, 0.0f);
+const Vector3 Vector3::ZAXIS(0.0f, 0.0f, 1.0f);
+const Vector3 Vector3::NEGATIVE_XAXIS(-1.0f, 0.0f, 0.0f);
+const Vector3 Vector3::NEGATIVE_YAXIS(0.0f, -1.0f, 0.0f);
+const Vector3 Vector3::NEGATIVE_ZAXIS(0.0f, 0.0f, -1.0f);
+const Vector3 Vector3::ZERO(0.0f, 0.0f, 0.0f);
+
+Vector3::Vector3( const Vector2& vec2 )
+: x(vec2.x),
+  y(vec2.y),
+  z(0.0f)
+{
+}
+
+Vector3::Vector3( const Vector4& vec4 )
+: x(vec4.x),
+  y(vec4.y),
+  z(vec4.z)
+{
+}
+
+Vector3& Vector3::operator=(const Vector2& rhs)
+{
+  x = rhs.x;
+  y = rhs.y;
+  z = 0.0f;
+
+  return *this;
+}
+
+Vector3& Vector3::operator=(const Vector4& rhs)
+{
+  x = rhs.x;
+  y = rhs.y;
+  z = rhs.z;
+
+  return *this;
+}
+
+Vector3& Vector3::operator*=(const Quaternion& rhs)
+{
+  // nVidia SDK implementation
+  Vector3 qvec(rhs.mVector.x, rhs.mVector.y, rhs.mVector.z);
+
+  Vector3 uv( (qvec.y * z) - (qvec.z * y),
+              (qvec.z * x) - (qvec.x * z),
+              (qvec.x * y) - (qvec.y * x) );
+
+  Vector3 uuv( (qvec.y * uv.z) - (qvec.z * uv.y),
+               (qvec.z * uv.x) - (qvec.x * uv.z),
+               (qvec.x * uv.y) - (qvec.y * uv.x) );
+
+  uv *= rhs.mVector.w;
+
+  x += (uv.x + uuv.x) * 2.0f;
+  y += (uv.y + uuv.y) * 2.0f;
+  z += (uv.z + uuv.z) * 2.0f;
+
+  return *this;
+}
+
+bool Vector3::operator==(const Vector3& rhs) const
+{
+  if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x) )
+  {
+    return false;
+  }
+  if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y) )
+  {
+    return false;
+  }
+  if (fabsf(z - rhs.z) > GetRangedEpsilon(z, rhs.z) )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+float Vector3::Dot(const Vector3 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return x * other.x + y * other.y + z * other.z;
+}
+
+Vector3 Vector3::Cross(const Vector3 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,6);
+
+  return Vector3( (y * other.z) - (z * other.y),
+                  (z * other.x) - (x * other.z),
+                  (x * other.y) - (y * other.x));
+}
+
+float Vector3::Length() const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return sqrtf(x*x + y*y + z*z);
+}
+
+float Vector3::LengthSquared() const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return x*x + y*y + z*z;
+}
+
+void Vector3::Normalize()
+{
+  float length = Length();
+  if( ! EqualsZero(length) )
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+    const float inverseLength = 1.0f / length;
+    x *= inverseLength;
+    y *= inverseLength;
+    z *= inverseLength;
+  }
+}
+
+void Vector3::Clamp( const Vector3& min, const Vector3& max )
+{
+  Dali::ClampInPlace<float>( x, min.x, max.x );
+  Dali::ClampInPlace<float>( y, min.y, max.y );
+  Dali::ClampInPlace<float>( z, min.z, max.z );
+}
+
+std::ostream& operator<< (std::ostream& o, const Vector3& vector)
+{
+  return o << "[" << vector.x << ", " << vector.y << ", " << vector.z << "]";
+}
+
+Vector3 Clamp( const Vector3& v, const float& min, const float& max )
+{
+  Vector3 result( v );
+  result.Clamp( Vector3( min, min, min ) , Vector3( max, max, max ) );
+
+  return result;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/vector3.h b/dali/public-api/math/vector3.h
new file mode 100644 (file)
index 0000000..f7d5bad
--- /dev/null
@@ -0,0 +1,614 @@
+#ifndef __DALI_VECTOR_3_H__
+#define __DALI_VECTOR_3_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+struct Vector2;
+struct Vector4;
+class Quaternion;
+
+/**
+ * @brief A three dimensional vector.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API Vector3
+{
+// Construction
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  // NOTE
+  // (x width r), (y height g), (z depth b) must be consecutive in memory.
+  // No other data must be added before (x width r) member.
+  // No virtual methods must be added to this struct.
+  Vector3()
+  : x(0.0f),
+    y(0.0f),
+    z(0.0f)
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] x (or width) component
+   * @param [in] y (or height) component
+   * @param [in] z (or depth) component
+   */
+  explicit Vector3(float x, float y, float z)
+  : x(x),
+    y(y),
+    z(z)
+  {
+  }
+
+  /**
+   * @brief Conversion constructor from an array of three floats.
+   *
+   * @since_tizen 2.4
+   * @param [in] array of xyz
+   */
+  explicit Vector3(const float* array)
+  : x(array[0]),
+    y(array[1]),
+    z(array[2])
+  {
+  }
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec2 Vector2 to create this vector from
+   */
+  explicit Vector3( const Vector2& vec2 );
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec4 Vector4 to create this vector from
+   */
+  explicit Vector3( const Vector4& vec4 );
+
+// Constants
+
+  static const Vector3 ONE;               ///< (1.0f,1.0f,1.0f)
+  static const Vector3 XAXIS;             ///< Vector representing the X axis
+  static const Vector3 YAXIS;             ///< Vector representing the Y axis
+  static const Vector3 ZAXIS;             ///< Vector representing the Z axis
+  static const Vector3 NEGATIVE_XAXIS;    ///< Vector representing the negative X axis
+  static const Vector3 NEGATIVE_YAXIS;    ///< Vector representing the negative Y axis
+  static const Vector3 NEGATIVE_ZAXIS;    ///< Vector representing the negative Z axis
+  static const Vector3 ZERO;              ///< (0.0f, 0.0f, 0.0f)
+
+// API
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] array of floats
+   * @return itself
+   */
+  Vector3& operator=(const float* array)
+  {
+    x = array[0];
+    y = array[1];
+    z = array[2];
+
+    return *this;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to assign.
+   * @return itself
+   */
+  Vector3& operator=(const Vector2& rhs);
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to assign.
+   * @return itself
+   */
+  Vector3& operator=(const Vector4& rhs);
+
+  /**
+   * @brief Addition operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return A vector containing the result of the addition
+   */
+  Vector3 operator+(const Vector3& rhs) const
+  {
+    Vector3 temp(*this);
+
+    return temp += rhs;
+  }
+
+  /**
+   * @brief Addition assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return itself
+   */
+  Vector3& operator+=(const Vector3& rhs)
+  {
+    x += rhs.x;
+    y += rhs.y;
+    z += rhs.z;
+
+    return *this;
+  }
+
+  /**
+   * @brief Subtraction operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs  the vector to subtract
+   * @return A vector containing the result of the subtraction
+   */
+  Vector3 operator-(const Vector3& rhs) const
+  {
+    Vector3 temp(*this);
+
+    return temp -= rhs;
+  }
+
+  /**
+   * @brief Subtraction assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to subtract
+   * @return itself
+   */
+  Vector3& operator-=(const Vector3& rhs)
+  {
+    x -= rhs.x;
+    y -= rhs.y;
+    z -= rhs.z;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return A vector containing the result of the multiplication
+   */
+  Vector3 operator*(const Vector3& rhs) const
+  {
+    Vector3 temp(*this);
+
+    return temp *= rhs;
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return A vector containing the result of the scaling
+   */
+  Vector3 operator*(float rhs) const
+  {
+    return Vector3(x * rhs, y * rhs, z * rhs);
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return itself
+   */
+  Vector3& operator*=(const Vector3& rhs)
+  {
+    x *= rhs.x;
+    y *= rhs.y;
+    z *= rhs.z;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return itself
+   */
+  Vector3& operator*=(float rhs)
+  {
+    x *= rhs;
+    y *= rhs;
+    z *= rhs;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the Quaternion value to multiply the vector by
+   * @return itself
+   */
+  Vector3& operator*=(const Quaternion& rhs);
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return A vector containing the result of the division
+   */
+  Vector3 operator/(const Vector3& rhs) const
+  {
+    Vector3 temp(*this);
+
+    return temp /= rhs;
+  }
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The float value to scale the vector by
+   * @return A vector containing the result of the scaling
+   */
+  Vector3 operator/(float rhs) const
+  {
+    return Vector3(x / rhs, y / rhs, z / rhs);
+  }
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return itself
+   */
+  Vector3& operator/=(const Vector3& rhs)
+  {
+    x /= rhs.x;
+    y /= rhs.y;
+    z /= rhs.z;
+
+    return *this;
+  }
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector by
+   * @return itself
+   */
+  Vector3& operator/=(float rhs)
+  {
+    float oneOverRhs = 1.0f / rhs;
+    x *= oneOverRhs;
+    y *= oneOverRhs;
+    z *= oneOverRhs;
+
+    return *this;
+  }
+
+  /**
+   * @brief Unary negation operator.
+   *
+   * @since_tizen 2.4
+   * @return A vector containg the negation
+   */
+  Vector3 operator-() const
+  {
+    Vector3 temp(-x, -y, -z);
+
+    return temp;
+  }
+
+  /**
+   * @brief Equality operator.
+   *
+   * utilises appropriate machine epsilon values;
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are equal
+   */
+  bool operator==(const Vector3& rhs) const;
+
+  /**
+   * @brief Inequality operator.
+   *
+   * utilises appropriate machine epsilon values;
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are not equal
+   */
+  bool operator!=(const Vector3& rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /**
+   * @brief Const array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0, 1 or 2
+   * @since_tizen 2.4
+   * @param[in] index Subscript
+   * @return    The float at the given index.
+   */
+  const float& operator[](const unsigned int index) const
+  {
+    DALI_ASSERT_ALWAYS( index < 3 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Mutable array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0, 1 or 2
+   * @since_tizen 2.4
+   * @param[in] index Subscript index
+   * @return    The float at the given index.
+   */
+  float& operator[](const unsigned int index)
+  {
+    DALI_ASSERT_ALWAYS( index < 3 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Returns the dot product of this vector and another vector.
+   *
+   * The dot product is the length of one vector in the direction of another vector.
+   * This is great for lighting, threshold testing the angle between two unit vectors,
+   * calculating the distance between two points in a particular direction.
+   * @since_tizen 2.4
+   * @param [in]  other     the other vector
+   * @return          the dot product
+   */
+  float Dot(const Vector3& other) const;
+
+  /**
+   * @brief Returns the cross produce of this vector and another vector.
+   *
+   * The cross produce of two vectors is a vector which is perpendicular to the plane of the
+   * two vectors. This is great for calculating normals and making matrices orthogonal.
+   *
+   * @since_tizen 2.4
+   * @param [in] other    the other vector
+   * @return         the cross product
+   */
+  Vector3 Cross(const Vector3& other) const;
+
+  /**
+   * @brief Returns the length of the vector.
+   *
+   * @since_tizen 2.4
+   * @return the length of the vector
+   */
+  float Length() const;
+
+  /**
+   * @brief Returns the length of the vector squared.
+   *
+   * This is more efficient than Length() for threshold
+   * testing as it avoids the use of a square root.
+   * @since_tizen 2.4
+   * @return the length of the vector squared.
+   */
+  float LengthSquared() const;
+
+  /**
+   * @brief Sets the vector to be unit length, whilst maintaining its direction.
+   *
+   * @since_tizen 2.4
+   */
+  void Normalize();
+
+  /**
+   * @brief Clamps the vector between minimum and maximum vectors.
+   *
+   * @since_tizen 2.4
+   * @param [in] min the minimum vector
+   * @param [in] max the maximum vector
+   */
+  void Clamp( const Vector3& min, const Vector3& max );
+
+  /**
+   * @brief Returns the contents of the vector as an array of 3 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or width, or r)
+   * 1: y (or height, or g)
+   * 2: z (or depth, or b)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 3 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const float* AsFloat() const {return &x;}
+
+  /**
+   * @brief Returns the contents of the vector as an array of 3 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or width, or r)
+   * 1: y (or height, or g)
+   * 2: z (or depth, or b)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 3 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  float* AsFloat() {return &x;}
+
+  /**
+   * @brief Returns the x & y components (or width & height, or r & g) as a Vector2.
+   *
+   * @since_tizen 2.4
+   * @return the partial vector contents as Vector2 (x,y)
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const Vector2& GetVectorXY() const {return reinterpret_cast<const Vector2&>(x);}
+
+  /**
+   * @brief Returns the x & y components (or width & height, or r & g) as a Vector2.
+   *
+   * @since_tizen 2.4
+   * @return the partial vector contents as Vector2 (x,y)
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  Vector2& GetVectorXY() {return reinterpret_cast<Vector2&>(x);}
+
+  /**
+   * @brief Returns the y & z components (or height & depth, or g & b) as a Vector2.
+   *
+   * @since_tizen 2.4
+   * @return the partial vector contents as Vector2 (y,z)
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const Vector2& GetVectorYZ() const {return reinterpret_cast<const Vector2&>(y);}
+
+  /**
+   * @brief Returns the y & z components (or height & depth, or g & b) as a Vector2.
+   *
+   * @since_tizen 2.4
+   * @return the partial vector contents as Vector2 (y,z)
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  Vector2& GetVectorYZ() {return reinterpret_cast<Vector2&>(y);}
+
+// Data
+
+  // NOTE
+  // (x width r), (y height g), (z depth b) must be consecutive in memory.
+  // No other data must be added before (x width r) member.
+  // No virtual methods must be added to this struct.
+  union
+  {
+    float x;      ///< x component
+    float width;  ///< width component
+    float r;      ///< red component
+  };
+  union
+  {
+    float y;      ///< y component
+    float height; ///< height component
+    float g;      ///< green component
+  };
+  union
+  {
+    float z;      ///< z component
+    float depth;  ///< depth component
+    float b;      ///< blue component
+  };
+};
+
+/**
+ * @brief Print a Vector3.
+ *
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] vector The vector to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<< (std::ostream& o, const Vector3& vector);
+
+/**
+ * @brief Returns a vector with components set to the minimum of the corresponding component in a and b.
+ *
+ * If a=0,1,2 and b=2,1,0  returns a vector of 2,1,2.
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the minimum of each component from a and b
+ */
+inline Vector3 Min( const Vector3& a, const Vector3& b )
+{
+  return Vector3( a.x < b.x ? a.x : b.x ,
+                  a.y < b.y ? a.y : b.y,
+                  a.z < b.z ? a.z : b.z );
+}
+
+/**
+ * @brief Returns a vector with components set to the maximum of the corresponding component in a and b.
+ *
+ * If a=0,1 and b=1,0  returns a vector of 1,1
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the maximum of each component from a and b
+ */
+inline Vector3 Max( const Vector3& a, const Vector3& b )
+{
+  return Vector3( a.x > b.x ? a.x : b.x,
+                  a.y > b.y ? a.y : b.y,
+                  a.z > b.z ? a.z : b.z );
+}
+
+/**
+ * @brief Clamps each of vector v's components between minimum and maximum values.
+ *
+ * @since_tizen 2.4
+ * @param [in] v     a vector
+ * @param [in] min the minimum value
+ * @param [in] max the maximum value
+ * @return     a vector containing the clamped components of v
+ */
+DALI_IMPORT_API Vector3 Clamp( const Vector3& v, const float& min, const float& max );
+
+// Allow Vector3 to be treated as a POD type
+template <> struct TypeTraits< Vector3 > : public BasicTypes< Vector3 > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_VECTOR_3_H__
diff --git a/dali/public-api/math/vector4.cpp b/dali/public-api/math/vector4.cpp
new file mode 100644 (file)
index 0000000..3924f6c
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/math/vector4.h>
+
+// EXTERNAL INCLUDES
+#include <math.h>
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/math-utils.h>
+#include <dali/internal/render/common/performance-monitor.h>
+
+namespace Dali
+{
+
+using Internal::PerformanceMonitor;
+
+const Vector4 Vector4::ONE(1.0f, 1.0f, 1.0f, 1.0f);
+const Vector4 Vector4::XAXIS(1.0f, 0.0f, 0.0f, 0.0f);
+const Vector4 Vector4::YAXIS(0.0f, 1.0f, 0.0f, 0.0f);
+const Vector4 Vector4::ZAXIS(0.0f, 0.0f, 1.0f, 0.0f);
+const Vector4 Vector4::ZERO(0.0f, 0.0f, 0.0f, 0.0f);
+
+Vector4::Vector4( const Vector2& vec2 )
+: x(vec2.x),
+  y(vec2.y),
+  z(0.0f),
+  w(0.0f)
+{
+}
+
+Vector4::Vector4( const Vector3& vec3 )
+: x(vec3.x),
+  y(vec3.y),
+  z(vec3.z),
+  w(0.0f)
+{
+}
+
+Vector4& Vector4::operator=(const Vector2& vec2 )
+{
+  // only set x and y
+  x = vec2.x;
+  y = vec2.y;
+  return *this;
+}
+
+Vector4& Vector4::operator=(const Vector3& vec3 )
+{
+  // only set x, y and z
+  x = vec3.x;
+  y = vec3.y;
+  z = vec3.z;
+  return *this;
+}
+
+
+bool Vector4::operator==(const Vector4& rhs) const
+{
+  if (fabsf(x - rhs.x) > GetRangedEpsilon(x, rhs.x) )
+  {
+    return false;
+  }
+  if (fabsf(y - rhs.y) > GetRangedEpsilon(y, rhs.y) )
+  {
+    return false;
+  }
+  if (fabsf(z - rhs.z) > GetRangedEpsilon(z, rhs.z) )
+  {
+    return false;
+  }
+  if (fabsf(w - rhs.w) > GetRangedEpsilon(w, rhs.w) )
+  {
+    return false;
+  }
+
+  return true;
+}
+
+float Vector4::Dot(const Vector3 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return x * other.x + y * other.y + z * other.z;
+}
+
+float Vector4::Dot(const Vector4 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return x * other.x + y * other.y + z * other.z;
+}
+
+float Vector4::Dot4(const Vector4 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,4);
+
+  return x * other.x + y * other.y + z * other.z + w * other.w;
+}
+
+Vector4 Vector4::Cross(const Vector4 &other) const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,6);
+
+  return Vector4( (y * other.z) - (z * other.y),
+                  (z * other.x) - (x * other.z),
+                  (x * other.y) - (y * other.x),
+                  0.0f);
+}
+
+// Will always return positive square root
+float Vector4::Length() const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return sqrtf(x*x + y*y + z*z);
+}
+
+float Vector4::LengthSquared() const
+{
+  MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY,3);
+
+  return x*x + y*y + z*z;
+}
+
+void Vector4::Normalize()
+{
+  const float length = Length();
+
+  // In the case where the length is exactly zero, the vector cannot be normalized.
+  if ( ! EqualsZero( length ) )
+  {
+    MATH_INCREASE_BY(PerformanceMonitor::FLOAT_POINT_MULTIPLY, 3);
+
+    const float inverseLength = 1.0f / length;
+    x *= inverseLength;
+    y *= inverseLength;
+    z *= inverseLength;
+  }
+}
+
+void Vector4::Clamp( const Vector4& min, const Vector4& max )
+{
+  Dali::ClampInPlace<float>( x, min.x, max.x );
+  Dali::ClampInPlace<float>( y, min.y, max.y );
+  Dali::ClampInPlace<float>( z, min.z, max.z );
+  Dali::ClampInPlace<float>( w, min.w, max.w );
+}
+
+std::ostream& operator<< (std::ostream& o, const Vector4& vector)
+{
+  return o << "[" << vector.x << ", " << vector.y << ", " << vector.z << ", " << vector.w << "]";
+}
+
+Vector4 Clamp( const Vector4& v, const float& min, const float& max )
+{
+  Vector4 result( v );
+  result.Clamp( Vector4( min, min, min, min ), Vector4( max, max, max, max) );
+
+  return result;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/math/vector4.h b/dali/public-api/math/vector4.h
new file mode 100644 (file)
index 0000000..9383ad4
--- /dev/null
@@ -0,0 +1,617 @@
+#ifndef __DALI_VECTOR_4_H__
+#define __DALI_VECTOR_4_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/type-traits.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+struct Vector2;
+struct Vector3;
+
+/**
+ * @brief A four dimensional vector.
+ *
+ * Components can be used as position or offset (x,y,z,w); color (r,g,b,a) or texture coords(s,t,p,q)
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API Vector4
+{
+// NOTE
+// xrs, ygt, zbp and waq must be consecutive in memory.
+// No other data must be added before xrs member.
+// No virtual methods must be added to this struct.
+
+// Construction
+
+  /**
+   * @brief Default constructor, initializes the vector to 0.
+   * @since_tizen 2.4
+   */
+  Vector4()
+  : x(0.0f),
+    y(0.0f),
+    z(0.0f),
+    w(0.0f)
+  {
+  }
+
+  /**
+   * @brief Conversion constructor from four floats.
+   *
+   * @since_tizen 2.4
+   * @param [in] x (or r/s) component
+   * @param [in] y (or g/t) component
+   * @param [in] z (or b/p) component
+   * @param [in] w (or a/q) component
+   */
+  explicit Vector4(float x, float y, float z, float w)
+  : x(x),
+    y(y),
+    z(z),
+    w(w)
+  {
+  }
+
+
+  /**
+   * @brief Conversion constructor from an array of four floats.
+   *
+   * @since_tizen 2.4
+   * @param [in] array of either xyzw/rgba/stpq
+   */
+  explicit Vector4(const float* array)
+  : x(array[0]),
+    y(array[1]),
+    z(array[2]),
+    w(array[3])
+  {
+  }
+
+  /**
+   * @brief Conversion constructor from Vector2.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec2 to copy from, z and w are initialized to 0
+   */
+  explicit Vector4( const Vector2& vec2 );
+
+  /**
+   * @brief Conversion constructor from Vector3.
+   *
+   * @since_tizen 2.4
+   * @param [in] vec3 to copy from, w is initialized to 0
+   */
+  explicit Vector4( const Vector3& vec3 );
+
+// Constants
+  static const Vector4 ONE;   ///< (1.0f,1.0f,1.0f,1.0f)
+  static const Vector4 XAXIS; ///< (1.0f,0.0f,0.0f,0.0f)
+  static const Vector4 YAXIS; ///< (0.0f,1.0f,0.0f,0.0f)
+  static const Vector4 ZAXIS; ///< (0.0f,0.0f,1.0f,0.0f)
+  static const Vector4 ZERO;  ///< (0.0f, 0.0f, 0.0f, 0.0f)
+
+// API
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param [in] array of floats
+   * @return itself
+   */
+  Vector4& operator=(const float* array)
+  {
+    x = array[0];
+    y = array[1];
+    z = array[2];
+    w = array[3];
+
+    return *this;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * Only sets x and y. z and w are left as they were
+   * @since_tizen 2.4
+   * @param [in] vec2 to assign from.
+   * @return itself
+   */
+  Vector4& operator=(const Vector2& vec2 );
+
+  /**
+   * @brief Assignment operator.
+   *
+   * Only sets x and y and z. w is left as it was
+   * @since_tizen 2.4
+   * @param [in] vec3 to assign from
+   * @return itself
+   */
+  Vector4& operator=(const Vector3& vec3 );
+
+  /**
+   * @brief Addition operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return A vector containing the result of the addition
+   */
+  Vector4 operator+(const Vector4 & rhs) const
+  {
+    Vector4 temp(*this);
+
+    return temp += rhs;
+  }
+
+  /**
+   * @brief Addition assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs vector to add.
+   * @return itself
+   */
+  Vector4& operator+=(const Vector4& rhs)
+  {
+    x += rhs.x;
+    y += rhs.y;
+    z += rhs.z;
+    w += rhs.w;
+
+    return *this;
+  }
+
+  /**
+   * @brief Subtraction operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs  the vector to subtract
+   * @return A vector containing the result of the subtraction
+   */
+  Vector4 operator-(const Vector4& rhs) const
+  {
+    Vector4 temp(*this);
+
+    temp-=rhs;
+
+    return temp;
+  }
+
+  /**
+   * @brief Subtraction assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to subtract
+   * @return itself
+   */
+  Vector4& operator-=(const Vector4& rhs)
+  {
+    x -= rhs.x;
+    y -= rhs.y;
+    z -= rhs.z;
+    w -= rhs.w;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return A vector containing the result of the multiplication
+   */
+  Vector4 operator*(const Vector4& rhs) const
+  {
+    Vector4 temp(*this);
+
+    return temp *= rhs;
+  }
+
+  /**
+   * @brief Multiplication operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return A vector containing the result of the scaling
+   */
+  Vector4 operator*(float rhs) const
+  {
+    return Vector4(x * rhs, y * rhs, z * rhs, w * rhs);
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to multiply
+   * @return itself
+   */
+  Vector4& operator*=(const Vector4& rhs)
+  {
+    x *= rhs.x;
+    y *= rhs.y;
+    z *= rhs.z;
+    w *= rhs.w;
+
+    return *this;
+  }
+
+  /**
+   * @brief Multiplication assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector
+   * @return itself
+   */
+  Vector4& operator*=(float rhs)
+  {
+    x *= rhs;
+    y *= rhs;
+    z *= rhs;
+    w *= rhs;
+
+    return *this;
+  }
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return A vector containing the result of the division
+   */
+  Vector4 operator/(const Vector4 & rhs) const
+  {
+    Vector4 temp(*this);
+
+    return temp /= rhs;
+  }
+
+  /**
+   * @brief Division operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The float value to scale the vector by
+   * @return A vector containing the result of the scaling
+   */
+  Vector4 operator/(float rhs) const
+  {
+    float oneOver = 1.0f / rhs;
+    return Vector4(x * oneOver, y * oneOver, z * oneOver, w * oneOver);
+  }
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the vector to divide
+   * @return itself
+   */
+  Vector4& operator/=(const Vector4& rhs)
+  {
+    x /= rhs.x;
+    y /= rhs.y;
+    z /= rhs.z;
+    w /= rhs.w;
+
+    return *this;
+  }
+
+  /**
+   * @brief Division assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs the float value to scale the vector by
+   * @return itself
+   */
+  Vector4& operator/=(float rhs)
+  {
+    const float oneOver = 1.0f / rhs;
+    x *= oneOver;
+    y *= oneOver;
+    z *= oneOver;
+    w *= oneOver;
+
+    return *this;
+  }
+
+  /**
+   * @brief Unary negation operator.
+   *
+   * @since_tizen 2.4
+   * @return the negative value
+   */
+  Vector4 operator-() const
+  {
+    Vector4 temp(-x, -y, -z, -w);
+
+    return temp;
+  }
+
+  /**
+   * @brief Equality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are equal
+   */
+  bool operator==(const Vector4 &rhs) const;
+
+  /**
+   * @brief Inequality operator.
+   *
+   * Utilises appropriate machine epsilon values.
+   *
+   * @since_tizen 2.4
+   * @param[in] rhs The vector to test against
+   * @return true if the vectors are not equal
+   */
+  bool operator!=(const Vector4 &rhs) const
+  {
+    return !(*this == rhs);
+  }
+
+  /**
+   * @brief Const array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0, 1, 2 or 3
+   * @since_tizen 2.4
+   * @param[in] index Subscript
+   * @return    The float at the given index
+   */
+  const float& operator[](const unsigned int index) const
+  {
+    DALI_ASSERT_ALWAYS( index < 4 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Mutable array subscript operator overload.
+   *
+   * Asserts if index is out of range. Should be 0, 1, 2 or 3
+   * @since_tizen 2.4
+   * @param[in] index Subscript index
+   * @return    The float at the given index
+   */
+  float& operator[](const unsigned int index)
+  {
+    DALI_ASSERT_ALWAYS( index < 4 && "Vector element index out of bounds" );
+
+    return AsFloat()[index];
+  }
+
+  /**
+   * @brief Returns the dot product of this vector (4d) and another vector (3d).
+   *
+   * The dot product is the length of one vector in the direction of another vector.
+   * This is great for lighting, threshold testing the angle between two unit vectors,
+   * calculating the distance between two points in a particular direction.
+   * @since_tizen 2.4
+   * @param [in] other     the other vector
+   * @return               the dot product
+   */
+  float Dot(const Vector3& other) const;
+
+  /**
+   * @brief Returns the dot product of this vector and another vector.
+   *
+   * The dot product is the length of one vector in the direction of another vector.
+   * This is great for lighting, threshold testing the angle between two unit vectors,
+   * calculating the distance between two points in a particular direction.
+   * @since_tizen 2.4
+   * @param [in] other     the other vector
+   * @return               the dot product
+   */
+  float Dot(const Vector4& other) const;
+
+  /**
+   * @brief Returns the 4d dot product of this vector and another vector.
+   *
+   * @since_tizen 2.4
+   * @param [in] other     the other vector
+   * @return          the dot product
+   */
+  float Dot4(const Vector4& other) const;
+
+  /**
+   * @brief Returns the cross produce of this vector and another vector.
+   *
+   * The cross produce of two vectors is a vector which is perpendicular to the plane of the
+   * two vectors. This is great for calculating normals and making matrices orthogonal.
+   *
+   * @since_tizen 2.4
+   * @param [in] other    the other vector
+   * @return A vector containing the cross product
+   */
+  Vector4 Cross(const Vector4& other) const;
+
+  /**
+   * @brief Returns the length of the vector.
+   *
+   * @since_tizen 2.4
+   * @return the length.
+   */
+  float Length() const;
+
+  /**
+   * @brief Returns the length of the vector squared.
+   *
+   * This is faster than using Length() when performing
+   * threshold checks as it avoids use of the square root.
+   * @since_tizen 2.4
+   * @return the length of the vector squared.
+   */
+  float LengthSquared() const;
+
+  /**
+   * @brief Normalizes the vector.
+   *
+   * Sets the vector to unit length whilst maintaining its direction.
+   * @since_tizen 2.4
+   */
+  void Normalize();
+
+  /**
+   * @brief Clamps the vector between minimum and maximum vectors.
+   *
+   * @since_tizen 2.4
+   * @param [in] min the minimum vector
+   * @param [in] max the maximum vector
+   */
+  void Clamp( const Vector4& min, const Vector4& max );
+
+  /**
+   * @brief Returns the contents of the vector as an array of 4 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or r, or s)
+   * 1: y (or g, or t)
+   * 2: z (or b, or p)
+   * 3: w (or a, or q)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 4 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  const float* AsFloat() const {return &x;}
+
+  /**
+   * @brief Returns the contents of the vector as an array of 4 floats.
+   *
+   * The order of the values in this array are as follows:
+   * 0: x (or r, or s)
+   * 1: y (or g, or t)
+   * 2: z (or b, or p)
+   * 3: w (or a, or q)
+   * @since_tizen 2.4
+   * @return the vector contents as an array of 4 floats.
+   * @note inlined for performance reasons (generates less code than a function call)
+   */
+  float* AsFloat() {return &x;}
+
+// Data
+
+  // NOTE
+  // xrs, ygt, zbp and waq must be consecutive in memory.
+  // No other data must be added before xrs member.
+  // No virtual methods must be added to this struct.
+
+  union
+  {
+    float x; ///< x component
+    float r; ///< red component
+    float s; ///< s component
+  };
+  union
+  {
+    float y; ///< y component
+    float g; ///< green component
+    float t; ///< t component
+  };
+  union
+  {
+    float z; ///< z component
+    float b; ///< blue component
+    float p; ///< p component
+  };
+  union
+  {
+    float w; ///< w component
+    float a; ///< alpha component
+    float q; ///< q component
+  };
+};
+
+/**
+ * @brief Print a Vector4.
+ *
+ * @since_tizen 2.4
+ * @param [in] o The output stream operator.
+ * @param [in] vector The vector to print.
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<<(std::ostream& o, const Vector4& vector);
+
+/**
+ * @brief Returns a vector with components set to the minimum of the corresponding component in a and b.
+ *
+ * If a=0,1,2,3 and b=4,0,1,2  returns a vector of 0,0,1,2
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the minimum of each component from a and b
+ */
+inline Vector4 Min( const Vector4& a, const Vector4& b )
+{
+  return Vector4( a.x < b.x ? a.x : b.x,
+                  a.y < b.y ? a.y : b.y,
+                  a.z < b.z ? a.z : b.z,
+                  a.w < b.w ? a.w : b.w );
+}
+
+/**
+ * @brief Returns a vector with components set to the maximum of the corresponding component in a and b.
+ *
+ * If a=0,1,2,3 and b=4,0,1,2  returns a vector of 4,1,2,3
+ * @since_tizen 2.4
+ * @param [in] a     a vector
+ * @param [in] b     a vector
+ * @return      a vector containing the maximum of each component from a and b
+ */
+inline Vector4 Max( const Vector4& a, const Vector4& b )
+{
+  return Vector4( a.x > b.x ? a.x : b.x,
+                  a.y > b.y ? a.y : b.y,
+                  a.z > b.z ? a.z : b.z,
+                  a.w > b.w ? a.w : b.w );
+}
+
+/**
+ * @brief Clamps each of vector v's components between minimum and maximum values.
+ *
+ * @since_tizen 2.4
+ * @param [in] v     a vector
+ * @param [in] min the minimum value
+ * @param [in] max the maximum value
+ * @return     a vector containing the clamped components of v
+ */
+DALI_IMPORT_API Vector4 Clamp( const Vector4& v, const float& min, const float& max );
+
+// Allow Vector4 to be treated as a POD type
+template <> struct TypeTraits< Vector4 > : public BasicTypes< Vector4 > { enum { IS_TRIVIAL_TYPE = true }; };
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_VECTOR_4_H__
diff --git a/dali/public-api/math/viewport.h b/dali/public-api/math/viewport.h
new file mode 100644 (file)
index 0000000..65eb2c7
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __DALI_VIEWPORT_H__
+#define __DALI_VIEWPORT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_math
+ * @{
+ */
+
+/**
+ * @brief Typedef for a viewport ( a rectangle representing a screen area ).
+ * @since_tizen 2.4
+ */
+typedef Rect<int> Viewport;
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_VIEWPORT_H__
diff --git a/dali/public-api/object/any.cpp b/dali/public-api/object/any.cpp
new file mode 100644 (file)
index 0000000..9930271
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/any.h>
+
+// EXTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+Any::Any()
+: mContainer( NULL )
+{
+}
+
+Any::~Any()
+{
+  // Call the implementation deletion function, which will invalidate mContainer
+
+  if ( NULL != mContainer )
+  {
+    mContainer->mDeleteFunc( mContainer );
+    mContainer = NULL;
+  }
+}
+
+Any& Any::operator=( const Any& any )
+{
+  if( &any != this )
+  {
+    if( NULL == any.mContainer )
+    {
+      delete mContainer;
+      mContainer = NULL;
+    }
+    else
+    {
+      AnyContainerBase* tmp = mContainer;
+
+      if( NULL != mContainer )
+      {
+        // Check if two Any types have the same type. Avoids assignments of values with different types.
+        if( mContainer->GetType() != any.GetType() )
+        {
+          AssertAlways( "Any::operator=( const Any& Any ). Trying to assign two values with different types." );
+        }
+      }
+
+      // Clone the correct templated object
+      mContainer = any.mContainer->mCloneFunc( *any.mContainer );
+
+      // Deletes previous container.
+      delete tmp;
+    }
+  }
+
+  return *this;
+}
+
+const std::type_info& Any::GetType() const
+{
+  return mContainer ? mContainer->GetType() : typeid( void );
+}
+
+void Any::AssertAlways( const char* assertMessage )
+{
+  DALI_LOG_ERROR_NOFN( assertMessage );
+  throw Dali::DaliException( assertMessage, "" );
+}
+
+
+} //namespace Dali
diff --git a/dali/public-api/object/any.h b/dali/public-api/object/any.h
new file mode 100644 (file)
index 0000000..474c63d
--- /dev/null
@@ -0,0 +1,498 @@
+#ifndef __DALI_ANY_TYPE_H__
+#define __DALI_ANY_TYPE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <typeinfo>   // operator typeid
+#include <cstddef>    // NULL
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief Stores a value of any type.
+ *
+ * Examples of use:
+ * \code{.cpp}
+ * Any uintVariable = 5u;
+ * Any floatVariable( 4.5f );
+ * Any strVariable( std::string( "Hello world" ) );
+ * uintVariable = 1u;
+ * unsigned int variable = AnyCast< unsigned int >( uintVariable );
+ * if ( typeid( int ) == uintVariable.GetType() )
+ * \endcode
+ * @since_tizen 2.4
+ */
+class Any
+{
+public:
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  DALI_IMPORT_API Any();
+
+  /**
+   * @brief Destructor. Free resources.
+   * @since_tizen 2.4
+   */
+  DALI_IMPORT_API ~Any();
+
+  /**
+   * @brief Pass Assert message
+   *
+   * @since_tizen 2.4
+   * @param assertMessage Assert message to report
+   */
+  DALI_IMPORT_API static void AssertAlways( const char* assertMessage );
+
+  /**
+   * @brief Constructs a Any type with the given value.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The given value.
+   */
+  template<typename Type>
+  Any( const Type& value )
+  : mContainer( new AnyContainerImpl<Type>( value ) )
+  {
+  }
+
+  /**
+   * @brief Copy Constructor.
+   * @since_tizen 2.4
+   * @param [in] any Any to be copied.
+   */
+  Any( const Any& any )
+  {
+    // If container isn't empty then copy the container?
+    if ( NULL != any.mContainer )
+    {
+      mContainer = any.mContainer->mCloneFunc( *any.mContainer );
+    }
+    else
+    {
+      // Otherwise mark new container as empty
+      mContainer = NULL;
+    }
+  }
+
+  /**
+   * @brief Assigns a given value to the Any type.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The given value.
+   * @note If the types are different, then the current container will be re-created.
+   *
+   */
+  template<typename Type>
+  Any& operator=( const Type& value )
+  {
+    // If the container is empty then assign the new value
+    if ( NULL == mContainer )
+    {
+      mContainer = new AnyContainerImpl< Type >( value );
+    }
+    else
+    {
+      // Check to see if this type is compatible with current container?
+      if ( mContainer->GetType() == typeid( Type ) )
+      {
+        // Same type so just set the new value
+        static_cast< AnyContainerImpl< Type >* >( mContainer )->SetValue( value );
+      }
+      else
+      {
+        // Incompatible types, so delete old container and assign a new one with this type and value
+        mContainer->mDeleteFunc( mContainer );
+        mContainer = new AnyContainerImpl< Type >( value );
+      }
+    }
+    return *this;
+  }
+
+  /**
+   * @brief Assignment operator.
+   *
+   * @since_tizen 2.4
+   * @param [in] any Any to be assigned which contains a value of identical type to current contents.
+   * @exception DaliException If parameter any is of a different type.
+   *
+   */
+  DALI_IMPORT_API Any& operator=( const Any& any );
+
+  /**
+   * @brief Get a value of type Type from container
+   *
+   * @since_tizen 2.4
+   * @param type destination of type Type to write to
+   */
+  template<typename Type>
+  void Get( Type& type ) const
+  {
+    type = Get<Type>();
+  }
+
+  /**
+   * @brief Returns the type info of the stored value.
+   *
+   * @since_tizen 2.4
+   * @return The std::type_info of the stored value or the type info of the void
+   * type if there is no value stored.
+   */
+  DALI_IMPORT_API const std::type_info& GetType() const;
+
+  /**
+   * @brief Retrieves the stored value in the Any type.
+   *
+   * @since_tizen 2.4
+   * @return The stored value.
+   */
+  template<typename Type>
+  const Type& Get() const
+  {
+
+    if ( NULL == mContainer )
+    {
+      AssertAlways( "Any::Get(). mContainer is NULL" );
+    }
+
+    // Check if the value has the same value than the Any type.
+    if( mContainer->GetType() != typeid( Type ) )
+    {
+      AssertAlways( "Any::Get(). Trying to retrieve a value of a different type than the template one." );
+    }
+    return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetValue();
+  }
+
+  /**
+   * @brief Return pointer of Type to the value stored
+   *
+   * @since_tizen 2.4
+   * @return pointer to the value or NULL if no value is contained
+   */
+  template<typename Type>
+  Type* GetPointer()
+  {
+    if( NULL == mContainer )
+    {
+      return NULL;
+    }
+     // Check if the value has the same value than the Any type.
+    if( mContainer->GetType() != typeid( Type ) )
+    {
+      AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
+    }
+    return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
+  }
+
+  /**
+   * @brief Return pointer of Type to the value stored
+   *
+   * @since_tizen 2.4
+   * @return pointer to the value or NULL if no value is contained
+   */
+  template<typename Type>
+  const Type* GetPointer() const
+  {
+    if( NULL == mContainer )
+    {
+      return NULL;
+    }
+     // Check if the value has the same value than the Any type.
+    if( mContainer->GetType() != typeid( Type ) )
+    {
+      AssertAlways( "Any::GetPointer(). Trying to retrieve a pointer to a value of a different type than the template one." );
+    }
+    return static_cast< AnyContainerImpl< Type >* >( mContainer )->GetPointerToValue();
+  }
+
+  /**
+   * @brief Returns whether container holds a value
+   *
+   * @since_tizen 2.4
+   * @return true if the container is empty, else false.
+   */
+  bool Empty() const
+  {
+    return ( NULL == mContainer ) ? true : false;
+  }
+
+  struct AnyContainerBase;    // Forward declaration for typedef
+  typedef AnyContainerBase* (*CloneFunc)( const AnyContainerBase& base );
+  typedef void (*DeleteFunc)( const AnyContainerBase* base );
+
+  /**
+   * @brief Base container to hold type for match verification and instance cloning function
+   *
+   * @since_tizen 2.4
+   */
+  struct AnyContainerBase
+  {
+    /**
+     * @brief Constructor of base container
+     *
+     * @since_tizen 2.4
+     * @param type typeid of container
+     * @param cloneFunc Cloning function to replicate this container type
+     * @param deleteFunc Deleting function to destroy this container type
+     */
+    AnyContainerBase( const std::type_info& type, CloneFunc cloneFunc, DeleteFunc deleteFunc )
+    : mType( type ),
+      mCloneFunc( cloneFunc ),
+      mDeleteFunc( deleteFunc )
+    {}
+
+    /**
+     * @brief Get the typeid of this container
+     *
+     * @since_tizen 2.4
+     * @return type
+     */
+    const std::type_info& GetType() const
+    {
+      return mType;
+    }
+
+    const::std::type_info& mType;       // typeID
+    CloneFunc mCloneFunc;               // cloning function for this container
+    DeleteFunc mDeleteFunc;             // deleting function for this container
+  };
+
+
+  /**
+   * @brief Templated Clone function from container base
+   *
+   * @since_tizen 2.4
+   * @param base reference to container
+   */
+  template<typename Type>
+  struct AnyContainerImplCloner
+  {
+    static AnyContainerBase* Clone( const AnyContainerBase& base )
+    {
+      return new AnyContainerImpl< Type >( static_cast< AnyContainerImpl< Type > >( base ) );
+    }
+  };
+
+  /**
+   * @brief Templated Delete function from container base
+   *
+   * @since_tizen 2.4
+   * @param base pointer to container
+   */
+  template<typename Type>
+  struct AnyContainerImplDelete
+  {
+    static void Delete( const AnyContainerBase* base )
+    {
+      delete ( static_cast< const AnyContainerImpl< Type >* > ( base ) );
+    }
+  };
+
+  /**
+   * @brief Templated class to hold value for type
+   *
+   * @since_tizen 2.4
+   */
+  template<typename Type>
+  class AnyContainerImpl : public AnyContainerBase
+  {
+  public:
+
+    /**
+     * @brief Constructor to create container holding value of type Type
+     *
+     * @since_tizen 2.4
+     * @param value Value of Type
+     */
+    AnyContainerImpl( const Type& value )
+    : AnyContainerBase( typeid( Type ),
+                        static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
+                        static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) ),
+                        mValue( value )
+    {}
+
+    /**
+     * @brief Constructor to create new container of type from and existing container (cloning)
+     *
+     * @since_tizen 2.4
+     * @param base reference to base container to copy from
+     */
+    AnyContainerImpl( const AnyContainerBase& base )
+    : AnyContainerBase( typeid( Type ),
+                        static_cast< CloneFunc >( &AnyContainerImplCloner< Type >::Clone ),
+                        static_cast< DeleteFunc >( &AnyContainerImplDelete< Type >::Delete ) )
+    {
+      mValue = static_cast< const AnyContainerImpl& >( base ).GetValue();
+    }
+
+    /**
+     * @brief Get the container's stored value
+     *
+     * @since_tizen 2.4
+     * @return value of type Type
+     */
+    const Type& GetValue() const
+    {
+      return mValue;
+    }
+
+    /**
+     * @brief Set the container's stored value
+     *
+     * @since_tizen 2.4
+     * @param value of type Type
+     */
+    void SetValue( const Type& value )
+    {
+      mValue = value;
+    }
+
+    /**
+     * @brief Get a pointer to the value held
+     *
+     * @since_tizen 2.4
+     * @return pointer to the value of type Type
+     */
+    Type* GetPointerToValue()
+    {
+      return static_cast< Type* >( &mValue );
+    }
+
+    /**
+     * @brief Get a pointer to the value held
+     *
+     * @since_tizen 2.4
+     * @return pointer to the value of type Type
+     */
+    const Type* GetPointerToValue() const
+    {
+      return static_cast< const Type* >( &mValue );
+    }
+
+    private:
+      Type mValue;
+  };
+
+  AnyContainerBase* mContainer;
+
+};
+
+/**
+ * AnyCast helper functions
+ */
+
+/**
+ * @brief Extract a pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
+ *
+ * @since_tizen 2.4
+ * @param any Pointer to an Any object
+ *
+ * @return Pointer to the Type held
+ */
+template<typename Type>
+inline Type* AnyCast( Any* any )
+{
+  return any->GetPointer<Type>();
+}
+
+/**
+ * @brief Extract a const pointer to the held type of an Any object from a pointer to that Any object (NULL if empty )
+ *
+ * @since_tizen 2.4
+ * @param any const Pointer to an Any object
+ *
+ * @return const Pointer to the Type held
+ */
+template<typename Type>
+inline const Type* AnyCast( const Any* any )
+{
+  return any->GetPointer<Type>();
+}
+
+/**
+ * @brief Extract a held value of type Type from an Any object from a reference to that Any object
+ *
+ * @since_tizen 2.4
+ * @param any reference to an Any object
+ *
+ * @return Type value of type Type
+ */
+template<typename Type>
+inline Type AnyCast( Any& any )
+{
+  return any.Get<Type>();
+}
+
+/**
+ * @brief Extract a held value of type Type from an Any object from a const reference to that Any object
+ *
+ * @since_tizen 2.4
+ * @param any reference to an Any object
+ *
+ * @return Type value of type Type
+ */
+template<typename Type>
+inline Type AnyCast( const Any& any )
+{
+  return any.Get<Type>();
+}
+
+/**
+ * @brief Extract a reference to the held value of type Type from an Any object from a reference to that Any object
+ *
+ * @since_tizen 2.4
+ * @param any reference to an Any object
+ *
+ * @return A reference to the Type value of type Type
+ */
+template<typename Type>
+inline Type& AnyCastReference( Any& any )
+{
+  return any.Get<Type>();
+}
+
+/**
+ * @brief Extract a const reference to the held value of type Type from an Any object from a const reference to that Any object
+ *
+ * @since_tizen 2.4
+ * @param any reference to an Any object
+ *
+ * @return A const reference to the Type value of type Type
+ */
+template<typename Type>
+inline const Type& AnyCastReference( const Any& any )
+{
+  return any.Get<Type>();
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_ANY_TYPE_H__
diff --git a/dali/public-api/object/base-handle.cpp b/dali/public-api/object/base-handle.cpp
new file mode 100644 (file)
index 0000000..24085ea
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <typeinfo>
+
+// CLASS HEADER
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/type-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+BaseHandle::BaseHandle(Dali::BaseObject* handle)
+: mObjectHandle(handle)
+{
+}
+
+BaseHandle::BaseHandle()
+{
+}
+
+BaseHandle::~BaseHandle()
+{
+}
+
+BaseHandle::BaseHandle(const BaseHandle& handle)
+  : mObjectHandle(handle.mObjectHandle)
+{
+}
+
+BaseHandle& BaseHandle::operator=(const BaseHandle& rhs)
+{
+  if( this != &rhs )
+  {
+    this->mObjectHandle = rhs.mObjectHandle;
+  }
+
+  return *this;
+}
+
+bool BaseHandle::DoAction(const std::string& command, const Property::Map& attributes)
+{
+  return GetImplementation(*this).DoAction( command, attributes );
+}
+
+const std::string& BaseHandle::GetTypeName() const
+{
+  return GetImplementation(*this).GetTypeName();
+}
+
+bool BaseHandle::GetTypeInfo(Dali::TypeInfo& typeInfo) const
+{
+  return GetImplementation(*this).GetTypeInfo(typeInfo);
+}
+
+BaseObject& BaseHandle::GetBaseObject()
+{
+  return static_cast<BaseObject&>(*mObjectHandle);
+}
+
+const BaseObject& BaseHandle::GetBaseObject() const
+{
+  return static_cast<const BaseObject&>(*mObjectHandle);
+}
+
+void BaseHandle::Reset()
+{
+  mObjectHandle = NULL;
+}
+
+BaseHandle::operator BaseHandle::BooleanType() const
+{
+  return mObjectHandle ? &BaseHandle::ThisIsSaferThanReturningVoidStar : NULL;
+}
+
+bool BaseHandle::operator==(const BaseHandle& rhs) const
+{
+  return this->mObjectHandle == rhs.mObjectHandle;
+}
+
+bool BaseHandle::operator!=(const BaseHandle& rhs) const
+{
+  return this->mObjectHandle != rhs.mObjectHandle;
+}
+
+Dali::RefObject* BaseHandle::GetObjectPtr() const
+{
+  return mObjectHandle.Get();
+}
+
+bool BaseHandle::DoConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  return GetImplementation(*this).DoConnectSignal( connectionTracker, signalName, functor );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/base-handle.h b/dali/public-api/object/base-handle.h
new file mode 100644 (file)
index 0000000..3f5ffd8
--- /dev/null
@@ -0,0 +1,313 @@
+#ifndef __DALI_BASE_HANDLE_H__
+#define __DALI_BASE_HANDLE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/signals/functor-delegate.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class BaseObject;
+class ConnectionTrackerInterface;
+class TypeInfo;
+
+/**
+ * @brief Dali::BaseHandle is a handle to an internal Dali resource.
+ *
+ * Each Dali handle consists of a single private pointer, and a set of non-virtual forwarding functions.
+ * This hides the internal implementation, so it may be modified without affecting the public interface.
+ *
+ * Dali handles have implicit smart-pointer semantics.
+ * This avoids the need to match resource allocation methods like new/delete (the RAII idiom).
+ *
+ * Dali handles can be copied by value.
+ * When a Dali handle is copied, both the copy and original will point to the same Dali resource.
+ *
+ * The internal Dali resources are reference counted. copying a Dali handle will increase the reference count.
+ * A resource will not be deleted until all its Dali::BaseHandle handles are destroyed, or reset.
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API BaseHandle
+{
+public:
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A pointer to a newly allocated Dali resource
+   */
+  BaseHandle(Dali::BaseObject* handle);
+
+  /**
+   * @brief This constructor provides an uninitialized Dali::BaseHandle.
+   *
+   * This should be initialized with a Dali New() method before use.
+   * Methods called on an uninitialized Dali::BaseHandle will assert.
+   * @code
+   * BaseHandle handle; // uninitialized
+   * handle.SomeMethod(); // unsafe! This will assert
+   *
+   * handle = SomeClass::New(); // now initialized
+   * handle.SomeMethod(); // safe
+   * @endcode
+   * @since_tizen 2.4
+   */
+  BaseHandle();
+
+  /**
+   * @brief Dali::BaseHandle is intended as a base class
+   *
+   * This is non-virtual since derived BaseHandle types must not contain data.
+   * @since_tizen 2.4
+   */
+  ~BaseHandle();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  BaseHandle(const BaseHandle& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * It makes this handle use the same BaseObject as the copied handle
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this handle
+   */
+  BaseHandle& operator=(const BaseHandle& rhs);
+
+  /**
+   * @brief Connects a void() functor to a specified signal.
+   *
+   * @since_tizen 2.4
+   * @param [in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param [in] signalName Name of the signal to connect to.
+   * @param [in] functor The functor to copy.
+   * @return True if the signal was available.
+   * @pre The signal must be available in this object.
+   */
+  template <class T>
+  bool ConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, const T& functor )
+  {
+    return DoConnectSignal( connectionTracker, signalName, FunctorDelegate::New( functor ) );
+  }
+
+  /**
+   * @brief Perform action on this object with the given action name and attributes.
+   *
+   * @since_tizen 2.4
+   * @param [in] actionName The command for the action.
+   * @param [in] attributes The list of attributes for the action.
+   * @return The action is performed by the object or not.
+   */
+  bool DoAction(const std::string& actionName, const Property::Map& attributes);
+
+  /**
+   * @brief Returns the type name for the Handle.
+   *
+   * Will return an empty string if the typename does not exist. This will happen for types that
+   * have not registered with type-registry.
+   *
+   * @since_tizen 2.4
+   * @return The type name. Empty string if the typename does not exist.
+   */
+  const std::string& GetTypeName() const;
+
+  /**
+   * @brief Returns the type info for the Handle.
+   *
+   * @since_tizen 2.4
+   * @return The type info.
+   */
+  bool GetTypeInfo(Dali::TypeInfo& info) const;
+
+public:
+
+  // BaseHandle accessors
+
+  /**
+   * @brief Retrieve the internal Dali resource.
+   *
+   * This is useful for checking the reference count of the internal resource.
+   * This method will not check the validity of the handle so the caller is expected to check it by using if (handle)
+   * @since_tizen 2.4
+   * @return The BaseObject which is referenced by the BaseHandle.
+   */
+  BaseObject& GetBaseObject();
+
+  /**
+   * @brief Retrieve the internal Dali resource.
+   *
+   * This is useful for checking the reference count of the internal resource.
+   * This method will not check the validity of the handle so the caller is expected to check it by using if (handle)
+   * @since_tizen 2.4
+   * @return The BaseObject which is referenced by the BaseHandle.
+   */
+  const BaseObject& GetBaseObject() const;
+
+  /**
+   * @brief Resets the handle.
+   *
+   * If no other handle copies exist, the internal Dali resouce will be deleted.
+   * Calling this is not required i.e. it will happen automatically when a Dali::BaseHandle is destroyed.
+   * @since_tizen 2.4
+   */
+  void Reset();
+
+  // BaseHandle comparisons - This is a variation of the safe bool idiom
+
+  /**
+   * @brief Pointer-to-member type.
+   * Objects can be implicitly converted to this for validity checks.
+   */
+  typedef void (BaseHandle::*BooleanType)() const;
+
+  /**
+   * @brief Converts an handle to a BooleanType.
+   *
+   * This is useful for checking whether the handle is empty.
+   * @since_tizen 2.4
+   */
+  operator BooleanType() const;
+
+  /**
+   * @brief Equality operator overload.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs A reference to the compared handle.
+   * @return true if the handle handles point to the same Dali resource, or if both are NULL.
+   */
+  bool operator==(const BaseHandle& rhs) const;
+
+  /**
+   * @brief Inequality operator overload.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs A reference to the compared handle.
+   * @return true if the handle handles point to the different Dali resources.
+   */
+  bool operator!=(const BaseHandle& rhs) const;
+
+  /**
+   * @brief Get the reference counted object pointer.
+   *
+   * @since_tizen 2.4
+   * @return A pointer to the reference counted object.
+   */
+  Dali::RefObject* GetObjectPtr() const;
+
+private:
+
+  /**
+   * @brief Not intended for application developers.
+   *
+   * @since_tizen 2.4
+   * @param [in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param [in] signalName Name of the signal to connect to.
+   * @param [in] functorDelegate A newly allocatated functor delegate (takes ownership).
+   * @return True if the signal was available.
+   */
+  bool DoConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functorDelegate );
+
+protected:
+
+  /**
+   * @brief Used by the safe bool idiom.
+   *
+   * @since_tizen 2.4
+   */
+  void ThisIsSaferThanReturningVoidStar() const {}
+
+private:
+
+  IntrusivePtr<Dali::RefObject> mObjectHandle; ///< Object this handle points at.
+
+};
+
+/**
+ * @brief Template wrapper to downcast an base object handle to derived class handle.
+ *
+ * @since_tizen 2.4
+ * @param handle to a base object
+ * @return handle pointer to either a valid deriving handle or an uninitialized handle
+ * @pre The BaseHandle has been initialized.
+ */
+template< class T >
+inline T DownCast( BaseHandle handle )
+{
+  return T::DownCast( handle );
+}
+
+// See also BaseHandle::BooleanType() conversion
+
+/**
+ * @brief Equality operator
+ * @since_tizen 2.4
+ */
+template <typename T>
+inline bool operator==(const BaseHandle& lhs, const T& rhs)
+{
+  // We depart from the safe bool idiom to allow Dali::BaseHandle derived classes to be compared
+  return lhs == static_cast<const BaseHandle&>(rhs);
+}
+
+/**
+ * @brief Equality operator
+ * @since_tizen 2.4
+ */
+template <typename T>
+inline bool operator!=(const BaseHandle& lhs, const T& rhs)
+{
+  // We depart from the safe bool idiom to allow Dali::BaseHandle derived classes to be compared
+  return lhs != static_cast<const BaseHandle&>(rhs);
+}
+
+/**
+ * @brief Less than operator
+ * @since_tizen 2.4
+ */
+inline bool operator<(const BaseHandle& lhs, const BaseHandle& rhs)
+{
+  return lhs.GetObjectPtr() < rhs.GetObjectPtr();
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_BASE_HANDLE_H__
diff --git a/dali/public-api/object/base-object.cpp b/dali/public-api/object/base-object.cpp
new file mode 100644 (file)
index 0000000..a464952
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/base-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/type-registry.h>
+#include <dali/integration-api/debug.h>
+#include <dali/internal/event/common/object-registry-impl.h>
+#include <dali/internal/event/common/stage-impl.h>
+#include <dali/internal/event/common/type-registry-impl.h>
+
+namespace Dali
+{
+
+BaseObject::BaseObject()
+{
+}
+
+BaseObject::~BaseObject()
+{
+}
+
+void BaseObject::RegisterObject()
+{
+  Internal::Stage* stage = Internal::Stage::GetCurrent();
+  if( stage )
+  {
+    stage->RegisterObject( this );
+  }
+}
+
+void BaseObject::UnregisterObject()
+{
+  // Guard to allow handle destruction after Core has been destroyed
+  Internal::Stage* stage = Internal::Stage::GetCurrent();
+  if( stage )
+  {
+    stage->UnregisterObject( this );
+  }
+}
+
+bool BaseObject::DoAction(const std::string& actionName, const Property::Map& attributes)
+{
+  Dali::Internal::TypeRegistry* registry = Dali::Internal::TypeRegistry::Get();
+
+  if( registry )
+  {
+    return registry->DoActionTo(this, actionName, attributes);
+  }
+
+  return false;
+}
+
+const std::string& BaseObject::GetTypeName() const
+{
+  Dali::Internal::TypeRegistry* registry = Dali::Internal::TypeRegistry::Get();
+
+  if( registry )
+  {
+    Dali::TypeInfo typeInfo = registry->GetTypeInfo(this);
+    if( typeInfo )
+    {
+      return typeInfo.GetName();
+    }
+  }
+
+  // Return an empty string if type-name not found.
+  DALI_LOG_WARNING( "TypeName Not Found\n" );
+  static std::string empty;
+  return empty;
+}
+
+bool BaseObject::GetTypeInfo(Dali::TypeInfo& typeInfo) const
+{
+  Dali::Internal::TypeRegistry* registry = Dali::Internal::TypeRegistry::Get();
+
+  Dali::TypeInfo info = registry->GetTypeInfo(this);
+  if(info)
+  {
+    typeInfo = info;
+    return true;
+  }
+  else
+  {
+    return false;
+  }
+}
+
+bool BaseObject::DoConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functor )
+{
+  Dali::Internal::TypeRegistry* registry = Dali::Internal::TypeRegistry::Get();
+
+  if( registry )
+  {
+    return registry->ConnectSignal( this, connectionTracker, signalName, functor );
+  }
+
+  return false;
+}
+
+} // namespace Dali
+
diff --git a/dali/public-api/object/base-object.h b/dali/public-api/object/base-object.h
new file mode 100644 (file)
index 0000000..da02f79
--- /dev/null
@@ -0,0 +1,152 @@
+#ifndef __DALI_BASE_OBJECT_H__
+#define __DALI_BASE_OBJECT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/ref-object.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/signals/functor-delegate.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class BaseHandle;
+
+/**
+ * @brief A base class for objects.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API BaseObject : public Dali::RefObject
+{
+public:
+
+  /**
+   * @brief Connects a void() functor to a specified signal.
+   *
+   * @since_tizen 2.4
+   * @param [in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param [in] signalName Name of the signal to connect to.
+   * @param [in] functor The functor to copy.
+   * @return True if the signal was available.
+   * @pre The signal must be available in this object.
+   */
+  template <class T>
+  bool ConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, const T& functor )
+  {
+    return DoConnectSignal( connectionTracker, signalName, FunctorDelegate::New( functor ) );
+  }
+
+  /**
+   * @copydoc Dali::BaseHandle::DoAction
+   */
+  bool DoAction(const std::string& actionName, const Property::Map& attributes);
+
+  /**
+   * @copydoc Dali::BaseHandle::GetTypeName
+   */
+  const std::string& GetTypeName() const;
+
+  /**
+   * @copydoc Dali::BaseHandle::GetTypeInfo
+   */
+  bool GetTypeInfo(Dali::TypeInfo& info) const;
+
+public: // Not intended for application developers
+
+  /**
+   * @copydoc Dali::BaseHandle::DoConnectSignal
+   */
+  bool DoConnectSignal( ConnectionTrackerInterface* connectionTracker, const std::string& signalName, FunctorDelegate* functorDelegate );
+
+protected:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  BaseObject();
+
+  /**
+   * @brief A reference counted object may only be deleted by calling Unreference().
+   * @since_tizen 2.4
+   */
+  virtual ~BaseObject();
+
+  /**
+   * @brief Registers the object as created with the Object registry.
+   * @since_tizen 2.4
+   */
+  void RegisterObject();
+
+  /**
+   * @brief Unregisters the object from Object registry.
+   * @since_tizen 2.4
+   */
+  void UnregisterObject();
+
+private:
+
+  // Not implemented
+  DALI_INTERNAL BaseObject(const BaseObject& rhs);
+
+  // Not implemented
+  DALI_INTERNAL BaseObject& operator=(const BaseObject& rhs);
+};
+
+// Helpers for public-api forwarding methods
+
+/**
+ * @brief Get the implementation of a handle.
+ *
+ * @since_tizen 2.4
+ * @param[in] handle The handle
+ * @return A reference to the object the handle points at.
+ */
+inline BaseObject& GetImplementation(Dali::BaseHandle& handle)
+{
+  DALI_ASSERT_ALWAYS( handle && "BaseObject handle is empty" );
+
+  return handle.GetBaseObject();
+}
+
+/**
+ * @brief Get the implementation of a handle.
+ *
+ * @since_tizen 2.4
+ * @param[in] handle The handle
+ * @return A reference to the object the handle points at.
+ */
+inline const BaseObject& GetImplementation(const Dali::BaseHandle& handle)
+{
+  DALI_ASSERT_ALWAYS( handle && "BaseObject handle is empty" );
+
+  return handle.GetBaseObject();
+}
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+# endif // __DALI_BASE_OBJECT_H__
diff --git a/dali/public-api/object/handle.cpp b/dali/public-api/object/handle.cpp
new file mode 100644 (file)
index 0000000..80da558
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/handle.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/object/property-conditions.h>
+#include <dali/public-api/object/property-notification.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/internal/event/common/object-impl.h>
+#include <dali/internal/event/object/custom-object-internal.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+Handle::Handle( Dali::Internal::Object* handle )
+: BaseHandle(handle)
+{
+}
+
+
+Handle::Handle()
+{
+}
+
+Handle Handle::New()
+{
+  return Handle( Internal::CustomObject::New() );
+}
+
+Handle::~Handle()
+{
+}
+
+Handle::Handle( const Handle& handle )
+: BaseHandle( handle )
+{
+}
+
+Handle& Handle::operator=( const Handle& rhs )
+{
+  if( this != &rhs )
+  {
+    BaseHandle::operator=(rhs);
+  }
+
+  return *this;
+}
+
+Handle Handle::DownCast( BaseHandle handle )
+{
+  return Handle( dynamic_cast<Dali::Internal::Object*>(handle.GetObjectPtr()) );
+}
+
+
+bool Handle::Supports( Capability capability ) const
+{
+  return GetImplementation(*this).Supports( capability );
+}
+
+unsigned int Handle::GetPropertyCount() const
+{
+  return GetImplementation(*this).GetPropertyCount();
+}
+
+std::string Handle::GetPropertyName( Property::Index index ) const
+{
+  return GetImplementation(*this).GetPropertyName( index );
+}
+
+Property::Index Handle::GetPropertyIndex( const std::string& name ) const
+{
+  return GetImplementation(*this).GetPropertyIndex( name );
+}
+
+bool Handle::IsPropertyWritable( Property::Index index ) const
+{
+  return GetImplementation(*this).IsPropertyWritable( index );
+}
+
+bool Handle::IsPropertyAnimatable( Property::Index index ) const
+{
+  return GetImplementation(*this).IsPropertyAnimatable( index );
+}
+
+bool Handle::IsPropertyAConstraintInput( Property::Index index ) const
+{
+  return GetImplementation(*this).IsPropertyAConstraintInput( index );
+}
+
+Property::Type Handle::GetPropertyType( Property::Index index ) const
+{
+  return GetImplementation(*this).GetPropertyType( index );
+}
+
+void Handle::SetProperty( Property::Index index, const Property::Value& propertyValue )
+{
+  GetImplementation(*this).SetProperty( index, propertyValue );
+}
+
+Property::Index Handle::RegisterProperty( const std::string& name, const Property::Value& propertyValue )
+{
+  return GetImplementation(*this).RegisterProperty( name, propertyValue );
+}
+
+Property::Index Handle::RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode )
+{
+  return GetImplementation(*this).RegisterProperty( name, propertyValue, accessMode );
+}
+
+Property::Value Handle::GetProperty( Property::Index index ) const
+{
+  return GetImplementation(*this).GetProperty( index );
+}
+
+void Handle::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+  GetImplementation(*this).GetPropertyIndices( indices );
+}
+
+Dali::PropertyNotification Handle::AddPropertyNotification( Property::Index index,
+                                                            const PropertyCondition& condition )
+{
+  return GetImplementation(*this).AddPropertyNotification( index, -1, condition );
+}
+
+Dali::PropertyNotification Handle::AddPropertyNotification( Property::Index index,
+                                                            int componentIndex,
+                                                            const PropertyCondition& condition )
+{
+  return GetImplementation(*this).AddPropertyNotification( index, componentIndex, condition );
+}
+
+void Handle::RemovePropertyNotification( Dali::PropertyNotification propertyNotification )
+{
+  GetImplementation(*this).RemovePropertyNotification( propertyNotification );
+}
+
+void Handle::RemovePropertyNotifications()
+{
+  GetImplementation(*this).RemovePropertyNotifications();
+}
+
+void Handle::RemoveConstraints()
+{
+  GetImplementation(*this).RemoveConstraints();
+}
+
+void Handle::RemoveConstraints( unsigned int tag )
+{
+  GetImplementation(*this).RemoveConstraints( tag );
+}
+
+namespace WeightObject
+{
+
+const Property::Index WEIGHT = PROPERTY_CUSTOM_START_INDEX;
+
+Handle New()
+{
+  Handle handle = Handle::New();
+
+  handle.RegisterProperty( "weight", 0.0f );
+
+  return handle;
+}
+
+} // namespace WeightObject
+
+} // namespace Dali
diff --git a/dali/public-api/object/handle.h b/dali/public-api/object/handle.h
new file mode 100644 (file)
index 0000000..8e793ad
--- /dev/null
@@ -0,0 +1,390 @@
+#ifndef __DALI_HANDLE_H__
+#define __DALI_HANDLE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property-notification-declarations.h>
+#include <dali/public-api/object/ref-object.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class Constraint;
+class PropertyNotification;
+class PropertyCondition;
+
+namespace Internal DALI_INTERNAL
+{
+class Object;
+}
+
+/**
+ * @brief Dali::Handle is a handle to an internal property owning Dali object that can have constraints applied to it.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Handle : public BaseHandle
+{
+public:
+
+  /**
+   * @brief An Handle's capabilities can be queried using Handle::Supports()
+   * @since_tizen 2.4
+   */
+  enum Capability
+  {
+    /**
+     * @brief Some objects support dynamic property creation at run-time.
+     *
+     * New properties are registered by calling RegisterProperty() with an unused property name.
+     */
+    DYNAMIC_PROPERTIES = 0x01,
+  };
+
+public:
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A pointer to a newly allocated Dali resource
+   */
+  Handle( Dali::Internal::Object* handle );
+
+  /**
+   * @brief This constructor provides an uninitialized Dali::Handle.
+   *
+   * This should be initialized with a Dali New() method before use.
+   * Methods called on an uninitialized Dali::Handle will assert.
+   * @code
+   * Handle handle; // uninitialized
+   * handle.SomeMethod(); // unsafe! This will assert
+   *
+   * handle = SomeClass::New(); // now initialized
+   * handle.SomeMethod(); // safe
+   * @endcode
+   * @since_tizen 2.4
+   */
+  Handle();
+
+  /**
+   * @brief Create a new object.
+   *
+   * @since_tizen 2.4
+   * @return A handle to a newly allocated object.
+   */
+  static Handle New();
+
+  /**
+   * @brief Dali::Handle is intended as a base class
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~Handle();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  Handle( const Handle& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  Handle& operator=( const Handle& rhs );
+
+  /**
+   * @brief Downcast to a handle.
+   *
+   * If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle or an uninitialized handle
+   */
+  static Handle DownCast( BaseHandle handle );
+
+  /**
+   * @brief Query whether an handle supports a given capability.
+   *
+   * @since_tizen 2.4
+   * @param[in] capability The queried capability.
+   * @return True if the capability is supported.
+   */
+  bool Supports( Capability capability ) const;
+
+  // Properties
+
+  /**
+   * @brief Query how many properties are provided by an handle.
+   *
+   * This may vary between instances of a class, if dynamic properties are supported.
+   * @since_tizen 2.4
+   * @return The number of properties.
+   */
+  unsigned int GetPropertyCount() const;
+
+  /**
+   * @brief Query the name of a property.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return The name of the property.
+   */
+  std::string GetPropertyName( Property::Index index ) const;
+
+  /**
+   * @brief Query the index of a property.
+   * Returns the first property index that matches the given name exactly.
+   *
+   * @since_tizen 2.4
+   * @param [in] name The name of the property.
+   * @return The index of the property, or Property::INVALID_INDEX if no property exists with the given name.
+   */
+  Property::Index GetPropertyIndex( const std::string& name ) const;
+
+  /**
+   * @brief Query whether a property can be set using SetProperty().
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return True if the property is writable.
+   * @pre Property::INVALID_INDEX < index.
+   */
+  bool IsPropertyWritable( Property::Index index ) const;
+
+  /**
+   * @brief Query whether a writable property can be the target of an animation or constraint.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return True if the property is animatable.
+   */
+  bool IsPropertyAnimatable( Property::Index index ) const;
+
+  /**
+   * @brief Query whether a property can be used as in input to a constraint.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return True if the property can be used as a constraint input.
+   */
+  bool IsPropertyAConstraintInput( Property::Index index ) const;
+
+  /**
+   * @brief Query the type of a property.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return The type of the property.
+   */
+  Property::Type GetPropertyType( Property::Index index ) const;
+
+  /**
+   * @brief Set the value of an existing property.
+   *
+   * Property should be write-able. Setting a read-only property is a no-op.
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @param [in] propertyValue The new value of the property.
+   * @pre The property types match i.e. propertyValue.GetType() is equal to GetPropertyType(index).
+   */
+  void SetProperty( Property::Index index, const Property::Value& propertyValue );
+
+  /**
+   * @brief Register a new animatable property.
+   *
+   * @since_tizen 2.4
+   * @param [in] name The name of the property.
+   * @param [in] propertyValue The new value of the property.
+   * @return The index of the property or Property::INVALID_INDEX if registration failed
+   * @pre The object supports dynamic properties i.e. Supports(Handle::DYNAMIC_PROPERTIES) returns true.
+   * Property names are expected to be unique, but this is not enforced.
+   * Property indices are unique to each registered custom property in a given object.
+   * returns Property::INVALID_INDEX if registration failed. This can happen if you try to register
+   * animatable property on an object that does not have scene graph object.
+   * @note Only the following types can be animated:
+   *       - Property::BOOLEAN
+   *       - Property::FLOAT
+   *       - Property::INTEGER
+   *       - Property::VECTOR2
+   *       - Property::VECTOR3
+   *       - Property::VECTOR4
+   *       - Property::MATRIX3
+   *       - Property::MATRIX
+   *       - Property::ROTATION
+   */
+  Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue );
+
+  /**
+   * @brief Register a new property.
+   *
+   * Properties can be set as non animatable using property attributes.
+   * @since_tizen 2.4
+   * @param [in] name The name of the property.
+   * @param [in] propertyValue The new value of the property.
+   * @param [in] accessMode The property access mode (writable, animatable etc).
+   * @return The index of the property
+   * @pre The handle supports dynamic properties i.e. Supports(Handle::DYNAMIC_PROPERTIES) returns true.
+   * @pre name is unused i.e. GetPropertyIndex(name) returns PropertyIndex::INVALID.
+   * @note Only the following types can be animated:
+   *       - Property::BOOLEAN
+   *       - Property::FLOAT
+   *       - Property::INTEGER
+   *       - Property::VECTOR2
+   *       - Property::VECTOR3
+   *       - Property::VECTOR4
+   *       - Property::MATRIX3
+   *       - Property::MATRIX
+   *       - Property::ROTATION
+   */
+  Property::Index RegisterProperty( const std::string& name, const Property::Value& propertyValue, Property::AccessMode accessMode );
+
+  /**
+   * @brief Retrieve a property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return The property value.
+   */
+  Property::Value GetProperty( Property::Index index ) const;
+
+  /**
+   * @brief Convenience function for obtaining a property of a known type.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @return The property value.
+   * @pre The property types match i.e. PropertyTypes::Get<T>() is equal to GetPropertyType(index).
+   */
+  template <typename T>
+  T GetProperty( Property::Index index ) const
+  {
+    Property::Value value = GetProperty(index);
+
+    return T( value.Get<T>() );
+  }
+
+  /**
+   * @brief Retrieve all the property indices for this object (including custom properties).
+   *
+   * @since_tizen 2.4
+   * @param[out] indices A container of property indices for this object.
+   * @note the added container is cleared
+   */
+  void GetPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @brief Add a property notification to this object.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @param [in] condition The notification will be triggered when this condition is satisfied.
+   *
+   * @return A handle to the newly created PropertyNotification
+   */
+  PropertyNotification AddPropertyNotification( Property::Index index,
+                                                const PropertyCondition& condition );
+
+  /**
+   * @brief Add a property notification to this object.
+   *
+   * @since_tizen 2.4
+   * @param [in] index The index of the property.
+   * @param [in] componentIndex Index to the component of a complex property such as a Vector
+   * @param [in] condition The notification will be triggered when this condition is satisfied.
+   *
+   * @return A handle to the newly created PropertyNotification
+   */
+  PropertyNotification AddPropertyNotification( Property::Index index,
+                                                int componentIndex,
+                                                const PropertyCondition& condition );
+
+  /**
+   * @brief Remove a property notification from this object.
+   *
+   * @since_tizen 2.4
+   * @param [in] propertyNotification The propertyNotification to be removed.
+   */
+  void RemovePropertyNotification( Dali::PropertyNotification propertyNotification );
+
+  /**
+   * @brief Remove all property notifications from this object.
+   * @since_tizen 2.4
+   */
+  void RemovePropertyNotifications();
+
+  // Constraints
+
+  /**
+   * @brief Remove all constraints from an Object.
+   *
+   * @since_tizen 2.4
+   * @pre The object has been initialized.
+   */
+  void RemoveConstraints();
+
+  /**
+   * @brief Remove all the constraint from the Object with a matching tag.
+   *
+   * @since_tizen 2.4
+   * @param[in] tag The tag of the constraints which will be removed
+   * @pre The Object has been initialized.
+   */
+  void RemoveConstraints( unsigned int tag );
+
+};
+
+namespace WeightObject
+{
+
+DALI_IMPORT_API extern const Property::Index WEIGHT; ///< name "weight", type FLOAT
+
+/**
+ * @brief Convenience function to create an object with a custom "weight" property.
+ *
+ * @since_tizen 2.4
+ * @return A handle to a newly allocated object.
+ */
+DALI_IMPORT_API Handle New();
+
+} // namespace WeightObject
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_HANDLE_H__
diff --git a/dali/public-api/object/object-registry.cpp b/dali/public-api/object/object-registry.cpp
new file mode 100644 (file)
index 0000000..aea7a2a
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/object-registry.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/object-registry-impl.h>
+
+namespace Dali
+{
+
+ObjectRegistry::ObjectRegistry()
+{
+}
+
+ObjectRegistry::~ObjectRegistry()
+{
+}
+
+ObjectRegistry::ObjectRegistry(const ObjectRegistry& copy)
+: BaseHandle(copy)
+{
+}
+
+ObjectRegistry& ObjectRegistry::operator=(const ObjectRegistry& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+ObjectRegistry::ObjectCreatedSignalType& ObjectRegistry::ObjectCreatedSignal()
+{
+  return GetImplementation(*this).ObjectCreatedSignal();
+}
+
+ObjectRegistry::ObjectDestroyedSignalType& ObjectRegistry::ObjectDestroyedSignal()
+{
+  return GetImplementation(*this).ObjectDestroyedSignal();
+}
+
+ObjectRegistry::ObjectRegistry(Internal::ObjectRegistry* internal)
+: BaseHandle(internal)
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/object-registry.h b/dali/public-api/object/object-registry.h
new file mode 100644 (file)
index 0000000..8f1a0d7
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef __DALI_OBJECT_REGISTRY_H__
+#define __DALI_OBJECT_REGISTRY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class ObjectRegistry;
+}
+
+/**
+ * @brief The ObjectRegistry notifies it's observers when an object is created.
+ *
+ * Handle to the created Object is passed in the call back function.
+ * The Handle is passed as Dali::Object handle, which can be DownCast
+ * to the appropriate type.
+ *
+ * Care should be taken to not store the handle in the Observer, as this will
+ * have adverse effect on the life time of the Internal Object. The Handle
+ * should only be used to connect to signals
+ *
+ * Usage:
+ * ObjectRegistry registry = Stage::GetObjectRegistry();
+ * registry.ObjectCreatedSignal().Connect( ObjectCreatedCallbackFunc );
+ *
+ * Signals
+ * | %Signal Name     | Method                       |
+ * |------------------|------------------------------|
+ * | object-created   | @ref ObjectCreatedSignal()   |
+ * | object-destroyed | @ref ObjectDestroyedSignal() |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ObjectRegistry : public BaseHandle
+{
+public:
+
+  // Typedefs
+
+  /**
+   * @brief Object created signal
+   * @since_tizen 2.4
+   */
+  typedef Signal< void ( BaseHandle ) > ObjectCreatedSignalType;
+
+  /**
+   * @brief Object destroyed signal
+   * @since_tizen 2.4
+   */
+  typedef Signal< void ( const Dali::RefObject* ) > ObjectDestroyedSignalType;
+
+  /**
+   * @brief Allows the creation of an empty objectRegistry handle.
+   *
+   * To retrieve the current objectRegistry,
+   * this handle can be set using Stage::GetCurrent().GetObjectRegistry().
+   * @since_tizen 2.4
+   */
+  ObjectRegistry();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~ObjectRegistry();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  ObjectRegistry(const ObjectRegistry& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  ObjectRegistry& operator=(const ObjectRegistry& rhs);
+
+public: // Signals
+
+  /**
+   * @brief This signal is emitted when an object is created.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(BaseHandle object);
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The Object has been initialized.
+   */
+  ObjectCreatedSignalType& ObjectCreatedSignal();
+
+  /**
+   * @brief This signal is emitted when an object is destroyed.
+   *
+   * WARNING: Since this signal is emitted when the object is
+   * in the process of being destroyed, the RefObject pointer
+   * passed in the signal should not be modified in anyways.
+   * And should NOT be used to create an handle. which will
+   * affect the life time of this destroyed object and leads to
+   * undefined behaviour.
+   *
+   * The only intended use is for Toolkit controls which want to
+   * keep track of objects being created and destroyed for internal
+   * bookkeeping.
+   *
+   * A callback of the following type may be connected:
+   * @code
+   *   void YourCallbackName(const Dali::RefObject* objectPointer);
+   * @endcode
+   * @since_tizen 2.4
+   * @return The signal to connect to.
+   * @pre The Object has been initialized.
+   */
+  ObjectDestroyedSignalType& ObjectDestroyedSignal();
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali Get() method.
+   *
+   * @since_tizen 2.4
+   * @param [in] objectRegistry A pointer to a Dali resource
+   */
+  explicit DALI_INTERNAL ObjectRegistry(Internal::ObjectRegistry* objectRegistry);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_OBJECT_REGISTRY_H__
diff --git a/dali/public-api/object/property-array.cpp b/dali/public-api/object/property-array.cpp
new file mode 100644 (file)
index 0000000..e401f32
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-array.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace
+{
+}; // unnamed namespace
+
+struct Property::Array::Impl
+{
+  typedef std::vector<Value> Array;
+
+  Array mArray;
+};
+
+Property::Array::Array()
+: mImpl( new Impl )
+{
+}
+
+Property::Array::Array( const Property::Array& other )
+: mImpl( new Impl )
+{
+  mImpl->mArray = other.mImpl->mArray;
+}
+
+Property::Array::~Array()
+{
+  delete mImpl;
+}
+
+Property::Array::SizeType Property::Array::Count() const
+{
+  return mImpl->mArray.size();
+}
+
+void Property::Array::PushBack( const Value& value )
+{
+  mImpl->mArray.push_back( value );
+}
+
+void Property::Array::Clear()
+{
+  mImpl->mArray.clear();
+}
+
+void Property::Array::Reserve( SizeType size )
+{
+  mImpl->mArray.reserve(size);
+}
+
+void Property::Array::Resize( SizeType size )
+{
+  mImpl->mArray.resize(size);
+}
+
+Property::Array::SizeType Property::Array::Capacity()
+{
+  return mImpl->mArray.capacity();
+}
+
+const Property::Value& Property::Array::operator[]( SizeType index ) const
+{
+  return mImpl->mArray[ index ];
+}
+
+Property::Value& Property::Array::operator[]( SizeType index )
+{
+  return mImpl->mArray[ index ];
+}
+
+Property::Array& Property::Array::operator=( const Property::Array& other )
+{
+  if( this != &other )
+  {
+    delete mImpl;
+    mImpl = new Impl;
+    mImpl->mArray = other.mImpl->mArray;
+  }
+  return *this;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-array.h b/dali/public-api/object/property-array.h
new file mode 100644 (file)
index 0000000..eacc77e
--- /dev/null
@@ -0,0 +1,198 @@
+#ifndef __DALI_PROPERTY_ARRAY_H__
+#define __DALI_PROPERTY_ARRAY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief A Array of property values.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Property::Array
+{
+public:
+
+  typedef std::size_t SizeType;
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Array();
+
+  /**
+   * @brief Copy Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The Array to copy from.
+   */
+  Array( const Array& other );
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Array();
+
+  /**
+   * @brief Retrieve the number of elements in the array.
+   *
+   * @since_tizen 2.4
+   * @return The number of elements in the array.
+   */
+  SizeType Size() const
+  {
+    return Count();
+  }
+
+  /**
+   * @brief Retrieve the number of elements in the array.
+   *
+   * @since_tizen 2.4
+   * @return The number of elements in the array.
+   */
+  SizeType Count() const;
+
+  /**
+   * @brief Returns whether the array is empty.
+   *
+   * @since_tizen 2.4
+   * @return true if empty, false otherwise
+   */
+  bool Empty() const
+  {
+    return Count() == 0;
+  }
+
+  /**
+   * @brief Clears the array.
+   * @since_tizen 2.4
+   */
+  void Clear();
+
+  /**
+   * @brief Increase the capcity of the array.
+   * @since_tizen 2.4
+   */
+  void Reserve( SizeType size );
+
+  /**
+   * @brief Resize to size.
+   * @since_tizen 2.4
+   */
+  void Resize( SizeType size );
+
+  /**
+   * @brief Retrieve the capacity of the array.
+   *
+   * @since_tizen 2.4
+   * @return The allocated capacity of the array
+   */
+  SizeType Capacity();
+
+  /**
+   * @brief Add an element to the array.
+   *
+   * @since_tizen 2.4
+   * @param[in] value The value to add to the end of the array
+   */
+  void PushBack( const Value& value );
+
+  /**
+   * @brief Const access an element.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The element index to access. No bounds checking is performed.
+   *
+   * @return The a reference to the element.
+   */
+  const Value& GetElementAt( SizeType index ) const
+  {
+    return operator[]( index );
+  }
+
+  /**
+   * @brief Access an element.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The element index to access. No bounds checking is performed.
+   *
+   * @return The a reference to the element.
+   */
+  Value& GetElementAt( SizeType index )
+  {
+    return operator[]( index );
+  }
+
+  /**
+   * @brief Const operator to access an element.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The element index to access. No bounds checking is performed.
+   *
+   * @return The a reference to the element.
+   *
+   */
+  const Value& operator[]( SizeType index ) const;
+
+  /**
+   * @brief Operator to access an element.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The element index to access. No bounds checking is performed.
+   *
+   * @return The a reference to the element.
+   *
+   */
+  Value& operator[]( SizeType index );
+
+  /**
+   * @brief Assignment Operator
+   *
+   * @since_tizen 2.4
+   * @param[in] other The array to copy from.
+   *
+   * @return The copied array.
+   */
+  Array& operator=( const Array& other );
+
+private:
+  struct DALI_INTERNAL Impl; ///< Private data
+  Impl* mImpl; ///< Pointer to private data
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_ARRAY_H__
diff --git a/dali/public-api/object/property-conditions.cpp b/dali/public-api/object/property-conditions.cpp
new file mode 100644 (file)
index 0000000..a538a12
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-conditions.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-value.h>
+#include <dali/internal/event/common/property-conditions-impl.h>
+
+namespace Dali
+{
+
+PropertyCondition::PropertyCondition()
+: BaseHandle(new Internal::PropertyCondition())
+{
+
+}
+
+PropertyCondition::~PropertyCondition()
+{
+
+}
+
+PropertyCondition::PropertyCondition( const PropertyCondition& handle )
+: BaseHandle(handle)
+{
+}
+
+PropertyCondition& PropertyCondition::operator=( const PropertyCondition& rhs )
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+std::size_t PropertyCondition::GetArgumentCount() const
+{
+  return GetImplementation(*this).arguments.Count();
+}
+
+float PropertyCondition::GetArgument( std::size_t index ) const
+{
+  return GetImplementation(*this).arguments[ index ];
+}
+
+PropertyCondition LessThanCondition( float arg )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::LessThan;
+  impl.arguments.PushBack( arg );
+
+  return condition;
+}
+
+PropertyCondition GreaterThanCondition( float arg )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::GreaterThan;
+  impl.arguments.PushBack( arg );
+
+  return condition;
+}
+
+PropertyCondition InsideCondition( float arg0, float arg1 )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::Inside;
+  impl.arguments.PushBack( arg0 );
+  impl.arguments.PushBack( arg1 );
+
+  return condition;
+}
+
+PropertyCondition OutsideCondition( float arg0, float arg1 )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::Outside;
+  impl.arguments.PushBack( arg0 );
+  impl.arguments.PushBack( arg1 );
+
+  return condition;
+}
+
+PropertyCondition StepCondition( float stepAmount, float referenceValue )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::Step;
+  impl.arguments.PushBack( referenceValue );
+  impl.arguments.PushBack( 1.0f / stepAmount );
+  impl.arguments.PushBack( 0.0f ); // current step
+
+  return condition;
+}
+
+PropertyCondition VariableStepCondition( const Dali::Vector<float>& stepAmount )
+{
+  PropertyCondition condition;
+  Internal::PropertyCondition& impl = GetImplementation( condition );
+  impl.type = Internal::PropertyCondition::VariableStep;
+  impl.arguments.PushBack( 0.0f ); // current step
+  Dali::Vector<float>::SizeType count = stepAmount.Count();
+  impl.arguments.PushBack( float( count ) ); // store number of steps
+  for( Dali::Vector<float>::SizeType index = 0; index < count; ++index )
+  {
+    impl.arguments.PushBack( stepAmount[index] );
+  }
+
+  return condition;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-conditions.h b/dali/public-api/object/property-conditions.h
new file mode 100644 (file)
index 0000000..86799ae
--- /dev/null
@@ -0,0 +1,192 @@
+#ifndef __DALI_PROPERTY_CONDITIONS_H__
+#define __DALI_PROPERTY_CONDITIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class PropertyCondition;
+}
+
+/**
+ * @brief This represents a condition that can be evaluated on a Property::Value.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API PropertyCondition : public BaseHandle
+{
+public:
+
+  /**
+   * @brief Constructor for condition clause.
+   * @since_tizen 2.4
+   */
+  PropertyCondition();
+
+  /**
+   * @brief Destructor.
+   * @since_tizen 2.4
+   */
+  ~PropertyCondition();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  PropertyCondition( const PropertyCondition& handle );
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  PropertyCondition& operator=( const PropertyCondition& rhs );
+
+public:
+
+  /**
+   * @brief Retrieve the arguments that this condition uses.
+   *
+   * @since_tizen 2.4
+   * @return The arguments used for this condition
+   */
+  std::size_t GetArgumentCount() const;
+
+  /**
+   * @brief Retrieve the arguments that this condition uses.
+   *
+   * @since_tizen 2.4
+   * @return The arguments used for this condition
+   * @note The container will only be valid as long PropertyCondition is valid.
+   */
+  float GetArgument( std::size_t index ) const;
+
+};
+
+/**
+ * @brief LessThanCondition compares whether property is less than arg.
+ *
+ * property type:
+ * bool (false = 0.0f, true = 1.0f)
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] arg The argument for the condition
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition LessThanCondition( float arg );
+
+/**
+ * @brief GreaterThanCondition compares whether property is greater than arg.
+ *
+ * property type:
+ * bool (false = 0.0f, true = 1.0f)
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] arg The argument for the condition
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition GreaterThanCondition( float arg );
+
+/**
+ * @brief InsideCondition compares whether property is greater than arg0 and less than arg1.
+ *
+ * property type:
+ * bool (false = 0.0f, true = 1.0f)
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] arg0 The first argument for the condition
+ * @param[in] arg1 The second argument for the condition
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition InsideCondition( float arg0, float arg1 );
+
+/**
+ * @brief OutsideCondition compares whether property is less than arg0 or greater than arg1.
+ *
+ * property type:
+ * bool (false = 0.0f, true = 1.0f)
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] arg0 The first argument for the condition
+ * @param[in] arg1 The second argument for the condition
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition OutsideCondition( float arg0, float arg1 );
+
+/**
+ * @brief Detects when a property changes by stepAmount from initialValue, in both positive and negative directions. This will continue checking for multiples of stepAmount
+ *
+ * property type:
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] stepAmount The step size required to trigger condition
+ * @param[in] initialValue The initial value to step from
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition StepCondition( float stepAmount, float initialValue = 0.0f );
+
+/**
+ * @brief Receive notifications as a property goes above/below the inputted values. Values must be ordered and can be either ascending or descending
+ *
+ * property type:
+ * float (float)
+ * vector2 (the 2D length)
+ * vector3 (the 3D length)
+ * vector4 (the 4D length)
+ * @since_tizen 2.4
+ * @param[in] steps List of values to receive notifications for as a property crosses them
+ * @return A property condition function object
+ */
+DALI_IMPORT_API PropertyCondition VariableStepCondition( const Dali::Vector<float>& steps );
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_CONDITIONS_H__
diff --git a/dali/public-api/object/property-index-ranges.h b/dali/public-api/object/property-index-ranges.h
new file mode 100644 (file)
index 0000000..5203e51
--- /dev/null
@@ -0,0 +1,67 @@
+#ifndef __DALI_PROPERTY_INDEX_RANGES_H__
+#define __DALI_PROPERTY_INDEX_RANGES_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief These are the property index ranges.
+ *
+ * Enumerations are being used here rather than static constants so that switch statements can be
+ * used to compare property indices.
+ * @since_tizen 2.4
+ */
+enum PropertyRanges
+{
+  DEFAULT_OBJECT_PROPERTY_START_INDEX           = 0,          ///< For all objects deriving from Handle (including Actors).
+
+  DEFAULT_ACTOR_PROPERTY_START_INDEX            = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< Start index for Actor.
+  DEFAULT_ACTOR_PROPERTY_MAX_COUNT              = 10000,      ///< Actor range: 0 to 9999
+
+  DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX    = DEFAULT_ACTOR_PROPERTY_START_INDEX + DEFAULT_ACTOR_PROPERTY_MAX_COUNT, ///< Property start index for classes deriving directly from Actor.
+
+  DEFAULT_PROPERTY_MAX_COUNT_PER_DERIVATION     = 10000,      ///< Second-level and onwards derived objects should increment their start index by this.
+
+  DEFAULT_GESTURE_DETECTOR_PROPERTY_START_INDEX = DEFAULT_DERIVED_ACTOR_PROPERTY_START_INDEX,  ///< Used by PanGestureDetector.
+
+  PROPERTY_REGISTRATION_START_INDEX             = 10000000,   ///< The index when registering a property should start from this number.
+  DEFAULT_PROPERTY_MAX_COUNT                    = PROPERTY_REGISTRATION_START_INDEX,           ///< Default Property Range: 0 to 9999999
+
+  PROPERTY_REGISTRATION_MAX_INDEX               = 19999999,   ///< The maximum index supported when registering a property
+
+  ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX  = 20000000,   ///< The index when registering an animatable property should start from this number. (SceneGraph properties per type)
+  ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX    = 29999999,   ///< The maximum index supported when registering an animatable property
+
+  PROPERTY_CUSTOM_START_INDEX                   = 50000000,   ///< The index at which custom properties start (SceneGraph and Event side properties per instance)
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_INDEX_RANGES_H__
diff --git a/dali/public-api/object/property-input.cpp b/dali/public-api/object/property-input.cpp
new file mode 100644 (file)
index 0000000..47937b3
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-input.h>
+
+namespace Dali
+{
+
+PropertyInput::~PropertyInput()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-input.h b/dali/public-api/object/property-input.h
new file mode 100644 (file)
index 0000000..84bafa1
--- /dev/null
@@ -0,0 +1,160 @@
+#ifndef __DALI_PROPERTY_INPUT_H__
+#define __DALI_PROPERTY_INPUT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+struct Vector2;
+struct Vector3;
+struct Vector4;
+class Matrix3;
+class Matrix;
+class Quaternion;
+
+/**
+ * @brief An abstract interface for receiving property values.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API PropertyInput
+{
+public:
+
+  class Extension; ///< Forward declare future extension interface
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~PropertyInput() = 0;
+
+  /**
+   * @brief Query the type of property input.
+   *
+   * @since_tizen 2.4
+   * @return The property type.
+   */
+  virtual Property::Type GetType() const = 0;
+
+  /**
+   * @brief Retrieve a boolean value.
+   *
+   * @since_tizen 2.4
+   * @return The boolean value.
+   * @pre GetType() returns Property::BOOLEAN.
+   */
+  virtual const bool& GetBoolean() const = 0;
+
+  /**
+   * @brief Retrieve a float value.
+   *
+   * @since_tizen 2.4
+   * @return The float value.
+   * @pre GetType() returns Property::FLOAT.
+   */
+  virtual const float& GetFloat() const = 0;
+
+  /**
+   * @brief Retrieve an integer value.
+   *
+   * @since_tizen 2.4
+   * @return The integer value.
+   * @pre GetType() returns Property::INTEGER.
+   */
+  virtual const int& GetInteger() const = 0;
+
+  /**
+   * @brief Retrieve a Vector2 value.
+   *
+   * @since_tizen 2.4
+   * @return The Vector2 value.
+   * @pre GetType() returns Property::VECTOR2.
+   */
+  virtual const Vector2& GetVector2() const = 0;
+
+  /**
+   * @brief Retrieve a Vector3 value.
+   *
+   * @since_tizen 2.4
+   * @return The Vector3 value.
+   * @pre GetType() returns Property::VECTOR3.
+   */
+  virtual const Vector3& GetVector3() const = 0;
+
+  /**
+   * @brief Retrieve a Vector4 value.
+   *
+   * @since_tizen 2.4
+   * @return The Vector4 value.
+   * @pre GetType() returns Property::VECTOR4.
+   */
+  virtual const Vector4& GetVector4() const = 0;
+
+  /**
+   * @brief Retrieve a Matrix (3x3) value.
+   *
+   * @since_tizen 2.4
+   * @return The Matrix value.
+   * @pre GetType() returns Property::Matrix3.
+   */
+  virtual const Matrix3& GetMatrix3() const = 0;
+
+  /**
+   * @brief Retrieve a Matrix (4x4) value.
+   *
+   * @since_tizen 2.4
+   * @return The Matrix value.
+   * @pre GetType() returns Property::Matrix4.
+   */
+  virtual const Matrix& GetMatrix() const = 0;
+
+  /**
+   * @brief Retrieve a Quaternion value.
+   *
+   * @since_tizen 2.4
+   * @return The Quaternion value.
+   * @pre GetType() returns Property::Quaternion.
+   */
+  virtual const Quaternion& GetQuaternion() const = 0;
+
+  /**
+   * @brief Retrieve the extension for the PropertyInput
+   *
+   * @since_tizen 2.4
+   * @return The extension if available, NULL otherwise
+   */
+  virtual Extension* GetExtension()
+  {
+    return NULL;
+  }
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_INPUT_H__
diff --git a/dali/public-api/object/property-map.cpp b/dali/public-api/object/property-map.cpp
new file mode 100644 (file)
index 0000000..fdf1cef
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-map.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+
+namespace
+{
+typedef std::vector< StringValuePair > Container;
+}; // unnamed namespace
+
+struct Property::Map::Impl
+{
+  Container mContainer;
+};
+
+Property::Map::Map()
+: mImpl( new Impl )
+{
+}
+
+Property::Map::Map( const Property::Map& other )
+: mImpl( new Impl )
+{
+  mImpl->mContainer = other.mImpl->mContainer;
+}
+
+Property::Map::~Map()
+{
+  delete mImpl;
+}
+
+Property::Map::SizeType Property::Map::Count() const
+{
+  return mImpl->mContainer.size();
+}
+
+bool Property::Map::Empty() const
+{
+  return mImpl->mContainer.empty();
+}
+
+void Property::Map::Insert( const char* key, const Value& value )
+{
+  mImpl->mContainer.push_back( std::make_pair( key, value ) );
+}
+
+void Property::Map::Insert( const std::string& key, const Value& value )
+{
+  mImpl->mContainer.push_back( std::make_pair( key, value ) );
+}
+
+Property::Value& Property::Map::GetValue( SizeType position ) const
+{
+  DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
+
+  return mImpl->mContainer[ position ].second;
+}
+
+const std::string& Property::Map::GetKey( SizeType position ) const
+{
+  DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
+
+  return mImpl->mContainer[ position ].first;
+}
+
+StringValuePair& Property::Map::GetPair( SizeType position ) const
+{
+  DALI_ASSERT_ALWAYS( position < Count() && "position out-of-bounds" );
+
+  return mImpl->mContainer[ position ];
+}
+
+Property::Value* Property::Map::Find( const char* key ) const
+{
+  for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
+  {
+    if ( iter->first == key )
+    {
+      return &iter->second;
+    }
+  }
+  return NULL; // Not found
+}
+
+Property::Value* Property::Map::Find( const std::string& key ) const
+{
+  return Find( key.c_str() );
+
+}
+
+Property::Value* Property::Map::Find( const std::string& key, Property::Type type ) const
+{
+  for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
+  {
+    // test type first to shortcut eval (possibly reducing string compares)
+    if( (iter->second.GetType() == type) && (iter->first == key) )
+    {
+      return &iter->second;
+    }
+  }
+  return NULL; // Not found
+}
+
+void Property::Map::Clear()
+{
+  mImpl->mContainer.clear();
+}
+
+void Property::Map::Merge( const Property::Map& from )
+{
+  // Ensure we're not attempting to merge with ourself
+  if ( this != &from )
+  {
+    if ( Count() )
+    {
+      for ( unsigned int i = 0, count = from.Count(); i < count; ++i )
+      {
+        StringValuePair& pair( from.GetPair( i ) );
+        (*this)[ pair.first ] = pair.second;
+      }
+    }
+    else
+    {
+      // If we're empty, then just copy
+      *this = from;
+    }
+  }
+}
+
+const Property::Value& Property::Map::operator[]( const std::string& key ) const
+{
+  for ( Container::const_iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
+  {
+    if ( iter->first == key )
+    {
+      return iter->second;
+    }
+  }
+
+  DALI_ASSERT_ALWAYS( ! "Invalid Key" );
+}
+
+Property::Value& Property::Map::operator[]( const std::string& key )
+{
+  for ( Container::iterator iter = mImpl->mContainer.begin(), endIter = mImpl->mContainer.end(); iter != endIter; ++iter )
+  {
+    if ( iter->first == key )
+    {
+      return iter->second;
+    }
+  }
+
+  // Create and return reference to new value
+  mImpl->mContainer.push_back( std::make_pair( key, Property::Value() ) );
+  return (mImpl->mContainer.end() - 1)->second;
+}
+
+Property::Map& Property::Map::operator=( const Property::Map& other )
+{
+  if( this != &other )
+  {
+    delete mImpl;
+    mImpl = new Impl;
+    mImpl->mContainer = other.mImpl->mContainer;
+  }
+  return *this;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-map.h b/dali/public-api/object/property-map.h
new file mode 100644 (file)
index 0000000..daea471
--- /dev/null
@@ -0,0 +1,225 @@
+#ifndef __DALI_PROPERTY_MAP_H__
+#define __DALI_PROPERTY_MAP_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/object/property-value.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+typedef std::pair<std::string, Property::Value> StringValuePair;
+
+/**
+ * @brief A Map of property values.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Property::Map
+{
+public:
+
+  typedef std::size_t SizeType;
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Map();
+
+  /**
+   * @brief Copy Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] other The Map to copy from.
+   */
+  Map( const Map& other );
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Map();
+
+  /**
+   * @brief Retrieve the number of elements in the map.
+   *
+   * @since_tizen 2.4
+   * @return The number of elements in the map.
+   */
+  SizeType Count() const;
+
+  /**
+   * @brief Returns whether the map is empty.
+   *
+   * @since_tizen 2.4
+   * @return true if empty, false otherwise
+   */
+  bool Empty() const;
+
+  /**
+   * @brief Inserts the key-value pair in the Map.
+   *
+   * Does not check for duplicates
+   * @since_tizen 2.4
+   * @param key to insert
+   * @param value to insert
+   */
+  void Insert( const char* key, const Value& value );
+
+  /**
+   * @brief Inserts the key-value pair in the Map.
+   *
+   * Does not check for duplicates
+   * @since_tizen 2.4
+   * @param key to insert
+   * @param value to insert
+   */
+  void Insert( const std::string& key, const Value& value );
+
+  /**
+   * @brief Retrieve the value at the specified position.
+   *
+   * @since_tizen 2.4
+   * @return A reference to the value at the specified position.
+   *
+   * @note Will assert if position >= Count()
+   */
+  Value& GetValue( SizeType position ) const;
+
+  /**
+   * @brief Retrieve the key at the specified position.
+   *
+   * @since_tizen 2.4
+   * @return A const reference to the key at the specified position.
+   *
+   * @note Will assert if position >= Count()
+   */
+  const std::string& GetKey( SizeType position ) const;
+
+  /**
+   * @brief Retrieve the key & the value at the specified position.
+   *
+   * @since_tizen 2.4
+   * @return A reference to the pair of key and value at the specified position.
+   *
+   * @note Will assert if position >= Count()
+   */
+  StringValuePair& GetPair( SizeType position ) const;
+
+  /**
+   * @brief Finds the value for the specified key if it exists.
+   *
+   * @since_tizen 2.4
+   * @param[in]  key   The key to find.
+   *
+   * @return A const pointer to the value if it exists, NULL otherwise
+   */
+  Value* Find( const char* key ) const;
+
+  /**
+   * @brief Finds the value for the specified key if it exists.
+   *
+   * @since_tizen 2.4
+   * @param[in]  key   The key to find.
+   *
+   * @return A const pointer to the value if it exists, NULL otherwise
+   */
+  Value* Find( const std::string& key ) const;
+
+  /**
+   * @brief Finds the value for the specified key if it exists and its type is type
+   *
+   * @since_tizen 2.4
+   * @param[in]  key   The key to find.
+   * @param[in]  type  The type to check.
+   *
+   * @return A const pointer to the value if it exists, NULL otherwise
+   */
+  Value* Find( const std::string& key, Property::Type type ) const;
+
+  /**
+   * @brief Clears the map.
+   * @since_tizen 2.4
+   */
+  void Clear();
+
+  /**
+   * @brief Merges values from the map 'from' to the current.
+   *
+   * Any values in 'from' will overwrite the values in the current map.
+   *
+   * @since_tizen 2.4
+   * @param[in]  from  The map to merge from.
+   */
+  void Merge( const Map& from );
+
+  /**
+   * @brief Const operator to access element with the specified key.
+   *
+   * @since_tizen 2.4
+   * @param[in] key The key whose value to access.
+   *
+   * @return The value for the element with the specified key, if key doesn't exist, then Property::NONE is returned.
+   *
+   * @note Will assert if invalid-key is given.
+   */
+  const Value& operator[]( const std::string& key ) const;
+
+  /**
+   * @brief Operator to access the element with the specified key.
+   *
+   * @since_tizen 2.4
+   * @param[in] key The key whose value to access.
+   *
+   * @return A reference to the value for the element with the specified key.
+   *
+   * @note If an element with the key does not exist, then it is created.
+   */
+  Value& operator[]( const std::string& key );
+
+  /**
+   * @brief Assignment Operator
+   *
+   * @since_tizen 2.4
+   * @param[in] other The map to copy from.
+   *
+   * @return The copied map.
+   */
+  Map& operator=( const Map& other );
+
+private:
+  struct DALI_INTERNAL Impl; ///< Private data
+  Impl* mImpl; ///< Pointer to private data
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_MAP_H__
diff --git a/dali/public-api/object/property-notification-declarations.h b/dali/public-api/object/property-notification-declarations.h
new file mode 100644 (file)
index 0000000..05639b0
--- /dev/null
@@ -0,0 +1,45 @@
+#ifndef __DALI_PROPERTY_NOTIFICATION_DECLARATIONS_H__
+#define __DALI_PROPERTY_NOTIFICATION_DECLARATIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class PropertyNotification;
+
+/**
+ * @brief Signal type for Dali::PropertyNotification::NotifySignal().
+ * @since_tizen 2.4
+ */
+typedef Signal< void (PropertyNotification& source) > PropertyNotifySignalType;
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_NOTIFICATION_DECLARATIONS_H__
diff --git a/dali/public-api/object/property-notification.cpp b/dali/public-api/object/property-notification.cpp
new file mode 100644 (file)
index 0000000..81e0538
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-notification.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/internal/event/common/property-notification-impl.h>
+#include <stdio.h>
+
+namespace Dali
+{
+
+PropertyNotification::PropertyNotification()
+{
+}
+
+PropertyNotification::PropertyNotification(Internal::PropertyNotification* propertyNotification)
+: BaseHandle(propertyNotification)
+{
+}
+
+PropertyNotification PropertyNotification::DownCast( BaseHandle handle )
+{
+  return PropertyNotification( dynamic_cast<Dali::Internal::PropertyNotification*>(handle.GetObjectPtr()) );
+}
+
+PropertyNotification::~PropertyNotification()
+{
+}
+
+PropertyNotification::PropertyNotification(const PropertyNotification& copy)
+: BaseHandle(copy)
+{
+}
+
+PropertyNotification& PropertyNotification::operator=(const PropertyNotification& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+PropertyCondition PropertyNotification::GetCondition()
+{
+  return GetImplementation(*this).GetCondition();
+}
+
+const PropertyCondition& PropertyNotification::GetCondition() const
+{
+  return GetImplementation(*this).GetCondition();
+}
+
+Dali::Handle PropertyNotification::GetTarget() const
+{
+  return GetImplementation(*this).GetTarget();
+}
+
+Property::Index PropertyNotification::GetTargetProperty() const
+{
+  return GetImplementation(*this).GetTargetProperty();
+}
+
+void PropertyNotification::SetNotifyMode( NotifyMode mode )
+{
+  GetImplementation(*this).SetNotifyMode( mode );
+}
+
+PropertyNotification::NotifyMode PropertyNotification::GetNotifyMode()
+{
+  return GetImplementation(*this).GetNotifyMode();
+}
+
+bool PropertyNotification::GetNotifyResult() const
+{
+  return GetImplementation(*this).GetNotifyResult();
+}
+
+PropertyNotifySignalType& PropertyNotification::NotifySignal()
+{
+  return GetImplementation(*this).NotifySignal();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-notification.h b/dali/public-api/object/property-notification.h
new file mode 100644 (file)
index 0000000..d4e273f
--- /dev/null
@@ -0,0 +1,190 @@
+#ifndef __DALI_PROPERTY_NOTIFICATION_H__
+#define __DALI_PROPERTY_NOTIFICATION_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/property-notification-declarations.h>
+#include <dali/public-api/object/property-conditions.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class PropertyNotification;
+}
+
+/**
+ * @brief This is used to issue a notification upon a condition of the property being met.
+ *
+ * For example checking if Actor::POSITION_X > 100.0.
+ * @since_tizen 2.4
+ * @see Dali::PropertyCondition
+ */
+class DALI_IMPORT_API PropertyNotification : public BaseHandle
+{
+public:
+  /**
+   * @brief Enumeration to describe how to check condition
+   * @since_tizen 2.4
+   */
+  enum NotifyMode
+  {
+    Disabled,                             ///< Don't notify, regardless of result of Condition
+    NotifyOnTrue,                         ///< Notify whenever condition changes from false to true.
+    NotifyOnFalse,                        ///< Notify whenever condition changes from true to false.
+    NotifyOnChanged                       ///< Notify whenever condition changes (false to true, and true to false)
+  };
+
+public:
+
+  /**
+   * @brief Create an uninitialized PropertyNotification; this can be initialized with PropertyNotification::New().
+   *
+   * Calling member functions with an uninitialized Dali::Object is not allowed.
+   * @since_tizen 2.4
+   */
+  PropertyNotification();
+
+  /**
+   * @brief Downcast an Object handle to PropertyNotification.
+   *
+   * If handle points to an PropertyNotification object the downcast
+   * produces valid handle. If not the returned handle is left
+   * uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a PropertyNotification object or an uninitialized handle
+   */
+  static PropertyNotification DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~PropertyNotification();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  PropertyNotification(const PropertyNotification& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  PropertyNotification& operator=(const PropertyNotification& rhs);
+
+  /**
+   * @brief Get the condition of this notification
+   *
+   * @since_tizen 2.4
+   * @return The condition is returned
+   */
+  PropertyCondition GetCondition();
+
+  /**
+   * @brief Get the condition of this notification
+   *
+   * @since_tizen 2.4
+   * @return The condition is returned
+   */
+  const PropertyCondition& GetCondition() const;
+
+  /**
+   * @brief Get the target handle that this notification is observing.
+   * @since_tizen 2.4
+   */
+  Dali::Handle GetTarget() const;
+
+  /**
+   * @brief Get the target handle's property index that this notification
+   * is observing.
+   *
+   * @since_tizen 2.4
+   * @return The target property.
+   */
+  Property::Index GetTargetProperty() const;
+
+  /**
+   * @brief Sets the Notification mode. This determines how the property
+   * notification should respond to the result of a condition.
+   *
+   * @since_tizen 2.4
+   * @param[in] mode Notification mode (Default is PropertyNotification::NotifyOnTrue)
+   */
+  void SetNotifyMode( NotifyMode mode );
+
+  /**
+   * @brief Retrieves the current Notification mode.
+   *
+   * @since_tizen 2.4
+   * @return Notification mode.
+   */
+  NotifyMode GetNotifyMode();
+
+  /**
+   * @brief Gets the result of the last condition check that caused a signal emit,
+   * useful when using NotifyOnChanged mode and need to know what it changed to.
+   *
+   * @since_tizen 2.4
+   * @return whether condition result that triggered last emit was true or false
+   */
+  bool GetNotifyResult() const;
+
+  /**
+   * @brief Connect to this signal to be notified when the notification has occurred.
+   *
+   * @since_tizen 2.4
+   * @return A signal object to Connect() with.
+   */
+  PropertyNotifySignalType& NotifySignal();
+
+public: // Not intended for use by Application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   *
+   * @since_tizen 2.4
+   * @param [in] propertyNotification A pointer to a newly allocated Dali resource
+   */
+  explicit DALI_INTERNAL PropertyNotification(Internal::PropertyNotification* propertyNotification);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_NOTIFICATION_H__
diff --git a/dali/public-api/object/property-types.cpp b/dali/public-api/object/property-types.cpp
new file mode 100644 (file)
index 0000000..a5e8d81
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-types.h>
+
+namespace Dali
+{
+
+namespace
+{
+const char* const PROPERTY_TYPE_NAMES[] =
+{
+  "NONE",
+  "BOOLEAN",
+  "FLOAT",
+  "INTEGER",
+  "VECTOR2",
+  "VECTOR3",
+  "VECTOR4",
+  "MATRIX3",
+  "MATRIX",
+  "RECTANGLE",
+  "ROTATION",
+  "STRING",
+  "ARRAY",
+  "MAP",
+};
+const unsigned int PROPERTY_TYPE_NAMES_COUNT = sizeof( PROPERTY_TYPE_NAMES ) / sizeof( const char* );
+}
+
+namespace PropertyTypes
+{
+
+DALI_EXPORT_API const char* GetName(Property::Type type)
+{
+  if (type < PROPERTY_TYPE_NAMES_COUNT )
+  {
+    return PROPERTY_TYPE_NAMES[type];
+  }
+
+  return PROPERTY_TYPE_NAMES[Property::NONE];
+}
+
+}; // namespace PropertyTypes
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-types.h b/dali/public-api/object/property-types.h
new file mode 100644 (file)
index 0000000..4009f30
--- /dev/null
@@ -0,0 +1,103 @@
+#ifndef __DALI_PROPERTY_TYPES_H__
+#define __DALI_PROPERTY_TYPES_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/public-api/math/angle-axis.h>
+#include <dali/public-api/math/degree.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/object/property.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+/**
+ * @brief Template function instances for property getters.
+ * @since_tizen 2.4
+ */
+namespace PropertyTypes
+{
+
+/**
+ * @brief Retrieve the name of a property type.
+ *
+ * @since_tizen 2.4
+ * @param [in] type The property type.
+ * @return The name of this type.
+ */
+DALI_IMPORT_API const char* GetName(Property::Type type);
+
+/**
+ * @brief Retrieve an enumerated property type.
+ *
+ * New versions of this templated function must be defined for future types.
+ * @since_tizen 2.4
+ * @return The property type.
+ */
+template <typename T>
+inline Property::Type Get()                   { return Property::NONE;  }
+template <>
+inline Property::Type Get<bool>()             { return Property::BOOLEAN;  }
+template <>
+inline Property::Type Get<float>()            { return Property::FLOAT;    }
+template <>
+inline Property::Type Get<int>()              { return Property::INTEGER;  }
+template <>
+inline Property::Type Get<Vector2>()          { return Property::VECTOR2;  }
+template <>
+inline Property::Type Get<Vector3>()          { return Property::VECTOR3;  }
+template <>
+inline Property::Type Get<Vector4>()          { return Property::VECTOR4;  }
+template <>
+inline Property::Type Get<Matrix3>()          { return Property::MATRIX3;  }
+template <>
+inline Property::Type Get<Matrix>()           { return Property::MATRIX;  }
+template <>
+inline Property::Type Get<AngleAxis>()        { return Property::ROTATION; } // Rotation has two representations
+template <>
+inline Property::Type Get<Quaternion>()       { return Property::ROTATION; } // Rotation has two representations
+template <>
+inline Property::Type Get<std::string>()      { return Property::STRING; }
+template <>
+inline Property::Type Get<Dali::Rect<int> >() { return Property::RECTANGLE; }
+template <>
+inline Property::Type Get<Property::Map>()    { return Property::MAP; }
+template <>
+inline Property::Type Get<Property::Array>()  { return Property::ARRAY; }
+
+
+}; // namespace PropertyTypes
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_TYPES_H__
diff --git a/dali/public-api/object/property-value.cpp b/dali/public-api/object/property-value.cpp
new file mode 100644 (file)
index 0000000..85f407f
--- /dev/null
@@ -0,0 +1,862 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property-value.h>
+
+// EXTERNAL INCLUDES
+#include <ostream>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/angle-axis.h>
+#include <dali/public-api/math/radian.h>
+#include <dali/public-api/math/vector2.h>
+#include <dali/public-api/math/vector3.h>
+#include <dali/public-api/math/vector4.h>
+#include <dali/public-api/math/matrix3.h>
+#include <dali/public-api/math/matrix.h>
+#include <dali/public-api/math/rect.h>
+#include <dali/public-api/math/quaternion.h>
+#include <dali/public-api/object/property-map.h>
+#include <dali/public-api/object/property-array.h>
+#include <dali/public-api/object/property-types.h>
+#include <dali/integration-api/debug.h>
+
+namespace Dali
+{
+
+namespace
+{
+/**
+ * Helper to check if the property value can be read as int/bool
+ */
+inline bool IsIntegerType( Property::Type type )
+{
+  return ( Property::BOOLEAN == type )||( Property::INTEGER == type );
+}
+}
+
+struct Property::Value::Impl
+{
+  Impl()
+  : type( Property::NONE ),
+    integerValue( 0 )
+  { }
+
+  Impl( bool booleanValue )
+  : type( Property::BOOLEAN ),
+    integerValue( booleanValue )
+  { }
+
+  Impl( float floatValue )
+  : type( Property::FLOAT ),
+    floatValue( floatValue )
+  { }
+
+  Impl( int integerValue )
+  : type( Property::INTEGER ),
+    integerValue( integerValue )
+  { }
+
+  Impl( const Vector2& vectorValue )
+  : type( Property::VECTOR2 ),
+    vector2Value( new Vector2( vectorValue ) )
+  { }
+
+  Impl( const Vector3& vectorValue )
+  : type( Property::VECTOR3 ),
+    vector3Value( new Vector3( vectorValue ) )
+  { }
+
+  Impl( const Vector4& vectorValue )
+  : type( Property::VECTOR4 ),
+    vector4Value( new Vector4( vectorValue ) )
+  { }
+
+  Impl( const Matrix3& matrixValue )
+  : type( Property::MATRIX3 ),
+    matrix3Value( new Matrix3( matrixValue ) )
+  {
+  }
+
+  Impl( const Matrix& matrixValue )
+  : type( Property::MATRIX ),
+    matrixValue( new Matrix( matrixValue ) )
+  {
+  }
+
+  Impl( const AngleAxis& angleAxisValue )
+  : type( Property::ROTATION ),
+    quaternionValue( new Quaternion( angleAxisValue.angle, angleAxisValue.axis ) )
+  {
+  }
+
+  Impl( const Quaternion& quaternionValue )
+  : type( Property::ROTATION ),
+    quaternionValue( new Quaternion( quaternionValue ) )
+  {
+  }
+
+  Impl(const std::string& stringValue)
+  : type( Property::STRING ),
+    stringValue( new std::string( stringValue ) )
+  {
+  }
+
+  Impl( const Rect<int>& rectValue )
+  : type( Property::RECTANGLE ),
+    rectValue( new Rect<int>( rectValue ) )
+  {
+  }
+
+  Impl( const Property::Array& arrayValue )
+  : type( Property::ARRAY ),
+    arrayValue( new Property::Array( arrayValue ) )
+  {
+  }
+
+  Impl( const Property::Map& mapValue )
+  : type( Property::MAP ),
+    mapValue( new Property::Map( mapValue ) )
+  {
+  }
+
+  /**
+   * Destructor, takes care of releasing the dynamically allocated types
+   */
+  ~Impl()
+  {
+    switch( type )
+    {
+      case Property::NONE :             // FALLTHROUGH
+      case Property::BOOLEAN :          // FALLTHROUGH
+      case Property::FLOAT :            // FALLTHROUGH
+      case Property::INTEGER :
+      {
+        break; // nothing to do
+      }
+      case Property::VECTOR2 :
+      {
+        delete vector2Value;
+        break;
+      }
+      case Property::VECTOR3:
+      {
+        delete vector3Value;
+        break;
+      }
+      case Property::VECTOR4:
+      {
+        delete vector4Value;
+        break;
+      }
+      case Property::MATRIX3:
+      {
+        delete matrix3Value;
+        break;
+      }
+      case Property::MATRIX:
+      {
+        delete matrixValue;
+        break;
+      }
+      case Property::RECTANGLE:
+      {
+        delete rectValue;
+        break;
+      }
+      case Property::ROTATION:
+      {
+        delete quaternionValue;
+        break;
+      }
+      case Property::STRING:
+      {
+        delete stringValue;
+        break;
+      }
+      case Property::ARRAY:
+      {
+        delete arrayValue;
+        break;
+      }
+      case Property::MAP:
+      {
+        delete mapValue;
+        break;
+      }
+    }
+  }
+
+public: // Data
+
+  Type type;
+  union
+  {
+    int integerValue;
+    float floatValue;
+    // must use pointers for any class value pre c++ 11
+    Vector2* vector2Value;
+    Vector3* vector3Value;
+    Vector4* vector4Value;
+    Matrix3* matrix3Value;
+    Matrix* matrixValue;
+    Quaternion* quaternionValue;
+    std::string* stringValue;
+    Rect<int>* rectValue;
+    Property::Array* arrayValue;
+    Property::Map* mapValue;
+  };
+};
+
+Property::Value::Value()
+: mImpl( NULL )
+{
+}
+
+Property::Value::Value( bool booleanValue )
+: mImpl( new Impl( booleanValue ) )
+{
+}
+
+Property::Value::Value( float floatValue )
+: mImpl( new Impl( floatValue ) )
+{
+}
+
+Property::Value::Value( int integerValue )
+: mImpl( new Impl( integerValue ) )
+{
+}
+
+Property::Value::Value( const Vector2& vectorValue )
+: mImpl( new Impl( vectorValue ) )
+{
+}
+
+Property::Value::Value( const Vector3& vectorValue )
+: mImpl( new Impl( vectorValue ) )
+{
+}
+
+Property::Value::Value( const Vector4& vectorValue )
+: mImpl( new Impl( vectorValue ) )
+{
+}
+
+Property::Value::Value( const Matrix3& matrixValue )
+: mImpl( new Impl( matrixValue ) )
+{
+}
+
+Property::Value::Value( const Matrix& matrixValue )
+: mImpl( new Impl( matrixValue ) )
+{
+}
+
+Property::Value::Value( const Rect<int>& rectValue )
+: mImpl( new Impl( rectValue ) )
+{
+}
+
+Property::Value::Value( const AngleAxis& angleAxisValue )
+: mImpl( new Impl( angleAxisValue ) )
+{
+}
+
+Property::Value::Value( const Quaternion& quaternionValue )
+: mImpl( new Impl( quaternionValue ) )
+{
+}
+
+Property::Value::Value( const std::string& stringValue )
+: mImpl( new Impl( stringValue ) )
+{
+}
+
+Property::Value::Value( const char* stringValue )
+: mImpl( NULL )
+{
+  if( stringValue ) // string constructor is undefined with NULL pointer
+  {
+    mImpl = new Impl( std::string(stringValue) );
+  }
+  else
+  {
+    mImpl = new Impl( std::string() );
+  }
+}
+
+Property::Value::Value( Property::Array& arrayValue )
+: mImpl( new Impl( arrayValue ) )
+{
+}
+
+Property::Value::Value( Property::Map& mapValue )
+: mImpl( new Impl( mapValue ) )
+{
+}
+
+Property::Value::Value( Type type )
+{
+  switch (type)
+  {
+    case Property::BOOLEAN:
+    {
+      mImpl = new Impl( false );
+      break;
+    }
+    case Property::FLOAT:
+    {
+      mImpl = new Impl( 0.f );
+      break;
+    }
+    case Property::INTEGER:
+    {
+      mImpl = new Impl( 0 );
+      break;
+    }
+    case Property::VECTOR2:
+    {
+      mImpl = new Impl( Vector2::ZERO );
+      break;
+    }
+    case Property::VECTOR3:
+    {
+      mImpl = new Impl( Vector3::ZERO );
+      break;
+    }
+    case Property::VECTOR4:
+    {
+      mImpl = new Impl( Vector4::ZERO );
+      break;
+    }
+    case Property::RECTANGLE:
+    {
+      mImpl = new Impl( Rect<int>(0,0,0,0) );
+      break;
+    }
+    case Property::ROTATION:
+    {
+      mImpl = new Impl( Quaternion() );
+      break;
+    }
+    case Property::STRING:
+    {
+      mImpl = new Impl( std::string() );
+      break;
+    }
+    case Property::MATRIX:
+    {
+      mImpl = new Impl( Matrix() );
+      break;
+    }
+    case Property::MATRIX3:
+    {
+      mImpl = new Impl( Matrix3() );
+      break;
+    }
+    case Property::ARRAY:
+    {
+      mImpl = new Impl( Property::Array() );
+      break;
+    }
+    case Property::MAP:
+    {
+      mImpl = new Impl( Property::Map() );
+      break;
+    }
+    case Property::NONE:
+    {
+      mImpl = new Impl();
+      break;
+    }
+  }
+}
+
+Property::Value::Value( const Property::Value& value )
+: mImpl( NULL )
+{
+  // reuse assignment operator
+  operator=( value );
+}
+
+Property::Value& Property::Value::operator=( const Property::Value& value )
+{
+  if ( this == &value )
+  {
+    // skip self assignment
+    return *this;
+  }
+  // if we are assigned an empty value, just drop impl
+  if( !value.mImpl )
+  {
+    delete mImpl;
+    mImpl = NULL;
+    return *this;
+  }
+  // first check if the type is the same, no need to change impl, just assign
+  if( mImpl && ( mImpl->type == value.mImpl->type ) )
+  {
+    switch( mImpl->type )
+    {
+      case Property::BOOLEAN:
+      {
+        mImpl->integerValue = value.mImpl->integerValue;
+        break;
+      }
+      case Property::FLOAT:
+      {
+        mImpl->floatValue = value.mImpl->floatValue;
+        break;
+      }
+      case Property::INTEGER:
+      {
+        mImpl->integerValue = value.mImpl->integerValue;
+        break;
+      }
+      case Property::VECTOR2:
+      {
+        *mImpl->vector2Value = *value.mImpl->vector2Value; // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::VECTOR3:
+      {
+        *mImpl->vector3Value = *value.mImpl->vector3Value; // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::VECTOR4:
+      {
+        *mImpl->vector4Value = *value.mImpl->vector4Value; // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::RECTANGLE:
+      {
+        *mImpl->rectValue = *value.mImpl->rectValue; // type cannot change in mImpl so rect is allocated
+        break;
+      }
+      case Property::ROTATION:
+      {
+        *mImpl->quaternionValue = *value.mImpl->quaternionValue; // type cannot change in mImpl so quaternion is allocated
+        break;
+      }
+      case Property::STRING:
+      {
+        *mImpl->stringValue = *value.mImpl->stringValue; // type cannot change in mImpl so string is allocated
+        break;
+      }
+      case Property::MATRIX:
+      {
+        *mImpl->matrixValue = *value.mImpl->matrixValue; // type cannot change in mImpl so matrix is allocated
+        break;
+      }
+      case Property::MATRIX3:
+      {
+        *mImpl->matrix3Value = *value.mImpl->matrix3Value; // type cannot change in mImpl so matrix is allocated
+        break;
+      }
+      case Property::ARRAY:
+      {
+        *mImpl->arrayValue = *value.mImpl->arrayValue; // type cannot change in mImpl so array is allocated
+        break;
+      }
+      case Property::MAP:
+      {
+        *mImpl->mapValue = *value.mImpl->mapValue; // type cannot change in mImpl so map is allocated
+        break;
+      }
+      case Property::NONE:
+      { // mImpl will be NULL, there's no way to get to this case
+      }
+    }
+  }
+  else
+  {
+    // different type, release old impl and create new
+    Impl* newImpl( NULL );
+    switch ( value.mImpl->type )
+    {
+      case Property::BOOLEAN:
+      {
+        newImpl = new Impl( bool( value.mImpl->integerValue ) );
+        break;
+      }
+      case Property::FLOAT:
+      {
+        newImpl = new Impl( value.mImpl->floatValue );
+        break;
+      }
+      case Property::INTEGER:
+      {
+        newImpl = new Impl( value.mImpl->integerValue );
+        break;
+      }
+      case Property::VECTOR2:
+      {
+        newImpl = new Impl( *value.mImpl->vector2Value ); // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::VECTOR3:
+      {
+        newImpl = new Impl( *value.mImpl->vector3Value ); // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::VECTOR4:
+      {
+        newImpl = new Impl( *value.mImpl->vector4Value ); // type cannot change in mImpl so vector is allocated
+        break;
+      }
+      case Property::RECTANGLE:
+      {
+        newImpl = new Impl( *value.mImpl->rectValue ); // type cannot change in mImpl so rect is allocated
+        break;
+      }
+      case Property::ROTATION:
+      {
+        newImpl = new Impl( *value.mImpl->quaternionValue ); // type cannot change in mImpl so quaternion is allocated
+        break;
+      }
+      case Property::MATRIX3:
+      {
+        newImpl = new Impl( *value.mImpl->matrix3Value ); // type cannot change in mImpl so matrix is allocated
+        break;
+      }
+      case Property::MATRIX:
+      {
+        newImpl = new Impl( *value.mImpl->matrixValue ); // type cannot change in mImpl so matrix is allocated
+        break;
+      }
+      case Property::STRING:
+      {
+        newImpl = new Impl( *value.mImpl->stringValue ); // type cannot change in mImpl so string is allocated
+        break;
+      }
+      case Property::ARRAY:
+      {
+        newImpl = new Impl( *value.mImpl->arrayValue ); // type cannot change in mImpl so array is allocated
+        break;
+      }
+      case Property::MAP:
+      {
+        newImpl = new Impl( *value.mImpl->mapValue ); // type cannot change in mImpl so map is allocated
+        break;
+      }
+      case Property::NONE:
+      { // NULL value will be used for "empty" value
+      }
+    }
+    delete mImpl;
+    mImpl = newImpl;
+  }
+
+  return *this;
+}
+
+Property::Value::~Value()
+{
+  delete mImpl;
+}
+
+Property::Type Property::Value::GetType() const
+{
+  Property::Type type( Property::NONE );
+  if( mImpl )
+  {
+    type = mImpl->type;
+  }
+  return type;
+}
+
+bool Property::Value::Get( bool& booleanValue ) const
+{
+  bool converted = false;
+  if( mImpl && IsIntegerType( mImpl->type ) )
+  {
+    booleanValue = mImpl->integerValue;
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( float& floatValue ) const
+{
+  bool converted = false;
+  if( mImpl )
+  {
+    if( mImpl->type == FLOAT )
+    {
+      floatValue = mImpl->floatValue;
+      converted = true;
+    }
+    else if( IsIntegerType( mImpl->type ) )
+    {
+      floatValue = static_cast< float >( mImpl->integerValue );
+      converted = true;
+    }
+  }
+  return converted;
+}
+
+bool Property::Value::Get( int& integerValue ) const
+{
+  bool converted = false;
+  if( mImpl )
+  {
+    if( IsIntegerType( mImpl->type ) )
+    {
+      integerValue = mImpl->integerValue;
+      converted = true;
+    }
+    else if( mImpl->type == FLOAT )
+    {
+      integerValue = static_cast< int >( mImpl->floatValue );
+      converted = true;
+    }
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Vector2& vectorValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == VECTOR2) ) // type cannot change in mImpl so vector is allocated
+  {
+    vectorValue = *(mImpl->vector2Value);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Vector3& vectorValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == VECTOR3) ) // type cannot change in mImpl so vector is allocated
+  {
+    vectorValue = *(mImpl->vector3Value);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Vector4& vectorValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == VECTOR4) ) // type cannot change in mImpl so vector is allocated
+  {
+    vectorValue = *(mImpl->vector4Value);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Matrix3& matrixValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == MATRIX3) ) // type cannot change in mImpl so matrix is allocated
+  {
+    matrixValue = *(mImpl->matrix3Value);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Matrix& matrixValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == MATRIX) ) // type cannot change in mImpl so matrix is allocated
+  {
+    matrixValue = *(mImpl->matrixValue);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Rect<int>& rectValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == RECTANGLE) ) // type cannot change in mImpl so rect is allocated
+  {
+    rectValue = *(mImpl->rectValue);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( AngleAxis& angleAxisValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
+  {
+    mImpl->quaternionValue->ToAxisAngle( angleAxisValue.axis, angleAxisValue.angle );
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Quaternion& quaternionValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == ROTATION) ) // type cannot change in mImpl so quaternion is allocated
+  {
+    quaternionValue = *(mImpl->quaternionValue);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( std::string& stringValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == STRING) ) // type cannot change in mImpl so string is allocated
+  {
+    stringValue.assign( *(mImpl->stringValue) );
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Property::Array& arrayValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
+  {
+    arrayValue = *(mImpl->arrayValue);
+    converted = true;
+  }
+  return converted;
+}
+
+bool Property::Value::Get( Property::Map& mapValue ) const
+{
+  bool converted = false;
+  if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
+  {
+    mapValue = *(mImpl->mapValue);
+    converted = true;
+  }
+  return converted;
+}
+
+Property::Array* Property::Value::GetArray() const
+{
+  Property::Array* array = NULL;
+  if( mImpl && (mImpl->type == ARRAY) ) // type cannot change in mImpl so array is allocated
+  {
+    array = mImpl->arrayValue;
+  }
+  return array;
+}
+
+Property::Map* Property::Value::GetMap() const
+{
+  Property::Map* map = NULL;
+  if( mImpl && (mImpl->type == MAP) ) // type cannot change in mImpl so map is allocated
+  {
+    map = mImpl->mapValue;
+  }
+  return map;
+}
+
+std::ostream& operator<<( std::ostream& stream, const Property::Value& value )
+{
+  if( value.mImpl )
+  {
+    const Property::Value::Impl& impl( *value.mImpl );
+
+    switch( impl.type )
+    {
+      case Dali::Property::BOOLEAN:
+      {
+        stream << impl.integerValue;
+        break;
+      }
+      case Dali::Property::FLOAT:
+      {
+        stream << impl.floatValue;
+        break;
+      }
+      case Dali::Property::INTEGER:
+      {
+         stream << impl.integerValue;
+         break;
+      }
+      case Dali::Property::VECTOR2:
+      {
+        stream << *impl.vector2Value;
+        break;
+      }
+      case Dali::Property::VECTOR3:
+      {
+        stream << *impl.vector3Value;
+        break;
+      }
+      case Dali::Property::VECTOR4:
+      {
+        stream << *impl.vector4Value;
+        break;
+      }
+      case Dali::Property::MATRIX3:
+      {
+        stream << *impl.matrix3Value;
+        break;
+      }
+      case Dali::Property::MATRIX:
+      {
+        stream << *impl.matrixValue;
+        break;
+      }
+      case Dali::Property::RECTANGLE:
+      {
+        stream << *impl.rectValue;
+        break;
+      }
+      case Dali::Property::ROTATION:
+      {
+        stream << *impl.quaternionValue;
+        break;
+      }
+      case Dali::Property::STRING:
+      {
+        stream << *impl.stringValue;
+        break;
+      }
+      case Dali::Property::ARRAY:
+      {
+        stream << "Array containing" << impl.arrayValue->Count() << " elements"; // TODO add ostream<< operator in array
+        break;
+      }
+      case Dali::Property::MAP:
+      {
+        stream << "Map containing " << impl.mapValue->Count() << " elements"; // TODO add ostream<< operator in map
+        break;
+      }
+      case Dali::Property::NONE:
+      {
+        stream << "undefined type";
+        break;
+      }
+    }
+  }
+  else
+  {
+    stream << "empty type";
+  }
+  return stream;
+}
+
+
+} // namespace Dali
diff --git a/dali/public-api/object/property-value.h b/dali/public-api/object/property-value.h
new file mode 100644 (file)
index 0000000..9b5a523
--- /dev/null
@@ -0,0 +1,420 @@
+#ifndef __DALI_PROPERTY_VALUE_H__
+#define __DALI_PROPERTY_VALUE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <iosfwd>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property.h>
+#include <dali/public-api/math/rect.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+struct AngleAxis;
+class Quaternion;
+struct Vector2;
+struct Vector3;
+struct Vector4;
+class Matrix3;
+class Matrix;
+
+/**
+ * @brief A value-type representing a property value.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API Property::Value
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   *
+   * This creates a property with type Property::NONE.
+   * @since_tizen 2.4
+   */
+  Value();
+
+  /**
+   * @brief Create a boolean property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] boolValue A boolean value.
+   */
+  Value( bool boolValue );
+
+  /**
+   * @brief Create an integer property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] integerValue An integer value.
+   */
+  Value( int integerValue );
+
+  /**
+   * @brief Create a float property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] floatValue A floating-point value.
+   */
+  Value( float floatValue );
+
+  /**
+   * @brief Create a Vector2 property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] vectorValue A vector of 2 floating-point values.
+   */
+  Value( const Vector2& vectorValue );
+
+  /**
+   * @brief Create a Vector3 property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] vectorValue A vector of 3 floating-point values.
+   */
+  Value( const Vector3& vectorValue );
+
+  /**
+   * @brief Create a Vector4 property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] vectorValue A vector of 4 floating-point values.
+   */
+  Value( const Vector4& vectorValue );
+
+  /**
+   * @brief Create a Matrix3 property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] matrixValue A matrix of 3x3 floating-point values.
+   */
+  Value( const Matrix3& matrixValue );
+
+  /**
+   * @brief Create a Matrix property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] matrixValue A matrix of 4x4 floating-point values.
+   */
+  Value( const Matrix& matrixValue );
+
+  /**
+   * @brief Create a Vector4 property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] vectorValue A vector of 4 integer values.
+   */
+  Value( const Rect<int>& vectorValue );
+
+  /**
+   * @brief Create an orientation property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] angleAxis An angle-axis representing the rotation.
+   */
+  Value( const AngleAxis& angleAxis );
+
+  /**
+   * @brief Create an orientation property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] quaternion A quaternion representing the rotation.
+   */
+  Value( const Quaternion& quaternion );
+
+  /**
+   * @brief Create an string property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] stringValue A string.
+   */
+  Value( const std::string& stringValue );
+
+  /**
+   * @brief Create an string property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] stringValue A string.
+   */
+  Value( const char* stringValue );
+
+  /**
+   * @brief Create an array property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] arrayValue An array
+   */
+  Value( Property::Array& arrayValue );
+
+  /**
+   * @brief Create a map property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] mapValue An array
+   */
+  Value( Property::Map& mapValue );
+
+  /**
+   * @brief Explicitly set a type and initialize it.
+   *
+   * @since_tizen 2.4
+   * @param [in] type The property value type.
+   */
+  explicit Value( Type type );
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param [in] value The property value to copy.
+   */
+  Value( const Value& value );
+
+  /**
+   * @brief Assign a property value.
+   *
+   * @since_tizen 2.4
+   * @param [in] value The property value to assign from.
+   * @return a reference to this
+   */
+  Value& operator=( const Value& value );
+
+  /**
+   * @brief Non-virtual destructor.
+   *
+   * This class is not a base class.
+   * @since_tizen 2.4
+   */
+  ~Value();
+
+  /**
+   * @brief Query the type of this property value.
+   *
+   * @since_tizen 2.4
+   * @return The type ID.
+   */
+  Type GetType() const;
+
+  /**
+   * @brief Retrieve a specific value.
+   *
+   * Works on a best-effort approach; if value type is not convertible returns a default value of the type
+   *
+   * @since_tizen 2.4
+   * @return A value of type T.
+   */
+  template <typename T>
+  T DALI_INTERNAL Get() const
+  {
+    T temp = T(); // value (zero) initialize
+    Get( temp );
+    return temp;
+  }
+
+  /**
+   * @brief Retrieve a boolean value.
+   *
+   * @since_tizen 2.4
+   * @param [out] boolValue On return, a boolean value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::BOOLEAN.
+   */
+  bool Get( bool& boolValue ) const;
+
+  /**
+   * @brief Retrieve a floating-point value.
+   *
+   * @since_tizen 2.4
+   * @param [out] floatValue On return, a floating-point value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::FLOAT.
+   */
+  bool Get( float& floatValue ) const;
+
+  /**
+   * @brief Retrieve an integer value.
+   *
+   * @since_tizen 2.4
+   * @param [out] integerValue On return, an integer value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::INTEGER.
+   */
+  bool Get( int& integerValue ) const;
+
+  /**
+   * @brief Retrieve an integer rectangle.
+   *
+   * @since_tizen 2.4
+   * @param [out] rect On return, an integer rectangle.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::RECTANGLE.
+   */
+  bool Get( Rect<int>& rect ) const;
+
+  /**
+   * @brief Retrieve a vector value.
+   *
+   * @since_tizen 2.4
+   * @param [out] vectorValue On return, a vector value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::VECTOR2.
+   */
+  bool Get( Vector2& vectorValue ) const;
+
+  /**
+   * @brief Retrieve a vector value.
+   *
+   * @since_tizen 2.4
+   * @param [out] vectorValue On return, a vector value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::VECTOR3.
+   */
+  bool Get( Vector3& vectorValue ) const;
+
+  /**
+   * @brief Retrieve a vector value.
+   *
+   * @since_tizen 2.4
+   * @param [out] vectorValue On return, a vector value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::VECTOR4.
+   */
+  bool Get( Vector4& vectorValue ) const;
+
+  /**
+   * @brief Retrieve a matrix3 value.
+   *
+   * @since_tizen 2.4
+   * @param [out] matrixValue On return, a matrix3 value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::MATRIX3.
+   */
+  bool Get( Matrix3& matrixValue ) const;
+
+  /**
+   * @brief Retrieve a matrix value.
+   *
+   * @since_tizen 2.4
+   * @param [out] matrixValue On return, a matrix value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::MATRIX.
+   */
+  bool Get( Matrix& matrixValue ) const;
+
+  /**
+   * @brief Retrieve an angle-axis value.
+   *
+   * @since_tizen 2.4
+   * @param [out] angleAxisValue On return, a angle-axis value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::ROTATION.
+   */
+  bool Get( AngleAxis& angleAxisValue ) const;
+
+  /**
+   * @brief Retrieve a quaternion value.
+   *
+   * @since_tizen 2.4
+   * @param [out] quaternionValue On return, a quaternion value.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::ROTATION.
+   */
+  bool Get( Quaternion& quaternionValue ) const;
+
+  /**
+   * @brief Retrieve an string property value.
+   *
+   * @since_tizen 2.4
+   * @param [out] stringValue A string.
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::STRING.
+   */
+  bool Get( std::string& stringValue ) const;
+
+  /**
+   * @brief Retrieve an array property value.
+   *
+   * @since_tizen 2.4
+   * @param [out] arrayValue The array as a vector Property Values
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::ARRAY.
+   */
+  bool Get( Property::Array& arrayValue ) const;
+
+  /**
+   * @brief Retrieve an map property value.
+   *
+   * @since_tizen 2.4
+   * @param [out] mapValue The map as vector of string and Property Value pairs
+   * @return true if the value is successfully retrieved, false if the type is not convertible
+   * @pre GetType() returns Property::MAP.
+   */
+  bool Get( Property::Map& mapValue ) const;
+
+  /**
+   * @brief Retrieve the Array API of the Property::Value without copying the contents of the map
+   *
+   * @since_tizen 2.4
+   * @return the Array API of the Property::Value or NULL if not a Property::Array
+   */
+  Property::Array* GetArray() const;
+
+  /**
+   * @brief Retrieve the Map API of the Property::Value without copying the contents of the map
+   *
+   * @since_tizen 2.4
+   * @return  the Map API of the Property::Value or NULL if not a Property::Map
+   */
+  Property::Map* GetMap() const;
+
+  /**
+   * @brief output to stream
+   * @since_tizen 2.4
+   */
+  friend std::ostream& operator<<( std::ostream& ouputStream, const Property::Value& value );
+
+private:
+
+  struct DALI_INTERNAL Impl;
+  Impl* mImpl; ///< Pointer to the implementation
+
+};
+
+/**
+ * @brief Convert the value of the property into a string and append to an output stream.
+ *
+ * @since_tizen 2.4
+ * @param [in] ouputStream The output stream operator.
+ * @param [in] value The value to insert
+ * @return The output stream operator.
+ */
+DALI_IMPORT_API std::ostream& operator<<( std::ostream& ouputStream, const Property::Value& value );
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_VALUE_H__
diff --git a/dali/public-api/object/property.cpp b/dali/public-api/object/property.cpp
new file mode 100644 (file)
index 0000000..cc2386a
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/property.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+
+namespace Dali
+{
+
+const int Property::INVALID_INDEX = -1;
+const int Property::INVALID_COMPONENT_INDEX = -1;
+
+Property::Property(Handle& obj, Property::Index propIndex)
+: object(obj),
+  propertyIndex(propIndex),
+  componentIndex(Property::INVALID_COMPONENT_INDEX)
+{
+}
+
+Property::Property(Handle& obj, Property::Index propIndex, int compIndex)
+: object(obj),
+  propertyIndex(propIndex),
+  componentIndex(compIndex)
+{
+}
+
+Property::Property(Handle& obj, const std::string& propertyName)
+: object(obj),
+  propertyIndex(Property::INVALID_INDEX),
+  componentIndex(Property::INVALID_COMPONENT_INDEX)
+{
+  propertyIndex = object.GetPropertyIndex( propertyName );
+}
+
+Property::Property(Handle& obj, const std::string& propertyName, int compIndex)
+: object(obj),
+  propertyIndex(Property::INVALID_INDEX),
+  componentIndex(compIndex)
+{
+  propertyIndex = object.GetPropertyIndex( propertyName );
+}
+
+Property::~Property()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/property.h b/dali/public-api/object/property.h
new file mode 100644 (file)
index 0000000..9e77534
--- /dev/null
@@ -0,0 +1,168 @@
+#ifndef __DALI_PROPERTY_H__
+#define __DALI_PROPERTY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <string>
+#include <utility>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/vector-wrapper.h>
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class Handle;
+
+/**
+ * @brief An object + property pair.
+ * @since_tizen 2.4
+ */
+struct DALI_IMPORT_API Property
+{
+  /**
+   * @brief A valid property index is zero or greater.
+   * @since_tizen 2.4
+   */
+  typedef int Index;
+
+  static const int INVALID_INDEX; ///< -1 is not a valid property index
+  static const int INVALID_COMPONENT_INDEX; ///< -1 is not a valid property index
+
+  typedef Dali::Vector< Index > IndexContainer; ///< A vector of property indices
+
+  /**
+   * @brief A value-type representing a property value.
+   */
+  class Value;
+
+  /**
+   * @brief A Map of property values.
+   */
+  class Map;
+
+  /**
+   * @brief An Array of property values.
+   */
+  class Array;
+
+  /**
+   * @brief The property types supported.
+   * @since_tizen 2.4
+   */
+  enum Type
+  {
+    NONE,            ///< No type
+
+    BOOLEAN,         ///< A boolean type
+    FLOAT,           ///< A float type
+    INTEGER,         ///< An integer type
+    VECTOR2,         ///< a vector array of size=2 with float precision
+    VECTOR3,         ///< a vector array of size=3 with float precision
+    VECTOR4,         ///< a vector array of size=4 with float precision
+    MATRIX3,         ///< a 3x3 matrix
+    MATRIX,          ///< a 4x4 matrix
+    RECTANGLE,       ///< an integer array of size=4
+    ROTATION,        ///< either a quaternion or an axis angle rotation
+    STRING,          ///< A string type
+    ARRAY,           ///< an array of Property::Value
+    MAP              ///< a string key to Property:value mapping
+  };
+
+  /**
+   * @brief The access mode for custom properties
+   * @since_tizen 2.4
+   */
+  enum AccessMode
+  {
+    READ_ONLY,          ///< if the property is read-only
+    READ_WRITE,         ///< If the property is read/writeable
+    ANIMATABLE,         ///< If the property can be animated or constrained
+    ACCESS_MODE_COUNT   ///< The number of access modes
+  };
+
+
+  /**
+   * @brief Create a Property instance.
+   *
+   * @since_tizen 2.4
+   * @param [in] object A valid handle to the target object.
+   * @param [in] propertyIndex The index of a property.
+   */
+  Property( Handle& object, Property::Index propertyIndex );
+
+
+  /**
+   * @brief Create a Property instance.
+   *
+   * @since_tizen 2.4
+   * @param [in] object A valid handle to the target object.
+   * @param [in] propertyIndex The index of a property.
+   * @param [in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4. -1 for main property (default is -1)
+   */
+  Property( Handle& object, Property::Index propertyIndex, int componentIndex );
+
+  /**
+   * @brief Create a Property instance.
+   *
+   * @since_tizen 2.4
+   * @param [in] object A valid handle to the target object.
+   * @param [in] propertyName The property name.
+   * @note This performs a property index query and is therefore slower than
+   * constructing a Property directly with the index.
+   */
+  Property( Handle& object, const std::string& propertyName );
+
+  /**
+   * @brief Create a Property instance.
+   *
+   * @since_tizen 2.4
+   * @param [in] object A valid handle to the target object.
+   * @param [in] propertyName The property name.
+   * @param [in] componentIndex Index to a sub component of a property, for use with Vector2, Vector3 and Vector4. -1 for main property (default is -1)
+   * @note This performs a property index query and is therefore slower than
+   * constructing a Property directly with the index.
+   */
+  Property( Handle& object, const std::string& propertyName, int componentIndex );
+
+  /**
+   * @brief Non-virtual destructor; Property is not intended as a base class.
+   * @since_tizen 2.4
+   */
+  ~Property();
+
+  Handle& object; ///< A valid handle to the target object.
+
+  Index propertyIndex; ///< The index of a property provided by object.
+
+  int componentIndex; ///< Index of a property sub component, for use with Vector2, Vector3 and Vector4, -1 if using main property
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_PROPERTY_H__
diff --git a/dali/public-api/object/ref-object.cpp b/dali/public-api/object/ref-object.cpp
new file mode 100644 (file)
index 0000000..5805e36
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/ref-object.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+// EXTERNAL INCLUDES
+#include <stdint.h>
+
+namespace Dali
+{
+
+RefObject::RefObject()
+: mCount(0)
+{
+}
+
+RefObject::RefObject(const RefObject&)
+: mCount(0) // Do not copy the reference count
+{
+}
+
+RefObject::~RefObject()
+{
+#ifdef ENABLE_DEBUG
+  if(mCount)
+  {
+    DALI_LOG_ERROR("mCount should be zero, deleting referenced object!");
+  }
+#endif // ENABLE_DEBUG
+}
+
+RefObject& RefObject::operator=(const RefObject&)
+{
+  // Do not copy the reference count
+  return *this;
+}
+
+void RefObject::Reference()
+{
+  // The inline assembly below was tested on an ARMv8 64 bit platform on
+  // 2015-02-06 and found to run in 11.8 nanoseconds, whereas
+  // __sync_add_and_fetch( address, 1 ) required 18.8 nanoseconds.
+  // Including the assembly here produced one fewer assembly instruction than if
+  // it was wrapped in a function and inlined here by the compiler.
+#if defined __aarch64__
+
+  asm volatile(
+  "1:\tldxr  w1, %[address] \n\t"
+      "add   w1, w1, %[one] \n\t"
+      "stxr  w2,  w1, %[address] \n\t"
+      "cbnz  w2,  1b \n\t"
+      // Outputs:
+    : // Q = A memory address with no offset
+      // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
+      [address] "+Q" (mCount)
+      // Inputs:
+    : [one] "Ir" (1)
+      // Clobbers: (explicitly clobber w1 register to hold the loaded value and
+      // register w2 to hold success/fail):
+    : "w1", "w2"
+  );
+
+  // 32 bit ARMv7 version of above:
+  // Better than the code emitted by GCC for __sync_add_and_fetch(), as that
+  // includes two dmb memory barrier instructions: one before and one after the
+  // loop.
+#elif defined __arm__
+
+  asm volatile(
+    "1:\tldrex r1, %[address] \n\t"
+        "add   r1, r1, %[one] \n\t"
+        "strex r2,  r1, %[address] \n\t"
+        "teq   r2,  %[zero] \n\t"
+        "bne   1b \n\t"
+        // Outputs:
+      : [address] "+Q" (mCount)
+        // Inputs:
+      : [zero] "Ir" (0),
+        [one]  "Ir" (1)
+        // Clobbers: (modified registers):
+      : "r1", "r2"
+    );
+
+#else
+
+  // gcc > 4.1 builtin atomic add and fetch:
+  __sync_add_and_fetch( &mCount, 1 );
+
+#endif
+}
+
+void RefObject::Unreference()
+{
+  // The output register:
+  int32_t newValue;
+
+#if defined __aarch64__
+
+  asm volatile(
+  "1:\tldxr   %w[newValue], %[address] \n\t"
+      "sub   %w[newValue], %w[newValue], %[one] \n\t"
+      "stxr  w2,  %w[newValue], %[address] \n\t"
+      "cbnz  w2,  1b \n\t"
+    // Outputs:
+  : [newValue] "=&r" (newValue),
+    // Q = A memory address with no offset
+    // ( https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html#Machine-Constraints )
+    [address] "+Q" (mCount)
+    // Inputs:
+  : [one]  "Ir" (1)
+    // Clobbered: I.e., stuff that is modified.
+  : "w2"
+  );
+
+#elif defined __arm__
+
+  asm volatile(
+  "1:\tldrex %[newValue], %[address] \n\t"
+      "sub   %[newValue], %[newValue], %[one] \n\t"
+      "strex r2,  %[newValue], %[address] \n\t"
+      "teq   r2, %[zero] \n\t"
+      "bne   1b \n\t"
+    // Outputs:
+  : [newValue] "=&r" (newValue),
+    [address] "+Q" (mCount)
+    // Inputs:
+    : [zero] "Ir" (0),
+      [one]  "Ir" (1)
+    // Clobbered:
+  : "r2"
+  );
+
+#else
+
+  // gcc > 4.1 builtin atomic subtract and fetch (--mCount; return mCount)
+  newValue = __sync_sub_and_fetch( &mCount, 1 );
+
+#endif
+
+  if( newValue == 0 )
+  {
+    delete this;
+  }
+}
+
+int RefObject::ReferenceCount()
+{
+  return mCount;
+}
+
+} // namespace Dali
+
+
diff --git a/dali/public-api/object/ref-object.h b/dali/public-api/object/ref-object.h
new file mode 100644 (file)
index 0000000..5df0a48
--- /dev/null
@@ -0,0 +1,112 @@
+#ifndef __DALI_REF_OBJECT_H__
+#define __DALI_REF_OBJECT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/intrusive-ptr.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class Value;
+
+/**
+ * @brief Base class for reference counted objects.
+ *
+ * Typically this should be used with an instrusive pointer,
+ * instead of calling Reference() and Unreference() methods directly.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API RefObject
+{
+public:
+
+  /**
+   * @brief Increment the object's reference count.
+   * @since_tizen 2.4
+   */
+  void Reference();
+
+  /**
+   * @brief Decrement the object's reference count.
+   *
+   * When the reference count drops to zero, the object will self-destruct.
+   * @since_tizen 2.4
+   */
+  void Unreference();
+
+  /**
+   * @brief Retrieve the object's reference count.
+   *
+   * @since_tizen 2.4
+   * @return The reference count
+   */
+  int ReferenceCount();
+
+protected:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  RefObject();
+
+  /**
+   * @brief RefObject is intended as a base class.
+   *
+   * A RefObject may only be deleted when its reference count is zero.
+   * @since_tizen 2.4
+   */
+  virtual ~RefObject();
+
+  /**
+   * @brief Copy constructor.
+   *
+   * The newly copied object will have a reference count of zero.
+   * @since_tizen 2.4
+   * @param[in] rhs The object to copy
+   */
+  RefObject(const RefObject& rhs);
+
+  /**
+   * @brief Assignment operator.
+   *
+   * The newly copied object will have a reference count of zero.
+   * @since_tizen 2.4
+   * @param[in] rhs The object to copy
+   * @return a reference to this
+   */
+  RefObject& operator=(const RefObject& rhs);
+
+private:
+
+  volatile int mCount; ///< Reference count
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_REF_OBJECT_H__
diff --git a/dali/public-api/object/type-info.cpp b/dali/public-api/object/type-info.cpp
new file mode 100644 (file)
index 0000000..03d96dc
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/type-info.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/common/type-info-impl.h>
+
+namespace Dali
+{
+
+TypeInfo::TypeInfo()
+{
+}
+
+TypeInfo::~TypeInfo()
+{
+}
+
+TypeInfo::TypeInfo(const TypeInfo& copy)
+: BaseHandle(copy)
+{
+}
+
+TypeInfo& TypeInfo::operator=(const TypeInfo& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+const std::string& TypeInfo::GetName() const
+{
+  return GetImplementation(*this).GetName();
+}
+
+const std::string& TypeInfo::GetBaseName() const
+{
+  return GetImplementation(*this).GetBaseName();
+}
+
+BaseHandle TypeInfo::CreateInstance() const
+{
+  return GetImplementation(*this).CreateInstance();
+}
+
+TypeInfo::CreateFunction TypeInfo::GetCreator() const
+{
+  return GetImplementation(*this).GetCreator();
+}
+
+size_t TypeInfo::GetActionCount() const
+{
+  return GetImplementation(*this).GetActionCount();
+}
+
+std::string TypeInfo::GetActionName(size_t index)
+{
+  return GetImplementation(*this).GetActionName(index);
+}
+
+size_t TypeInfo::GetSignalCount() const
+{
+  return GetImplementation(*this).GetSignalCount();
+}
+
+std::string TypeInfo::GetSignalName(size_t index)
+{
+  return GetImplementation(*this).GetSignalName(index);
+}
+
+size_t TypeInfo::GetPropertyCount() const
+{
+  return GetImplementation(*this).GetPropertyCount();
+}
+
+void TypeInfo::GetPropertyIndices( Property::IndexContainer& indices ) const
+{
+  indices.Clear(); // We do not want to clear the container if called internally, so only clear here
+  GetImplementation(*this).GetPropertyIndices( indices );
+}
+
+const std::string& TypeInfo::GetPropertyName( Property::Index index ) const
+{
+  return GetImplementation(*this).GetPropertyName( index );
+}
+
+TypeInfo::TypeInfo(Internal::TypeInfo* internal)
+: BaseHandle(internal)
+{
+}
+
+} // namespace Dali
+
diff --git a/dali/public-api/object/type-info.h b/dali/public-api/object/type-info.h
new file mode 100644 (file)
index 0000000..ceb4ade
--- /dev/null
@@ -0,0 +1,235 @@
+#ifndef __DALI_TYPE_INFO_H__
+#define __DALI_TYPE_INFO_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/common/vector-wrapper.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+class ConnectionTrackerInterface;
+class FunctorDelegate;
+
+namespace Internal DALI_INTERNAL
+{
+  class TypeInfo;
+};
+
+/**
+ * @brief TypeInfo class for instantiation of registered types and introspection of
+ * their actions and signals.
+ *
+ * See TypeRegistry for methods of type registration and TypeInfo retrieval.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API TypeInfo : public BaseHandle
+{
+public:
+  typedef BaseHandle (*CreateFunction)(); ///< Function signature for creating an instance of the associated object type.
+
+  typedef bool (*ActionFunction)(BaseObject*, const std::string&, const Property::Map&); ///< Function signature for creating scriptable actions
+
+  /**
+   * @brief Connects a callback function with the object's signals.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object providing the signal.
+   * @param[in] tracker Used to disconnect the signal.
+   * @param[in] signalName The signal to connect to.
+   * @param[in] functor A newly allocated FunctorDelegate.
+   * @return True if the signal was connected.
+   * @post If a signal was connected, ownership of functor was passed to CallbackBase. Otherwise the caller is responsible for deleting the unused functor.
+   */
+  typedef bool (*SignalConnectorFunction)(BaseObject* object, ConnectionTrackerInterface* tracker, const std::string& signalName, FunctorDelegate* functor);
+
+  /**
+   * @brief Callback to set an event-thread only property.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object whose property should be set.
+   * @param[in] index The index of the property being set.
+   * @param[in] value The new value of the property for the object specified.
+   * @see PropertyRegistration.
+   */
+  typedef void (*SetPropertyFunction)( BaseObject* object, Property::Index index, const Property::Value& value );
+
+  /**
+   * @brief Callback to get the value of an event-thread only property.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object whose property value is required.
+   * @param[in] index The index of the property required.
+   * @return The current value of the property for the object specified.
+   * @see PropertyRegistration.
+   */
+  typedef Property::Value (*GetPropertyFunction)( BaseObject* object, Property::Index index );
+
+  /**
+   * @brief Allows the creation of an empty TypeInfo handle.
+   * @since_tizen 2.4
+   */
+  TypeInfo();
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~TypeInfo();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  TypeInfo(const TypeInfo& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  TypeInfo& operator=(const TypeInfo& rhs);
+
+  /**
+   * @brief Retrieve the type name for this type.
+   *
+   * @since_tizen 2.4
+   * @return string name
+   */
+  const std::string& GetName() const;
+
+  /**
+   * @brief Retrieve the base type name for this type.
+   *
+   * @since_tizen 2.4
+   * @return string of base name
+   */
+  const std::string& GetBaseName() const;
+
+  /**
+   * @brief Create an object from this type.
+   *
+   * @since_tizen 2.4
+   * @return the BaseHandle for the newly created object
+   */
+  BaseHandle CreateInstance() const;
+
+  /**
+   * @brief Retrieve the creator function for this type.
+   *
+   * @since_tizen 2.4
+   * @return the creator function
+   */
+  CreateFunction GetCreator() const;
+
+  /**
+   * @brief Retrieve the number of actions for this type.
+   *
+   * @since_tizen 2.4
+   * @return The count
+   */
+  size_t GetActionCount() const;
+
+  /**
+   * @brief Retrieve the action name for the index.
+   *
+   * @since_tizen 2.4
+   * @param[in] index Index to lookup
+   * @return action name or empty string where index is invalid
+   */
+  std::string GetActionName(size_t index);
+
+  /**
+   * @brief Retrieve the number of signals for this type.
+   *
+   * @since_tizen 2.4
+   * @return The count
+   */
+  size_t GetSignalCount() const;
+
+  /**
+   * @brief Retrieve the signal name for the index.
+   *
+   * @since_tizen 2.4
+   * @param[in] index Index to lookup
+   * @return signal name or empty string where index is invalid
+   */
+  std::string GetSignalName(size_t index);
+
+  /**
+   * @brief Retrieve the number of event side type registered properties for this type.
+   *
+   * This count does not include all properties
+   * @since_tizen 2.4
+   * @return The count
+   */
+  size_t GetPropertyCount() const;
+
+  // Properties
+
+  /**
+   * @brief Retrieve all the property indices for this type.
+   *
+   * @since_tizen 2.4
+   * @param[out] indices Container of property indices
+   * @note The container will be cleared
+   */
+  void GetPropertyIndices( Property::IndexContainer& indices ) const;
+
+  /**
+   * @brief Given a property index, retrieve the property name associated with it.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The property index.
+   * @return The name of the property at the given index.
+   * @exception DaliException If index is not valid.
+   *
+   */
+  const std::string& GetPropertyName( Property::Index index ) const;
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali Get() method.
+   *
+   * @since_tizen 2.4
+   * @param [in] typeInfo A pointer to a Dali resource
+   */
+  explicit DALI_INTERNAL TypeInfo(Internal::TypeInfo* typeInfo);
+
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_TYPE_INFO_H__
diff --git a/dali/public-api/object/type-registry.cpp b/dali/public-api/object/type-registry.cpp
new file mode 100644 (file)
index 0000000..ac1f2fb
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/object/type-registry.h>
+
+// EXTERNAL INCLUDES
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/internal/event/common/type-registry-impl.h>
+
+namespace Dali
+{
+
+TypeRegistry::TypeRegistry()
+{
+}
+
+TypeRegistry::~TypeRegistry()
+{
+}
+
+TypeRegistry::TypeRegistry(const TypeRegistry& copy)
+: BaseHandle(copy)
+{
+}
+
+TypeRegistry& TypeRegistry::operator=(const TypeRegistry& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+TypeRegistry TypeRegistry::Get()
+{
+  return TypeRegistry(Internal::TypeRegistry::Get());
+}
+
+Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::string &uniqueTypeName )
+{
+  return GetImplementation(*this).GetTypeInfo( uniqueTypeName );
+}
+
+Dali::TypeInfo TypeRegistry::GetTypeInfo( const std::type_info& registerType )
+{
+  return GetImplementation(*this).GetTypeInfo( registerType );
+}
+
+size_t TypeRegistry::GetTypeNameCount() const
+{
+  return GetImplementation(*this).GetTypeNameCount();
+}
+
+std::string TypeRegistry::GetTypeName(size_t index) const
+{
+  return GetImplementation(*this).GetTypeName(index);
+}
+
+TypeRegistry::TypeRegistry(Internal::TypeRegistry* internal)
+: BaseHandle(internal)
+{
+}
+
+TypeRegistration::TypeRegistration( const std::type_info& registerType, const std::type_info& baseType,
+                                    TypeInfo::CreateFunction f )
+  : mReference(Internal::TypeRegistry::Get())
+{
+  Internal::TypeRegistry *impl = Internal::TypeRegistry::Get();
+
+  if( impl->Register( registerType, baseType, f, false ) )
+  {
+    mName = impl->RegistrationName( registerType );
+  }
+}
+
+TypeRegistration::TypeRegistration( const std::type_info& registerType, const std::type_info& baseType,
+                                    TypeInfo::CreateFunction f, bool callCreateOnInit )
+  : mReference(Internal::TypeRegistry::Get())
+{
+  Internal::TypeRegistry *impl = Internal::TypeRegistry::Get();
+
+  if( impl->Register( registerType, baseType, f, callCreateOnInit ) )
+  {
+    mName = impl->RegistrationName( registerType );
+  }
+}
+
+TypeRegistration::TypeRegistration( const std::string& name, const std::type_info& baseType,
+                                    TypeInfo::CreateFunction f )
+  : mReference(Internal::TypeRegistry::Get())
+{
+  Internal::TypeRegistry *impl = Internal::TypeRegistry::Get();
+
+  if( impl->Register( name, baseType, f, false ) )
+  {
+    mName = name;
+  }
+}
+
+
+const std::string TypeRegistration::RegisteredName() const
+{
+  return mName;
+}
+
+SignalConnectorType::SignalConnectorType( TypeRegistration& typeRegistration, const std::string& name, TypeInfo::SignalConnectorFunction func )
+{
+  Internal::TypeRegistry::Get()->RegisterSignal( typeRegistration, name, func );
+}
+
+TypeAction::TypeAction( TypeRegistration &registered, const std::string &name, TypeInfo::ActionFunction f)
+{
+  Internal::TypeRegistry::Get()->RegisterAction( registered, name, f );
+}
+
+PropertyRegistration::PropertyRegistration( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type, TypeInfo::SetPropertyFunction setFunc, TypeInfo::GetPropertyFunction getFunc )
+{
+  DALI_ASSERT_ALWAYS( ( index >= PROPERTY_REGISTRATION_START_INDEX ) && ( index <= PROPERTY_REGISTRATION_MAX_INDEX ) );
+
+  Internal::TypeRegistry::Get()->RegisterProperty( registered, name, index, type, setFunc, getFunc );
+}
+
+AnimatablePropertyRegistration::AnimatablePropertyRegistration( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type )
+{
+  DALI_ASSERT_ALWAYS( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) );
+
+  Internal::TypeRegistry::Get()->RegisterAnimatableProperty( registered, name, index, type );
+}
+
+AnimatablePropertyComponentRegistration::AnimatablePropertyComponentRegistration( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex)
+{
+  DALI_ASSERT_ALWAYS( ( index >= ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX ) && ( index <= ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX ) );
+
+  Internal::TypeRegistry::Get()->RegisterAnimatablePropertyComponent( registered, name, index, baseIndex, componentIndex );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/object/type-registry.h b/dali/public-api/object/type-registry.h
new file mode 100644 (file)
index 0000000..22e66ab
--- /dev/null
@@ -0,0 +1,373 @@
+#ifndef __DALI_TYPE_REGISTRY_H__
+#define __DALI_TYPE_REGISTRY_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+
+// EXTERNAL INCLUDES
+#include <typeinfo>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+#include <dali/public-api/object/type-info.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_object
+ * @{
+ */
+
+namespace Internal DALI_INTERNAL
+{
+class TypeRegistry;
+}
+
+/**
+ * @brief The TypeRegistry allows registration of type instance creation functions.
+ *
+ * These can then be created later by name and down cast to the appropriate type.
+ *
+ * Usage: (Registering)
+ *
+ * In my-actor.cpp
+ * @code
+ * // Note: object construction in namespace scope is defined in a translation unit as being
+ * //       in appearance order (C++ standard 3.6/2). So TypeRegistration is declared first in
+ * //       the cpp file below. Signal, action and property declarations follow in any order.
+ * namespace
+ * {
+ *   TypeRegistration myActorType(typeid(MyActor), typeid(Actor), CreateMyActor );
+ *
+ *   SignalConnectorType( myActorType, "highlighted", ConnectSignalForMyActor );
+ *   TypeAction( myActorType, "open", DoMyActorAction );
+ *   TypeAction( myActorType, "close", DoMyActorAction );
+ *   PropertyRegistration( myActorType, "status", PropertyRegistration::START_INDEX, Property::BOOLEAN, SetPropertyFunction, GetPropertyFunction );
+ * }
+ * @endcode
+ *
+ * Usage: (Creation)
+ *
+ * @code
+ *   TypeRegistry::TypeInfo type = TypeRegistry::Get().GetTypeInfo("MyActor");
+ *   MyActor a = MyActor::DownCast(type.CreateInstance());
+ *   if(a)
+ *   {
+ *     ...
+ *   }
+ * @endcode
+ *
+ * CustomActor
+ *
+ *  Actors that inherit from the CustomActor framework must ensure the implementation
+ *  class has an identical name to the Actor class. This is to ensure the class can be
+ *  found at runtime for signals and actions. Otherwise these will silently fail.
+ *
+ *  As namespaces are discarded the convention is to use a namespace ie
+ *
+ *    'class MyActor {}; namespace Internal { class MyActor {}; }'
+ *
+ *  Warning: this arrangement will silently fail
+ *
+ *    'class MyActor {}; class MyActorImpl {};'
+ *
+ * Naming Conventions
+ *
+ *   Signal and action names follow properties and are by convention lower case hyphen
+ *   separated ie 'next-page'. This maintains consistency with the scripted interface.
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API TypeRegistry : public BaseHandle
+{
+public:
+  /**
+   * @brief Get Type Registry handle.
+   *
+   * @since_tizen 2.4
+   * @return TypeRegistry handle
+   */
+  static TypeRegistry Get();
+
+  /**
+   * @brief Allows the creation of an empty typeRegistry handle.
+   * @since_tizen 2.4
+   */
+  TypeRegistry();
+
+  /**
+   * @brief destructor.
+   * @since_tizen 2.4
+   */
+  ~TypeRegistry();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  TypeRegistry(const TypeRegistry& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  TypeRegistry& operator=(const TypeRegistry& rhs);
+
+  /**
+   * @brief Get TypeInfo for a registered type.
+   *
+   * @since_tizen 2.4
+   * @param [in] uniqueTypeName A unique type name
+   * @return TypeInfo if the type exists otherwise an empty handle
+   */
+  TypeInfo GetTypeInfo( const std::string &uniqueTypeName );
+
+  /**
+   * @brief Get TypeInfo for a registered type.
+   *
+   * @since_tizen 2.4
+   * @param [in] registerType The registered type info
+   * @return TypeInfo if the type exists otherwise an empty handle
+   */
+  TypeInfo GetTypeInfo( const std::type_info& registerType );
+
+  /**
+   * @brief Get type name count.
+   *
+   * @since_tizen 2.4
+   * @return The count
+   */
+  size_t GetTypeNameCount() const;
+
+  /**
+   * @brief Get type names by index.
+   *
+   * @since_tizen 2.4
+   * @return The type name or an empty string when index is not valid
+   */
+  std::string GetTypeName(size_t index) const;
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali Get() method.
+   *
+   * @since_tizen 2.4
+   * @param [in] typeRegistry A pointer to a Dali resource
+   */
+  explicit DALI_INTERNAL TypeRegistry(Internal::TypeRegistry*typeRegistry);
+};
+
+/**
+ * @brief Register a type from type info.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API TypeRegistration
+{
+public:
+  /**
+   * @brief Constructor registers the type creation function.
+   *
+   * @since_tizen 2.4
+   * @param [in] registerType the type info for the type to be registered
+   * @param [in] baseType the base type info of registerType
+   * @param [in] f registerType instance creation function
+   */
+  TypeRegistration( const std::type_info& registerType, const std::type_info& baseType,
+                    TypeInfo::CreateFunction f );
+
+  /**
+   * @brief Constructor registers the type creation function.
+   *
+   * @since_tizen 2.4
+   * @param [in] registerType the type info for the type to be registered
+   * @param [in] baseType the base type info of registerType
+   * @param [in] f registerType instance creation function
+   * @param [in] callCreateOnInit If true the creation function is called as part of Dali initialisation
+   */
+  TypeRegistration( const std::type_info& registerType, const std::type_info& baseType,
+                    TypeInfo::CreateFunction f, bool callCreateOnInit );
+
+  /**
+   * @brief Constructor registers the type creation function for a named class or type.
+   *
+   * This allows types to be created dynamically from script. The name must be
+   * unique for successful registration.
+   * @since_tizen 2.4
+   * @param [in] name the name of the type to be registered
+   * @param [in] baseType the base type info of registerType
+   * @param [in] f registerType instance creation function
+   */
+  TypeRegistration( const std::string& name, const std::type_info& baseType,
+                    TypeInfo::CreateFunction f );
+
+  /**
+   * @brief The name the type is registered under (derived from type_info).
+   *
+   * @since_tizen 2.4
+   * @return the registered name or empty if unregistered
+   */
+  const std::string RegisteredName() const;
+
+private:
+  TypeRegistry mReference; ///< Reference to the type registry
+  std::string mName;       ///< Name of the type
+};
+
+/**
+ * @brief Register a signal connector function to a registered type.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API SignalConnectorType
+{
+public:
+  /**
+   * @brief Constructor registers the type creation function.
+   *
+   * @since_tizen 2.4
+   * @param [in] typeRegistration The TypeRegistration object
+   * @param [in] name The signal name
+   * @param [in] func The signal connector function
+   */
+  SignalConnectorType( TypeRegistration& typeRegistration, const std::string& name, TypeInfo::SignalConnectorFunction func );
+};
+
+/**
+ * @brief Register an action function.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API TypeAction
+{
+public:
+  /**
+   * @brief Constructor registers the type creation function.
+   *
+   * @since_tizen 2.4
+   * @param [in] registered The TypeRegistration object
+   * @param [in] name The action name
+   * @param [in] f The action function
+   */
+  TypeAction( TypeRegistration &registered, const std::string &name, TypeInfo::ActionFunction f);
+};
+
+/**
+ * @brief Register a property for the given type.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API PropertyRegistration
+{
+public:
+
+  /**
+   * @brief This constructor registers the property with the registered type.
+   *
+   * This constructor is for event-thread only properties where the
+   * value of the property can be retrieved and set via specified
+   * functions.
+   *
+   * Functions of the following type may be used for setFunc and getFunc respectively:
+   * @code
+   *   void SetProperty( BaseObject* object, Property::Index index, const Property::Value& value );
+   *   Property::Value GetProperty( BaseObject* object, Property::Index index );
+   * @endcode
+   *
+   * @since_tizen 2.4
+   * @param [in] registered The TypeRegistration object
+   * @param [in] name The name of the property
+   * @param [in] index The property index. Must be a value between PROPERTY_REGISTRATION_START_INDEX and PROPERTY_REGISTRATION_MAX_INDEX inclusive.
+   * @param [in] type The property value type.
+   * @param [in] setFunc The function to call when setting the property. If NULL, then the property becomes read-only.
+   * @param [in] getFunc The function to call to retrieve the current value of the property. MUST be provided.
+   *
+   * @pre "registered" must be registered with the TypeRegistry.
+   * @note The "index" value must be between START_INDEX and MAX_INDEX inclusive.
+   * @note If "setFunc" is NULL, then the property becomes a read-only property.
+   * @note "getFunc" MUST be provided
+   *
+   */
+  PropertyRegistration( TypeRegistration& registered,
+                        const std::string& name, Property::Index index, Property::Type type,
+                        TypeInfo::SetPropertyFunction setFunc, TypeInfo::GetPropertyFunction getFunc );
+};
+
+/**
+ * @brief Register an animatable property for the given type.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API AnimatablePropertyRegistration
+{
+public:
+
+  /**
+   * @brief This constructor registers the animatable property with the registered type.
+   *
+   * This constructor is for scene-graph only properties where the
+   * value of the property can be retrieved and set via specified
+   * functions.
+   *
+   * @since_tizen 2.4
+   * @param [in] registered The TypeRegistration object
+   * @param [in] name The name of the property
+   * @param [in] index The property index. Must be a value between ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX and ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX inclusive.
+   * @param [in] type The property value type.
+   *
+   * @pre "registered" must be registered with the TypeRegistry.
+   */
+  AnimatablePropertyRegistration( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Type type );
+};
+
+/**
+ * @brief Register a component of animatable property for the given component index.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API AnimatablePropertyComponentRegistration
+{
+public:
+
+  /**
+   * @brief This constructor registers a component of an animatable property where
+   * the base animatable property must be a property that supports property component
+   * (i.e. Vector2, Vector3 or Vector4) and the base animatable property must have
+   * been registered.
+   *
+   * This constructor is for a component of scene-graph only properties where the
+   * value of the property can be retrieved and set via specified functions.
+   *
+   * @since_tizen 2.4
+   * @param [in] registered The TypeRegistration object
+   * @param [in] name The name of the component
+   * @param [in] index The property index. Must be a value between ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX and ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX inclusive.
+   * @param [in] baseIndex The index of the base animatable property. Must be a value between ANIMATABLE_PROPERTY_REGISTRATION_START_INDEX and ANIMATABLE_PROPERTY_REGISTRATION_MAX_INDEX inclusive.
+   * @param [in] componentIndex The index of the component (e.g. 0 for the x component of a Vector2 property and 1 for the y component of a Vector2 property).
+   *
+   * @pre "registered" must be registered with the TypeRegistry.
+   */
+  AnimatablePropertyComponentRegistration( TypeRegistration& registered, const std::string& name, Property::Index index, Property::Index baseIndex, unsigned int componentIndex );
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // header
diff --git a/dali/public-api/render-tasks/render-task-list.cpp b/dali/public-api/render-tasks/render-task-list.cpp
new file mode 100644 (file)
index 0000000..7bd754b
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/render-tasks/render-task-list.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/render-tasks/render-task-list-impl.h>
+
+namespace Dali
+{
+
+RenderTaskList::RenderTaskList()
+{
+}
+
+RenderTaskList RenderTaskList::DownCast( BaseHandle handle )
+{
+  return RenderTaskList( dynamic_cast<Dali::Internal::RenderTaskList*>( handle.GetObjectPtr() ) );
+}
+
+RenderTaskList::~RenderTaskList()
+{
+}
+
+RenderTaskList::RenderTaskList(const RenderTaskList& handle)
+: BaseHandle(handle)
+{
+}
+
+RenderTaskList& RenderTaskList::operator=(const RenderTaskList& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+RenderTask RenderTaskList::CreateTask()
+{
+  return GetImplementation(*this).CreateTask();
+}
+
+void RenderTaskList::RemoveTask( RenderTask task )
+{
+  GetImplementation(*this).RemoveTask( task );
+}
+
+unsigned int RenderTaskList::GetTaskCount() const
+{
+  return GetImplementation(*this).GetTaskCount();
+}
+
+RenderTask RenderTaskList::GetTask( unsigned int index ) const
+{
+  return GetImplementation(*this).GetTask( index );
+}
+
+RenderTaskList::RenderTaskList( Internal::RenderTaskList* internal )
+: BaseHandle( internal )
+{
+}
+
+} // namespace Dali
+
diff --git a/dali/public-api/render-tasks/render-task-list.h b/dali/public-api/render-tasks/render-task-list.h
new file mode 100644 (file)
index 0000000..97000b2
--- /dev/null
@@ -0,0 +1,143 @@
+#ifndef __DALI_RENDER_TASK_LIST_H__
+#define __DALI_RENDER_TASK_LIST_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/base-handle.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+class RenderTask;
+
+namespace Internal DALI_INTERNAL
+{
+class RenderTaskList;
+}
+
+/**
+ * @brief An ordered list of Dali::RenderTask%s.
+ *
+ * These tasks describe how the Dali scene should be rendered; @see Dali::RenderTask for more details.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API RenderTaskList : public BaseHandle
+{
+public:
+
+  /**
+   * @brief Create an empty RenderTaskList handle.
+   *
+   * This can be initialised with Stage::GetRenderTaskList().
+   * @since_tizen 2.4
+   */
+  RenderTaskList();
+
+  /**
+   * @brief Downcast a handle to RenderTaskList handle.
+   *
+   * If handle points to a RenderTaskList the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle A handle to an object.
+   * @return A handle to a RenderTaskList or an uninitialized handle.
+   */
+  static RenderTaskList DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~RenderTaskList();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  RenderTaskList(const RenderTaskList& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  RenderTaskList& operator=(const RenderTaskList& rhs);
+
+  /**
+   * @brief Create a new RenderTask.
+   *
+   * This will be appended to the list of render-tasks.
+   * @since_tizen 2.4
+   * @return A valid handle to a new RenderTask.
+   */
+  RenderTask CreateTask();
+
+  /**
+   * @brief Remove a RenderTask from the list of render-tasks.
+   * @since_tizen 2.4
+   * @param[in] task The render-task to remove.
+   */
+  void RemoveTask( RenderTask task );
+
+  /**
+   * @brief Query the number of render-tasks in the list.
+   *
+   * This is ordered i.e. the task with index 0 is the first to be processed each frame.
+   * @since_tizen 2.4
+   * @return The number of render-tasks.
+   */
+  unsigned int GetTaskCount() const;
+
+  /**
+   * @brief Retrieve a render-task.
+   *
+   * @since_tizen 2.4
+   * @param[in] index The index of the render task to retrieve
+   * @return A handle to the render-task.
+   * @pre index should be in range i.e. less than GetTaskCount().
+   */
+  RenderTask GetTask( unsigned int index ) const;
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods
+   * @since_tizen 2.4
+   * @param [in] renderTask A pointer to a newly allocated render-task
+   */
+  explicit DALI_INTERNAL RenderTaskList( Internal::RenderTaskList* renderTask );
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif //__DALI_RENDER_TASK_LIST_H__
diff --git a/dali/public-api/render-tasks/render-task.cpp b/dali/public-api/render-tasks/render-task.cpp
new file mode 100644 (file)
index 0000000..51903a7
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/render-tasks/render-task.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/constants.h>
+#include <dali/internal/event/actors/actor-impl.h>
+#include <dali/internal/event/actors/camera-actor-impl.h>
+#include <dali/internal/event/render-tasks/render-task-impl.h>
+
+namespace Dali
+{
+
+static bool DefaultScreenToFrameBufferFunction( Vector2& coordinates )
+{
+  return false;
+}
+
+static bool FullScreenFrameBufferFunction( Vector2& coordinates )
+{
+  // Don't need to modify frameBufferCoords
+  return true;
+}
+
+RenderTask::ConstScreenToFrameBufferFunction RenderTask::DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION = DefaultScreenToFrameBufferFunction;
+RenderTask::ConstScreenToFrameBufferFunction RenderTask::FULLSCREEN_FRAMEBUFFER_FUNCTION        = FullScreenFrameBufferFunction;
+
+const bool         RenderTask::DEFAULT_EXCLUSIVE     = false;
+const bool         RenderTask::DEFAULT_INPUT_ENABLED = true;
+const Vector4      RenderTask::DEFAULT_CLEAR_COLOR   = Vector4( 0.0f, 0.0f, 0.0f, 1.0f ); // cannot use Color::Black because it may or may not be initialized yet
+const bool         RenderTask::DEFAULT_CLEAR_ENABLED = false;
+const bool         RenderTask::DEFAULT_CULL_MODE     = true;
+const unsigned int RenderTask::DEFAULT_REFRESH_RATE  = REFRESH_ALWAYS;
+
+RenderTask::RenderTask()
+{
+}
+
+RenderTask RenderTask::DownCast( BaseHandle handle )
+{
+  return RenderTask( dynamic_cast<Dali::Internal::RenderTask*>( handle.GetObjectPtr() ) );
+}
+
+RenderTask::~RenderTask()
+{
+}
+
+RenderTask::RenderTask(const RenderTask& handle)
+: Handle(handle)
+{
+}
+
+RenderTask& RenderTask::operator=(const RenderTask& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+void RenderTask::SetSourceActor( Actor actor )
+{
+  // NULL handle is allowed
+  Internal::Actor* actorImpl( NULL );
+  if ( actor )
+  {
+    actorImpl = &GetImplementation( actor );
+  }
+
+  GetImplementation(*this).SetSourceActor( actorImpl );
+}
+
+Actor RenderTask::GetSourceActor() const
+{
+  return Dali::Actor(GetImplementation(*this).GetSourceActor());
+}
+
+void RenderTask::SetExclusive( bool exclusive )
+{
+  GetImplementation(*this).SetExclusive( exclusive );
+}
+
+bool RenderTask::IsExclusive() const
+{
+  return GetImplementation(*this).IsExclusive();
+}
+
+void RenderTask::SetCameraActor( CameraActor cameraActor )
+{
+  // NULL handle is allowed
+  Internal::CameraActor* actorImpl( NULL );
+  if ( cameraActor )
+  {
+    actorImpl = &GetImplementation( cameraActor );
+  }
+
+  GetImplementation(*this).SetCameraActor( actorImpl );
+}
+
+CameraActor RenderTask::GetCameraActor() const
+{
+  return Dali::CameraActor(GetImplementation(*this).GetCameraActor());
+}
+
+void RenderTask::SetTargetFrameBuffer( FrameBufferImage frameBuffer )
+{
+  GetImplementation(*this).SetTargetFrameBuffer( frameBuffer );
+}
+
+FrameBufferImage RenderTask::GetTargetFrameBuffer() const
+{
+  return GetImplementation(*this).GetTargetFrameBuffer();
+}
+
+void RenderTask::SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction )
+{
+  GetImplementation(*this).SetScreenToFrameBufferFunction( conversionFunction );
+}
+
+RenderTask::ScreenToFrameBufferFunction RenderTask::GetScreenToFrameBufferFunction() const
+{
+  return GetImplementation(*this).GetScreenToFrameBufferFunction();
+}
+
+void RenderTask::SetScreenToFrameBufferMappingActor( Dali::Actor mappingActor )
+{
+  // NULL handle is allowed
+  Internal::Actor* actorImpl( NULL );
+  if ( mappingActor )
+  {
+    actorImpl = &GetImplementation( mappingActor );
+  }
+
+  GetImplementation(*this).SetScreenToFrameBufferMappingActor( actorImpl );
+}
+
+Dali::Actor RenderTask::GetScreenToFrameBufferMappingActor() const
+{
+  return Dali::Actor(GetImplementation(*this).GetScreenToFrameBufferMappingActor());
+}
+
+void RenderTask::SetViewportPosition( Vector2 position )
+{
+  GetImplementation(*this).SetViewportPosition( position );
+}
+
+Vector2 RenderTask::GetCurrentViewportPosition() const
+{
+  return GetImplementation(*this).GetCurrentViewportPosition();
+}
+
+void RenderTask::SetViewportSize( Vector2 size )
+{
+  GetImplementation(*this).SetViewportSize( size );
+}
+
+Vector2 RenderTask::GetCurrentViewportSize() const
+{
+  return GetImplementation(*this).GetCurrentViewportSize();
+}
+
+void RenderTask::SetViewport( Viewport viewport )
+{
+  GetImplementation(*this).SetViewport( viewport );
+}
+
+Viewport RenderTask::GetViewport() const
+{
+  Viewport result;
+  GetImplementation(*this).GetViewport( result );
+  return result;
+}
+
+void RenderTask::SetClearColor( const Vector4& color )
+{
+  GetImplementation(*this).SetClearColor( color );
+}
+
+Vector4 RenderTask::GetClearColor() const
+{
+  return GetImplementation(*this).GetClearColor();
+}
+
+void RenderTask::SetClearEnabled( bool enabled )
+{
+  GetImplementation(*this).SetClearEnabled( enabled );
+}
+
+bool RenderTask::GetClearEnabled() const
+{
+  return GetImplementation(*this).GetClearEnabled();
+}
+
+void RenderTask::SetCullMode( bool mode )
+{
+  GetImplementation(*this).SetCullMode( mode );
+}
+
+bool RenderTask::GetCullMode() const
+{
+  return GetImplementation(*this).GetCullMode();
+}
+
+void RenderTask::SetRefreshRate( unsigned int refreshRate )
+{
+  GetImplementation(*this).SetRefreshRate( refreshRate );
+}
+
+unsigned int RenderTask::GetRefreshRate() const
+{
+  return GetImplementation(*this).GetRefreshRate();
+}
+
+RenderTask::RenderTaskSignalType& RenderTask::FinishedSignal()
+{
+  return GetImplementation(*this).FinishedSignal();
+}
+
+void RenderTask::SetInputEnabled( bool enabled )
+{
+  GetImplementation(*this).SetInputEnabled( enabled );
+}
+
+bool RenderTask::GetInputEnabled() const
+{
+  return GetImplementation(*this).GetInputEnabled();
+}
+
+RenderTask::RenderTask( Internal::RenderTask* internal )
+: Handle(internal)
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/render-tasks/render-task.h b/dali/public-api/render-tasks/render-task.h
new file mode 100644 (file)
index 0000000..2cdbbc0
--- /dev/null
@@ -0,0 +1,467 @@
+#ifndef __DALI_RENDER_TASK_H__
+#define __DALI_RENDER_TASK_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/math/viewport.h>
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+#include <dali/public-api/signals/dali-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+class Actor;
+class CameraActor;
+class FrameBufferImage;
+struct Vector4;
+
+namespace Internal DALI_INTERNAL
+{
+class RenderTask;
+}
+
+/**
+ * @brief RenderTasks describe how the Dali scene should be rendered.
+ *
+ * The Stage::GetRenderTaskList() method provides access to an ordered list of render-tasks.
+ *
+ * Each RenderTask must specify the source actors to be rendered, and a camera actor from
+ * which the scene is viewed.
+ *
+ * RenderTasks may optionally target a frame-buffer, otherwise the default GL surface is used;
+ * typically this is a window provided by the native system.
+ *
+ * By default Dali provides a single RenderTask, which renders the entire actor hierachy using
+ * a default camera actor and GL surface. If stereoscopic rendering is enabled, Dali will create
+ * two additional render tasks, on for each eye. Each render task will have its own camera parented
+ * to the default camera actor.
+ *
+ * The first RenderTask used for input handling will be the last one rendered, which also has input enabled,
+ * and has a valid source & camera actor; see SetInputEnabled().
+ *
+ * If none of the actors are hit in the last RenderTask rendered, then input handling will continue
+ * with the second last RenderTask rendered, and so on.
+ *
+ * All RenderTasks which target a frame-buffer (i.e. off screen) will be rendered before all RenderTasks
+ * which target the default GL surface. This allows the user to render intermediate targets which are used
+ * later when targetting the screen.
+ *
+ * A RenderTask targetting a frame-buffer can still be hit-tested, provided that the
+ * screen->frame-buffer coordinate conversion is successful; see SetScreenToFrameBufferFunction().
+ *
+ * If the refresh rate id REFRESH_ONCE and a "Finish" signal is connected, it will be emitted when the RenderTask is completed.
+ * Note that all connected signals must be disconnected before the object is destroyed. This is typically done in the
+ * object destructor, and requires either the Dali::Connection object or Dali::RenderTask handle to be stored.
+ *
+ * Signals
+ * | %Signal Name | Method                |
+ * |--------------|-----------------------|
+ * | finished     | @ref FinishedSignal() |
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API RenderTask : public Handle
+{
+public:
+
+  /**
+   * @brief An enumeration of properties belonging to the RenderTask class.
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      VIEWPORT_POSITION = DEFAULT_OBJECT_PROPERTY_START_INDEX, ///< name "viewport-position", type Vector2
+      VIEWPORT_SIZE,                                           ///< name "viewport-size",     type Vector2
+      CLEAR_COLOR,                                             ///< name "clear-color",       type Vector4
+    };
+  };
+
+  /**
+   * @brief Typedef for signals sent by this class.
+   * @since_tizen 2.4
+   */
+  typedef Signal< void (RenderTask& source) > RenderTaskSignalType;
+
+  /**
+   * @brief A pointer to a function for converting screen to frame-buffer coordinates.
+   * @since_tizen 2.4
+   * @param[in,out] coordinates The screen coordinates to convert where (0,0) is the top-left of the screen.
+   * @return True if the conversion was successful, otherwise coordinates should be unmodified.
+   */
+  typedef bool (* ScreenToFrameBufferFunction)( Vector2& coordinates );
+
+  /**
+   * @brief A pointer to a function for converting screen to frame-buffer coordinates.
+   * @since_tizen 2.4
+   * @param[in,out] coordinates The screen coordinates to convert where (0,0) is the top-left of the screen.
+   * @return True if the conversion was successful, otherwise coordinates should be unmodified.
+   */
+  typedef bool (* const ConstScreenToFrameBufferFunction)( Vector2& coordinates );
+
+  /**
+   * @brief The default conversion function returns false for any screen coordinates.
+   *
+   * This effectively disables hit-testing for RenderTasks rendering to a frame buffer.
+   * See also FULLSCREEN_FRAMEBUFFER_FUNCTION below.
+   */
+  static ConstScreenToFrameBufferFunction DEFAULT_SCREEN_TO_FRAMEBUFFER_FUNCTION;
+
+  /**
+   * @brief This conversion function outputs the (unmodified) screen coordinates as frame-buffer coordinates.
+   *
+   * Therefore the contents of an off-screen image is expected to be rendered "full screen".
+   */
+  static ConstScreenToFrameBufferFunction FULLSCREEN_FRAMEBUFFER_FUNCTION;
+
+  /**
+   * @brief The refresh-rate of the RenderTask.
+   * @since_tizen 2.4
+   */
+  enum RefreshRate
+  {
+    REFRESH_ONCE   = 0, ///< Process once only e.g. take a snap-shot of the scene.
+    REFRESH_ALWAYS = 1  ///< Process every frame.
+  };
+
+  static const bool         DEFAULT_EXCLUSIVE;     ///< false
+  static const bool         DEFAULT_INPUT_ENABLED; ///< true
+  static const Vector4      DEFAULT_CLEAR_COLOR;   ///< Color::BLACK
+  static const bool         DEFAULT_CLEAR_ENABLED; ///< false
+  static const bool         DEFAULT_CULL_MODE;     ///< true
+  static const unsigned int DEFAULT_REFRESH_RATE;  ///< REFRESH_ALWAYS
+
+  /**
+   * @brief Create an empty RenderTask handle.
+   *
+   * This can be initialised with RenderTaskList::CreateRenderTask().
+   * @since_tizen 2.4
+   */
+  RenderTask();
+
+  /**
+   * @brief Downcast a handle to RenderTask handle.
+   *
+   * If handle points to a RenderTask the
+   * downcast produces valid handle. If not the returned handle is left uninitialized.
+   * @since_tizen 2.4
+   * @param[in] handle A handle to an object.
+   * @return A handle to a RenderTask or an uninitialized handle.
+   */
+  static RenderTask DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~RenderTask();
+
+  /**
+   * @brief This copy constructor is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] handle A reference to the copied handle
+   */
+  RenderTask(const RenderTask& handle);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  RenderTask& operator=(const RenderTask& rhs);
+
+  /**
+   * @brief Set the actors to be rendered.
+   * @since_tizen 2.4
+   * @param[in] actor This actor and its children will be rendered.
+   * If actor is an empty handle, then nothing will be rendered.
+   */
+  void SetSourceActor( Actor actor );
+
+  /**
+   * @brief Retrieve the actors to be rendered.
+   * @since_tizen 2.4
+   * @return This actor and its children will be rendered.
+   */
+  Actor GetSourceActor() const;
+
+  /**
+   * @brief Set whether the RenderTask has exclusive access to the source actors; the default is false.
+   * @since_tizen 2.4
+   * @param[in] exclusive True if the source actors will only be rendered by this render-task.
+   */
+  void SetExclusive( bool exclusive );
+
+  /**
+   * @brief Query whether the RenderTask has exclusive access to the source actors.
+   * @since_tizen 2.4
+   * @return True if the source actors will only be rendered by this render-task.
+   */
+  bool IsExclusive() const;
+
+  /**
+   * @brief Set whether the render-task should be considered for input handling; the default is true.
+   *
+   * The task used for input handling will be last task in the RenderTaskList which has input enabled,
+   * and has a valid source & camera actor.
+   * A RenderTask targetting a frame-buffer can still be hit-tested, provided that the screen->frame-buffer
+   * coordinate conversion is successful; see also SetScreenToFrameBufferFunction().
+   * @since_tizen 2.4
+   * @param[in] enabled True if the render-task should be considered for input handling.
+   */
+  void SetInputEnabled( bool enabled );
+
+  /**
+   * @brief Query whether the render-task should be considered for input handling.
+   * @since_tizen 2.4
+   * @return True if the render-task should be considered for input handling.
+   */
+  bool GetInputEnabled() const;
+
+  /**
+   * @brief Set the actor from which the scene is viewed.
+   * @since_tizen 2.4
+   * @param[in] cameraActor The scene is viewed from the perspective of this actor.
+   */
+  void SetCameraActor( CameraActor cameraActor );
+
+  /**
+   * @brief Retrieve the actor from which the scene is viewed.
+   * @since_tizen 2.4
+   * @return The scene is viewed from the perspective of this actor.
+   */
+  CameraActor GetCameraActor() const;
+
+  /**
+   * @brief Set the frame-buffer used as a render target.
+   * @since_tizen 2.4
+   * @param[in] frameBuffer A valid frame-buffer handle to enable off-screen rendering, or an uninitialized handle to disable.
+   */
+  void SetTargetFrameBuffer( FrameBufferImage frameBuffer );
+
+  /**
+   * @brief Retrieve the frame-buffer used as a render target.
+   * @since_tizen 2.4
+   * @return A valid frame-buffer handle, or an uninitialised handle if off-screen rendering is disabled.
+   */
+  FrameBufferImage GetTargetFrameBuffer() const;
+
+  /**
+   * @brief Set the function used to convert screen coordinates to frame-buffer coordinates.
+   *
+   * This is useful for hit-testing actors which are rendered off-screen.
+   * @since_tizen 2.4
+   * @param[in] conversionFunction The conversion function.
+   */
+  void SetScreenToFrameBufferFunction( ScreenToFrameBufferFunction conversionFunction );
+
+  /**
+   * @brief Retrieve the function used to convert screen coordinates to frame-buffer coordinates.
+   * @since_tizen 2.4
+   * @return The conversion function.
+   */
+  ScreenToFrameBufferFunction GetScreenToFrameBufferFunction() const;
+
+  /**
+   * @brief Set the actor used to convert screen coordinates to frame-buffer coordinates.
+   *
+   * The local coordinates of the actor are mapped as frame-buffer coordinates.
+   * This is useful for hit-testing actors which are rendered off-screen.
+   * Note: The mapping actor needs to be rendered by the default render task to make the mapping work properly.
+   * @since_tizen 2.4
+   * @param[in] mappingActor The actor used for conversion.
+   */
+  void SetScreenToFrameBufferMappingActor( Actor mappingActor );
+
+  /**
+   * @brief Retrieve the actor used to convert screen coordinates to frame-buffer coordinates.
+   * @since_tizen 2.4
+   * @return The actor used for conversion.
+   */
+  Actor GetScreenToFrameBufferMappingActor() const;
+
+  /**
+   * @brief Set the GL viewport position used when rendering.
+   *
+   * This specifies the transformation between normalized device coordinates and target window (or frame-buffer) coordinates.
+   * By default this will match the target window or frame-buffer size.
+   * @since_tizen 2.4
+   * @param[in] position The viewports position (x,y)
+   * @note Unlike the glViewport method, the x & y coordinates refer to the top-left of the viewport rectangle.
+   */
+  void SetViewportPosition( Vector2 position );
+
+  /**
+   * @brief Retrieve the GL viewport position used when rendering.
+   * @since_tizen 2.4
+   * @return The viewport.
+   */
+  Vector2 GetCurrentViewportPosition() const;
+
+  /**
+   * @brief Set the GL viewport size used when rendering.
+   *
+   * This specifies the transformation between normalized device coordinates and target window (or frame-buffer) coordinates.
+   * By default this will match the target window or frame-buffer size.
+   * @since_tizen 2.4
+   * @param[in] size The viewports size (width,height)
+   */
+  void SetViewportSize( Vector2 size );
+
+  /**
+   * @brief Retrieve the GL viewport size used when rendering.
+   * @since_tizen 2.4
+   * @return The viewport.
+   */
+  Vector2 GetCurrentViewportSize() const;
+
+  /**
+   * @brief Set the GL viewport used when rendering.
+   *
+   * This specifies the transformation between normalized device coordinates and target window (or frame-buffer) coordinates.
+   * By default this will match the target window or frame-buffer size.
+   * @since_tizen 2.4
+   * @param[in] viewport The new viewport.
+   * @note Unlike the glViewport method, the x & y coordinates refer to the top-left of the viewport rectangle.
+   */
+  void SetViewport( Viewport viewport );
+
+  /**
+   * @brief Retrieve the GL viewport used when rendering.
+   * @since_tizen 2.4
+   * @return The viewport.
+   */
+  Viewport GetViewport() const;
+
+  /**
+   * @brief Set the clear color used when SetClearEnabled(true) is used.
+   * @since_tizen 2.4
+   * @param[in] color The new clear color.
+   */
+  void SetClearColor( const Vector4& color );
+
+  /**
+   * @brief Retrieve the clear color used when SetClearEnabled(true) is used.
+   * @since_tizen 2.4
+   * @return The clear color.
+   * @note This property can be animated; the return value may not match the value written with SetClearColor().
+   */
+  Vector4 GetClearColor() const;
+
+  /**
+   * @brief Set whether the render-task will clear the results of previous render-tasks.
+   *
+   * The default is false.
+   *
+   * @since_tizen 2.4
+   * @param[in] enabled True if the render-task should clear.
+   * @note The default GL surface is cleared automatically at the
+   * beginning of each frame; this setting is only useful when 2+
+   * render-tasks are used, and the result of the first task needs to
+   * be (partially) cleared before rendering the second.
+   *
+   */
+  void SetClearEnabled( bool enabled );
+
+  /**
+   * @brief Query whether the render-task will clear the results of previous render-tasks.
+   * @since_tizen 2.4
+   * @return True if the render-task should clear.
+   */
+  bool GetClearEnabled() const;
+
+  /**
+   * @brief Set whether the render task will cull the actors to the camera's view frustum.
+   *
+   * Note that this will only affect image views that use the default vertex shader.
+   * The default mode is to cull actors.
+   * @since_tizen 2.4
+   * @param[in] cullMode True if the renderers should be culled.
+   */
+  void SetCullMode( bool cullMode );
+
+  /**
+   * @brief Get the cull mode.
+   *
+   * @since_tizen 2.4
+   * @return True if the render task should cull the actors to the camera's view frustum
+   */
+  bool GetCullMode() const;
+
+  /**
+   * @brief Set the refresh-rate of the RenderTask.
+   *
+   * The default is REFRESH_ALWAYS (1), meaning that the RenderTask
+   * will be processed every frame if the scene graph is changing.  It
+   * may be desirable to process less frequently. For example,
+   * SetRefreshRate(3) will process once every 3 frames if the scene
+   * graph is changing.  If the scene graph is not changing, then the
+   * render task will not be rendered, regardless of this value.
+   *
+   * The REFRESH_ONCE value means that the RenderTask will be
+   * processed once only, to take a snap-shot of the scene.
+   * Repeatedly calling SetRefreshRate(REFRESH_ONCE) will cause more
+   * snap-shots to be taken.
+   *
+   * @since_tizen 2.4
+   * @param[in] refreshRate The new refresh rate.
+   */
+  void SetRefreshRate( unsigned int refreshRate );
+
+  /**
+   * @brief Query the refresh-rate of the RenderTask.
+   * @since_tizen 2.4
+   * @return The refresh-rate.
+   */
+  unsigned int GetRefreshRate() const;
+
+public: // Signals
+
+  /**
+   * @brief If the refresh rate is REFRESH_ONCE, connect to this signal to be notified when a RenderTask has finished.
+   * @since_tizen 2.4
+   */
+  RenderTaskSignalType& FinishedSignal();
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   * @since_tizen 2.4
+   * @param [in] renderTask A pointer to a newly allocated render-task
+   */
+  explicit DALI_INTERNAL RenderTask( Internal::RenderTask* renderTask );
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif //__DALI_RENDER_TASK_H__
diff --git a/dali/public-api/shader-effects/shader-effect.cpp b/dali/public-api/shader-effects/shader-effect.cpp
new file mode 100644 (file)
index 0000000..d8c09e0
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/shader-effects/shader-effect.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/event/effects/shader-effect-impl.h>
+#include <dali/internal/event/animation/constraint-impl.h>
+#include <dali/public-api/animation/constraint.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+const float ShaderEffect::DEFAULT_GRID_DENSITY = 40;
+
+ShaderEffect::ShaderEffect()
+{
+}
+
+ShaderEffect::ShaderEffect(Internal::ShaderEffect* internal)
+: Handle(internal)
+{
+}
+
+ShaderEffect::~ShaderEffect()
+{
+}
+
+ShaderEffect::ShaderEffect(const ShaderEffect& handle)
+: Handle(handle)
+{
+}
+
+ShaderEffect& ShaderEffect::operator=(const ShaderEffect& rhs)
+{
+  BaseHandle::operator=(rhs);
+  return *this;
+}
+
+ShaderEffect ShaderEffect::New( const std::string& vertexShader, const std::string& fragmentShader, GeometryHints hints)
+{
+  // @todo MESH_REWORK - Assert only image geometry type is passed.
+  Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( hints );
+
+  internal->SetPrograms( vertexShader, fragmentShader );
+
+  return ShaderEffect( internal.Get() );
+}
+
+ShaderEffect ShaderEffect::NewWithPrefix( const std::string& vertexShaderPrefix,
+                                          const std::string& vertexShader,
+                                          const std::string& fragmentShaderPrefix,
+                                          const std::string& fragmentShader,
+                                          GeometryHints hints)
+{
+  // @todo MESH_REWORK - Assert only image geometry type is passed.
+  Internal::ShaderEffectPtr internal = Internal::ShaderEffect::New( hints );
+
+  internal->SetPrograms( vertexShaderPrefix, fragmentShaderPrefix, vertexShader, fragmentShader );
+
+  return ShaderEffect( internal.Get() );
+}
+
+ShaderEffect ShaderEffect::DownCast( BaseHandle handle )
+{
+  return ShaderEffect( dynamic_cast<Dali::Internal::ShaderEffect*>(handle.GetObjectPtr()) );
+}
+
+void ShaderEffect::SetEffectImage( Image image )
+{
+  GetImplementation(*this).SetEffectImage( image );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, float value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, Vector2 value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, Vector3 value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, Vector4 value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, const Matrix& value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+void ShaderEffect::SetUniform( const std::string& name, const Matrix3& value, UniformCoordinateType uniformCoordinateType )
+{
+  GetImplementation(*this).SetUniform( name, value, uniformCoordinateType );
+}
+
+} // namespace Dali
diff --git a/dali/public-api/shader-effects/shader-effect.h b/dali/public-api/shader-effects/shader-effect.h
new file mode 100644 (file)
index 0000000..a848fa4
--- /dev/null
@@ -0,0 +1,363 @@
+#ifndef __DALI_SHADER_EFFECT_H__
+#define __DALI_SHADER_EFFECT_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/object/handle.h>
+#include <dali/public-api/object/property-index-ranges.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_rendering_effects
+ * @{
+ */
+
+/**
+ * @brief DALI_COMPOSE_SHADER macro provides a convenient way to write shader source code.
+ *
+ * We normally use double quotation marks to write a string such as "Hello World".
+ * However many symbols are needed to add multiple lines of string.
+ * We don't need to write quotation marks using this macro at every line.
+ *
+ * [An example of double quotation marks usage]
+ * const string FRAGMENT_SHADER_SOURCE = \
+ * "  void main()\n"
+ * "  {\n"
+ * "    gl_FragColor = texture2D( sTexture, vTexCoord ) * uColor;\n"
+ * "  }\n";
+ *
+ * [An example of DALI_COMPOSE_SHADER usage]
+ * const string VERTEX_SHADER_SOURCE = DALI_COMPOSE_SHADER (
+ *   void main()
+ *   {
+ *     gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
+ *     vTexCoord = aTexCoord;
+ *   }
+ * );
+ * @since_tizen 2.4
+ */
+#define DALI_COMPOSE_SHADER(STR) #STR
+
+class Image;
+struct Vector2;
+struct Vector3;
+struct Vector4;
+
+namespace Internal DALI_INTERNAL
+{
+class ShaderEffect;
+}
+
+/**
+ * @brief Shader effects provide a visual effect for image views.
+ *
+ * For a Custom shader you can provide the vertex and fragment shader code as strings.
+ * These shader snippets get concatenated with the default attributes and uniforms.
+ * For a vertex shader this part contains the following code:
+ * <pre>
+ * precision highp float;
+ * attribute vec3  aPosition;
+ * attribute vec2  aTexCoord;
+ * uniform   mat4  uMvpMatrix;
+ * uniform   mat4  uModelMatrix;
+ * uniform   mat4  uViewMatrix;
+ * uniform   mat4  uModelView;
+ * uniform   mat3  uNormalMatrix;
+ * uniform   mat4  uProjection;
+ * uniform   vec4  uColor;
+ * varying   vec2  vTexCoord;
+ * </pre>
+ * The custom shader part is expected to output the vertex position and texture coordinate.
+ * A basic custom vertex shader would contain the following code:
+ * <pre>
+ * void main()
+ * {
+ *   gl_Position = uProjection * uModelView * vec4(aPosition, 1.0);
+ *   vTexCoord = aTexCoord;
+ * }
+ * </pre>
+ * For fragment shader the default part for images contains the following code:
+ * <pre>
+ * precision mediump float;
+ * uniform   sampler2D sTexture;
+ * uniform   sampler2D sEffect;
+ * uniform   vec4      uColor;
+ * varying   vec2      vTexCoord;
+ * </pre>
+ * <BR>
+ * <B>
+ * Note: In order for fade and color animations to work, the fragment shader needs to multiply the fragment color
+ * with the uniform color "uColor" of the node
+ * </B>
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ShaderEffect : public Handle
+{
+public:
+
+  // Default Properties
+  /**
+   * @brief An enumeration of properties belonging to the Path class.
+   * Grid Density defines the spacing of vertex coordinates in world units.
+   * ie a larger actor will have more grids at the same spacing.
+   *
+   *  +---+---+         +---+---+---+
+   *  |   |   |         |   |   |   |
+   *  +---+---+         +---+---+---+
+   *  |   |   |         |   |   |   |
+   *  +---+---+         +---+---+---+
+   *                    |   |   |   |
+   *                    +---+---+---+
+   * @since_tizen 2.4
+   */
+  struct Property
+  {
+    enum
+    {
+      GRID_DENSITY = DEFAULT_ACTOR_PROPERTY_START_INDEX, ///< name "grid-density",   type float
+      IMAGE,                                             ///< name "image",          type Map {"filename":"", "load-policy":...}
+      PROGRAM,                                           ///< name "program",        type Map {"vertex-prefix":"","fragment-prefix":"","vertex":"","fragment":""}
+      GEOMETRY_HINTS                                     ///< name "geometry-hints", type int (bitfield) values from enum GeometryHints
+    };
+  };
+
+  static const float DEFAULT_GRID_DENSITY;              ///< The default density is 40 pixels
+
+  /**
+   * @brief Hints for rendering/subdividing geometry.
+   * @since_tizen 2.4
+   */
+  enum GeometryHints
+  {
+    HINT_NONE           = 0x00,   ///< no hints
+    HINT_GRID_X         = 0x01,   ///< Geometry must be subdivided in X
+    HINT_GRID_Y         = 0x02,   ///< Geometry must be subdivided in Y
+    HINT_GRID           = (HINT_GRID_X | HINT_GRID_Y),
+    HINT_DEPTH_BUFFER   = 0x04,   ///< Needs depth buffering turned on
+    HINT_BLENDING       = 0x08,   ///< Notifies the actor to use blending even if it's fully opaque. Needs actor's blending set to BlendingMode::AUTO
+    HINT_DOESNT_MODIFY_GEOMETRY = 0x10 ///< Notifies that the vertex shader will not change geometry (enables bounding box culling)
+  };
+
+  /**
+   * @brief Coordinate type of the shader uniform.
+   *
+   * Viewport coordinate types will convert from viewport to view space.
+   * Use this coordinate type if your are doing a transformation in view space.
+   * The texture coordinate type converts a value in actor local space to texture coodinates.
+   * This is useful for pixel shaders and accounts for texture atlas.
+   * @since_tizen 2.4
+   */
+  enum UniformCoordinateType
+  {
+    COORDINATE_TYPE_DEFAULT,           ///< Default, No transformation to be applied
+    COORDINATE_TYPE_VIEWPORT_POSITION, ///< The uniform is a position vector in viewport coordinates that needs to be converted to GL view space coordinates.
+    COORDINATE_TYPE_VIEWPORT_DIRECTION ///< The uniform is a directional vector in viewport coordinates that needs to be converted to GL view space coordinates.
+  };
+
+  /**
+   * @brief Create an empty ShaderEffect.
+   *
+   * This can be initialised with ShaderEffect::New(...)
+   * @since_tizen 2.4
+   */
+  ShaderEffect();
+
+  /**
+   * @brief Create ShaderEffect.
+   *
+   * @since_tizen 2.4
+   * @param vertexShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param fragmentShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param hints GeometryHints to define the geometry of the rendered object
+   * @return A handle to a shader effect
+   */
+  static ShaderEffect New( const std::string& vertexShader,
+                           const std::string& fragmentShader,
+                           GeometryHints hints = GeometryHints(HINT_NONE) );
+
+  /**
+   * @brief Create ShaderEffect.
+   * @since_tizen 2.4
+   * @param vertexShaderPrefix code for the effect. It will be inserted before the default uniforms (ideal for \#defines)
+   * @param vertexShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param fragmentShaderPrefix code for the effect. It will be inserted before the default uniforms (ideal for \#defines)
+   * @param fragmentShader code for the effect. If you pass in an empty string, the default version will be used
+   * @param hints GeometryHints to define the geometry of the rendered object
+   * @return A handle to a shader effect
+   */
+  static ShaderEffect NewWithPrefix(const std::string& vertexShaderPrefix,
+                                    const std::string& vertexShader,
+                                    const std::string& fragmentShaderPrefix,
+                                    const std::string& fragmentShader,
+                                    GeometryHints hints = GeometryHints(HINT_NONE) );
+
+  /**
+   * @brief Downcast an Object handle to ShaderEffect.
+   *
+   * If handle points to a ShaderEffect the downcast produces valid
+   * handle. If not the returned handle is left uninitialized.
+   *
+   * @since_tizen 2.4
+   * @param[in] handle to An object
+   * @return handle to a ShaderEffect object or an uninitialized handle
+   */
+  static ShaderEffect DownCast( BaseHandle handle );
+
+  /**
+   * @brief Destructor
+   *
+   * This is non-virtual since derived Handle types must not contain data or virtual methods.
+   * @since_tizen 2.4
+   */
+  ~ShaderEffect();
+
+  /**
+   * @brief Copy constructor
+   *
+   * @since_tizen 2.4
+   * @param object A reference to a ShaderEffect object
+   */
+  ShaderEffect(const ShaderEffect& object);
+
+  /**
+   * @brief This assignment operator is required for (smart) pointer semantics.
+   *
+   * @since_tizen 2.4
+   * @param [in] rhs  A reference to the copied handle
+   * @return A reference to this
+   */
+  ShaderEffect& operator=(const ShaderEffect& rhs);
+
+  /**
+   * @brief Sets image for using as effect texture.
+   *
+   * This image texture will be bound to the "sEffect" sampler
+   * so it can be used in fragment shader for effects
+   *
+   * @since_tizen 2.4
+   * @param[in] image to use as effect texture
+   */
+  void SetEffectImage( Image image );
+
+  /**
+   * @brief Set a uniform value.
+   * This will register a property of type Property::FLOAT; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   float value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+  /**
+   * @brief Set a uniform value.
+   *
+   * This will register a property of type Property::VECTOR2; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   Vector2 value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+  /**
+   * @brief Set a uniform value.
+   *
+   * This will register a property of type Property::VECTOR3; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   Vector3 value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+  /**
+   * @brief Set a uniform value.
+   *
+   * This will register a property of type Property::VECTOR4; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   Vector4 value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+  /**
+   * @brief Set a uniform value.
+   *
+   * This will register a property of type Property::MATRIX; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   const Matrix& value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+  /**
+   * @brief Set a uniform value.
+   *
+   * This will register a property of type Property::MATRIX3; see Object::RegisterProperty() for more details.
+   * If name matches a uniform in the shader source, this value will be uploaded when rendering.
+   * @since_tizen 2.4
+   * @param name The name of the uniform.
+   * @param value The value to to set.
+   * @param uniformCoordinateType The coordinate type of the uniform.
+   * @pre Either the property name is not in use, or a property exists with the correct name & type.
+   */
+  void SetUniform( const std::string& name,
+                   const Matrix3& value,
+                   UniformCoordinateType uniformCoordinateType = UniformCoordinateType(COORDINATE_TYPE_DEFAULT) );
+
+public: // Not intended for application developers
+
+  /**
+   * @brief This constructor is used by Dali New() methods.
+   * @since_tizen 2.4
+   * @param [in] effect A pointer to a newly allocated Dali resource.
+   */
+  explicit DALI_INTERNAL ShaderEffect(Internal::ShaderEffect* effect);
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SHADER_EFFECT_H__
diff --git a/dali/public-api/signals/base-signal.cpp b/dali/public-api/signals/base-signal.cpp
new file mode 100644 (file)
index 0000000..6150994
--- /dev/null
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/base-signal.h>
+
+// EXTERNAL INCLUDES
+#include <algorithm> // remove_if
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+namespace
+{
+
+const int INVALID_CALLBACK_INDEX = -1;
+
+} // unnamed namespace
+
+namespace Dali
+{
+
+BaseSignal::BaseSignal()
+: mEmittingFlag( false )
+{
+}
+
+BaseSignal::~BaseSignal()
+{
+  // We can't assert in a destructor
+  if( mEmittingFlag )
+  {
+    DALI_LOG_ERROR( "Invalid destruction of Signal during Emit()\n" );
+  }
+
+  // The signal is being destroyed. We have to inform any slots
+  // that are connected, that the signal is dead.
+  const std::size_t count( mSignalConnections.Count() );
+  for( std::size_t i=0; i < count; i++ )
+  {
+    SignalConnection* connection = mSignalConnections[ i ];
+
+    // Note that values are set to NULL in DeleteConnection
+    if( connection )
+    {
+      connection->Disconnect( this );
+      delete connection;
+    }
+  }
+
+  mSignalConnections.Clear();
+}
+
+bool BaseSignal::Empty() const
+{
+  return ( 0 == GetConnectionCount() );
+}
+
+std::size_t BaseSignal::GetConnectionCount() const
+{
+  std::size_t count( 0 );
+
+  const std::size_t size( mSignalConnections.Count() );
+  for( std::size_t i = 0; i < size; ++i )
+  {
+    // Note that values are set to NULL in DeleteConnection
+    if ( NULL != mSignalConnections[i] )
+    {
+      ++count;
+    }
+  }
+
+  return count;
+}
+
+void BaseSignal::Emit()
+{
+  // Guards against nested Emit() calls
+  EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+  if( guard.ErrorOccurred() )
+  {
+    return;
+  }
+
+  // If more connections are added by callbacks, these are ignore until the next Emit()
+  // Note that mSignalConnections.Count() count cannot be reduced while iterating
+  const std::size_t initialCount( mSignalConnections.Count() );
+
+  for( std::size_t i = 0; i < initialCount; ++i )
+  {
+    CallbackBase* callback( GetCallback(i) );
+
+    // Note that connections will be set to NULL when disconnected
+    // This is preferable to reducing the connection count while iterating
+    if( callback )
+    {
+      CallbackBase::Execute( *callback );
+    }
+  }
+
+  // Cleanup NULL values from Connection container
+  CleanupConnections();
+}
+
+void BaseSignal::OnConnect( CallbackBase* callback )
+{
+  DALI_ASSERT_ALWAYS( NULL != callback && "Invalid member function pointer passed to Connect()" );
+
+  int index = FindCallback( callback );
+
+  // Don't double-connect the same callback
+  if( INVALID_CALLBACK_INDEX == index )
+  {
+    // create a new signal connection object, to allow the signal to track the connection.
+    SignalConnection* connection = new SignalConnection( callback );
+
+    mSignalConnections.PushBack( connection );
+  }
+  else
+  {
+    // clean-up required
+    delete callback;
+  }
+}
+
+void BaseSignal::OnDisconnect( CallbackBase* callback )
+{
+  DALI_ASSERT_ALWAYS( NULL != callback && "Invalid member function pointer passed to Disconnect()" );
+
+  int index = FindCallback( callback );
+
+  if( index > INVALID_CALLBACK_INDEX )
+  {
+    DeleteConnection( index );
+  }
+
+  // call back is a temporary created to find which slot should be disconnected.
+  delete callback;
+}
+
+void BaseSignal::OnConnect( ConnectionTrackerInterface* tracker, CallbackBase* callback )
+{
+  DALI_ASSERT_ALWAYS( NULL != tracker  && "Invalid ConnectionTrackerInterface pointer passed to Connect()" );
+  DALI_ASSERT_ALWAYS( NULL != callback && "Invalid member function pointer passed to Connect()" );
+
+  int index = FindCallback( callback );
+
+  // Don't double-connect the same callback
+  if( INVALID_CALLBACK_INDEX == index )
+  {
+    // create a new signal connection object, to allow the signal to track the connection.
+    SignalConnection* connection = new SignalConnection( tracker, callback );
+
+    mSignalConnections.PushBack( connection );
+
+    // Let the connection tracker know that a connection between a signal and a slot has been made.
+    tracker->SignalConnected( this, callback );
+  }
+  else
+  {
+    // clean-up required
+    delete callback;
+  }
+}
+
+void BaseSignal::OnDisconnect( ConnectionTrackerInterface* tracker, CallbackBase* callback )
+{
+  DALI_ASSERT_ALWAYS( NULL != tracker  && "Invalid ConnectionTrackerInterface pointer passed to Disconnect()" );
+  DALI_ASSERT_ALWAYS( NULL != callback && "Invalid member function pointer passed to Disconnect()" );
+
+  int index = FindCallback( callback );
+
+  if( index > INVALID_CALLBACK_INDEX )
+  {
+    // temporary pointer to disconnected callback
+    CallbackBase* disconnectedCallback = mSignalConnections[index]->GetCallback();
+
+    // close the signal side connection first.
+    DeleteConnection( index );
+
+    // close the slot side connection
+    tracker->SignalDisconnected( this, disconnectedCallback );
+  }
+
+  // call back is a temporary created to find which slot should be disconnected.
+  delete callback;
+}
+
+// for SlotObserver::SlotDisconnected
+void BaseSignal::SlotDisconnected( CallbackBase* callback )
+{
+  const std::size_t count( mSignalConnections.Count() );
+  for( std::size_t i=0; i < count; ++i )
+  {
+    const CallbackBase* connectionCallback = GetCallback( i );
+
+    // Pointer comparison i.e. SignalConnection contains pointer to same callback instance
+    if( connectionCallback &&
+        connectionCallback == callback )
+    {
+      DeleteConnection( i );
+
+      // Disconnection complete
+      return;
+    }
+  }
+
+  DALI_ASSERT_ALWAYS( false && "Callback lost in SlotDisconnected()" );
+}
+
+CallbackBase* BaseSignal::GetCallback( std::size_t connectionIndex ) const
+{
+  DALI_ASSERT_ALWAYS( connectionIndex < mSignalConnections.Count() && "GetCallback called with invalid index" );
+
+  CallbackBase* callback( NULL );
+
+  SignalConnection* connection( mSignalConnections[ connectionIndex ] );
+
+  // Note that values are set to NULL in DeleteConnection
+  if( connection )
+  {
+    callback = connection->GetCallback();
+  }
+
+  return callback;
+}
+
+int BaseSignal::FindCallback( CallbackBase* callback )
+{
+  int index( INVALID_CALLBACK_INDEX );
+
+  // A signal can have multiple slots connected to it.
+  // We need to search for the slot which has the same call back function (if it's static)
+  // Or the same object / member function (for non-static)
+  const std::size_t count( mSignalConnections.Count() );
+  for( std::size_t i=0; i < count; ++i )
+  {
+    const CallbackBase* connectionCallback = GetCallback( i );
+
+    // Note that values are set to NULL in DeleteConnection
+    if( connectionCallback &&
+        ( *connectionCallback == *callback ) )
+    {
+      index = i;
+      break;
+    }
+  }
+
+  return index;
+}
+
+void BaseSignal::DeleteConnection( std::size_t connectionIndex )
+{
+  DALI_ASSERT_ALWAYS( connectionIndex < mSignalConnections.Count() && "DeleteConnection called with invalid index" );
+
+  // delete the object
+  SignalConnection* connection( mSignalConnections[ connectionIndex ] );
+  delete connection;
+
+  // IMPORTANT - do not remove from items from mSignalConnections, set to NULL instead.
+  // Signal Emit() methods require that connection count is not reduced while iterating
+  // i.e. DeleteConnection can be called from within callbacks, while iterating through mSignalConnections.
+  mSignalConnections[ connectionIndex ] = NULL;
+}
+
+void BaseSignal::CleanupConnections()
+{
+  const std::size_t total = mSignalConnections.Count();
+  // only do something if there are items
+  if( total > 0 )
+  {
+    std::size_t index = 0;
+    // process the whole vector
+    for( std::size_t i = 0; i < total; ++i )
+    {
+      if( mSignalConnections[ index ] == NULL )
+      {
+        // items will be moved so don't increase index (erase will decrease the count of vector)
+        mSignalConnections.Erase( mSignalConnections.Begin() + index );
+      }
+      else
+      {
+        // increase to next element
+        ++index;
+      }
+    }
+  }
+}
+
+// BaseSignal::EmitGuard
+
+BaseSignal::EmitGuard::EmitGuard( bool& flag )
+: mFlag( NULL )
+{
+  if( !flag )
+  {
+    mFlag = &flag;
+    flag = true;
+  }
+  else
+  {
+    // mFlag is NULL when Emit() is called during Emit()
+    DALI_LOG_ERROR( "Cannot call Emit() from inside Emit()" );
+  }
+}
+
+BaseSignal::EmitGuard::~EmitGuard()
+{
+  if( mFlag )
+  {
+    *mFlag = false;
+  }
+}
+
+bool BaseSignal::EmitGuard::ErrorOccurred()
+{
+  // mFlag is NULL when Emit() is called during Emit()
+  return (NULL == mFlag);
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/base-signal.h b/dali/public-api/signals/base-signal.h
new file mode 100644 (file)
index 0000000..acbdf65
--- /dev/null
@@ -0,0 +1,529 @@
+#ifndef __DALI_BASE_SIGNAL_H__
+#define __DALI_BASE_SIGNAL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/signals/callback.h>
+#include <dali/public-api/signals/connection-tracker-interface.h>
+#include <dali/public-api/signals/signal-slot-connections.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+/**
+ * @brief Implementation class for Dali::Signal.
+ *
+ * A slot can be connected to many signals
+ * A signal can be connected to many slots
+ *
+ * To provide automatic disconnection when either a signal or the object owning the slot dies,
+ * observers are used.
+ *
+ * A signal is an object with state. It holds a list of SignalConnection%s.
+ *
+ * E.g.
+ *  Signal OnTouch. mSignalConnections contains
+ * <table>
+ * <tr><td> %Callback 0 </td><td> Signal Observer 0  </td></tr>
+ * <tr><td> %Callback 1 </td><td> Signal Observer 1  </td></tr>
+ * <tr><td> %Callback 2 </td><td> Signal Observer 2  </td></tr>
+ * </table>
+ *
+ * OnTouch.Emit() will run callbacks 0, 1 and 2.
+ *
+ * When the signal is destroyed. SignalDisconnected() is called on each Signal Observer.
+ *
+ * Slots are just static or member functions, so have no state. E.g. they can't keep
+ * track of how many signals they are connected to.
+ * If the object owning a slot dies, it must automatically disconnected from all signals.
+ * If it doesn't disconnect and the signal is emitted, there will be a crash.
+ *
+ * To keep track of connections between slots and signals, a Connection tracker is used.
+ * It holds a list of SlotConnections.
+ *
+ * <table>
+ * <tr><td> %Callback 0 </td><td> Slot Observer 0  </td></tr>
+ * <tr><td> %Callback 1 </td><td> Slot Observer 1  </td></tr>
+ * <tr><td> %Callback 2 </td><td> Slot Observer 2  </td></tr>
+ * </table>
+ *
+ * When the connection tracker is destroyed, SlotDisconnected() is called on every slot observer ( signal )
+ * Signals implement the Slot Observer interface, to be told when a slot has disconnected
+ * Connection tracker implements the Signal Observer interface, to be told when a signal has disconnected (died)
+ *
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API BaseSignal : public SlotObserver
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  BaseSignal();
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~BaseSignal();
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const;
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const;
+
+  // Templated Emit functions for the Signal implementations
+
+  /**
+   * @brief Used to guard against nested Emit() calls.
+   * @since_tizen 2.4
+   */
+  struct EmitGuard
+  {
+    /**
+     * @brief Create the guard.
+     *
+     * @since_tizen 2.4
+     * @param[in,out] flag This flag will be set to true during Emit() calls.
+     */
+    EmitGuard( bool& flag );
+
+    /**
+     * @brief Non-virtual destructor.
+     *
+     * @since_tizen 2.4
+     */
+    ~EmitGuard();
+
+    /**
+     * @brief  Determine if an error occured.
+     *
+     * @since_tizen 2.4
+     * @return True if an error occurred i.e. if Emit() was called during Emit()
+     */
+    bool ErrorOccurred();
+
+    bool* mFlag; ///< Pointer to the emit guard flag.
+  };
+
+  /**
+   * @brief Emit a signal with no parameters.
+   *
+   * @since_tizen 2.4
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  void Emit();
+
+  /**
+   * @brief Emit a signal with no parameters.
+   *
+   * @since_tizen 2.4
+   * @return The value returned by the last callback.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Ret >
+  Ret EmitReturn()
+  {
+    Ret returnVal = Ret();
+
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag );
+    if( guard.ErrorOccurred() )
+    {
+      return returnVal;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        returnVal = CallbackBase::ExecuteReturn<Ret>( *callback );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Emit a signal with 1 parameter.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Arg0 >
+  void Emit( Arg0 arg0 )
+  {
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        CallbackBase::Execute<Arg0 >( *callback, arg0 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+  }
+
+  /**
+   * @brief Emit a signal with 1 parameter.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @return The value returned by the last callback.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Ret, typename Arg0 >
+  Ret EmitReturn( Arg0 arg0 )
+  {
+    Ret returnVal = Ret();
+
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return returnVal;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        returnVal = CallbackBase::ExecuteReturn<Ret,Arg0>( *callback, arg0 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Emit a signal with 2 parameters.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @param[in] arg1 The second parameter.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Arg0, typename Arg1 >
+  void Emit( Arg0 arg0, Arg1 arg1 )
+  {
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        CallbackBase::Execute<Arg0,Arg1>( *callback, arg0, arg1 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+  }
+
+  /**
+   * @brief Emit a signal with 2 parameters.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @param[in] arg1 The second parameter.
+   * @return The value returned by the last callback.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Ret, typename Arg0, typename Arg1 >
+  Ret EmitReturn( Arg0 arg0, Arg1 arg1 )
+  {
+    Ret returnVal = Ret();
+
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return returnVal;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1>( *callback, arg0, arg1 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Emit a signal with 3 parameters.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @param[in] arg1 The second parameter.
+   * @param[in] arg2 The third parameter.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Arg0, typename Arg1, typename Arg2 >
+  void Emit( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
+  {
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        CallbackBase::Execute<Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+  }
+
+  /**
+   * @brief Emit a signal with 3 parameters.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first parameter.
+   * @param[in] arg1 The second parameter.
+   * @param[in] arg2 The third parameter.
+   * @return The value returned by the last callback.
+   * @pre Cannot be called from inside the same Signal's Emit methods.
+   */
+  template< typename Ret, typename Arg0, typename Arg1, typename Arg2 >
+  Ret EmitReturn( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
+  {
+    Ret returnVal = Ret();
+
+    // Guards against nested Emit() calls
+    EmitGuard guard( mEmittingFlag ); // Guards against nested Emit() calls
+    if( guard.ErrorOccurred() )
+    {
+      return returnVal;
+    }
+
+    // If more connections are added by callbacks, these are ignore until the next Emit()
+    // Note that count cannot be reduced while iterating
+    const std::size_t initialCount( mSignalConnections.Count() );
+
+    for( std::size_t i = 0; i < initialCount; ++i )
+    {
+      CallbackBase* callback( GetCallback(i) );
+
+      // Note that connections will be set to NULL when disconnected
+      // This is preferable to reducing the connection count while iterating
+      if( callback )
+      {
+        returnVal = CallbackBase::ExecuteReturn<Ret,Arg0,Arg1,Arg2>( *callback, arg0, arg1, arg2 );
+      }
+    }
+
+    // Cleanup NULL values from Connection container
+    CleanupConnections();
+
+    return returnVal;
+  }
+
+  // Connect / Disconnect function for use by Signal implementations
+
+  /**
+   * @brief Called by Signal implementations, when the user calls Signal.Connect( ... )
+   *
+   * @since_tizen 2.4
+   * @param[in] callback A newly allocated callback object (takes ownership).
+   */
+  void OnConnect( CallbackBase* callback );
+
+  /**
+   * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... )
+   *
+   * @since_tizen 2.4
+   * @param[in] callback A newly allocated callback object (takes ownership).
+   */
+  void OnDisconnect( CallbackBase* callback );
+
+  /**
+   * @brief Called by Signal implementations, when the user calls Signal.Connect( ... )
+   *
+   * @since_tizen 2.4
+   * @param[in] tracker The connection tracker.
+   * @param[in] callback A newly allocated callback object (takes ownership).
+   */
+  void OnConnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
+
+  /**
+   * @brief Called by Signal implementations, when the user calls Signal.Disconnect( ... )
+   *
+   * @since_tizen 2.4
+   * @param[in] tracker The connection tracker.
+   * @param[in] callback A newly allocated callback object (takes ownership).
+   */
+  void OnDisconnect( ConnectionTrackerInterface* tracker, CallbackBase* callback );
+
+private: // SlotObserver interface, to be told when a slot disconnects
+
+  /**
+   * @copydoc SlotObserver::SlotDisconnected
+   */
+  virtual void SlotDisconnected( CallbackBase* callback );
+
+private:
+
+  /**
+   * @brief Returns a callback given an index in to the connection array.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionIndex The index of the callback.
+   * @return The callback, or NULL if the connection has been deleted.
+   */
+  CallbackBase* GetCallback( std::size_t connectionIndex ) const;
+
+  /**
+   * @brief Helper to find whether a callback is connected.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The call back object.
+   * @return A valid index if the callback is connected.
+   */
+  int FindCallback( CallbackBase* callback );
+
+  /**
+   * @brief Deletes a connection object from the list of connections.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionIndex The index of the callback.
+   */
+  void DeleteConnection( std::size_t connectionIndex );
+
+  /**
+   * @brief Helper to remove NULL items from mSignalConnections, which is only safe at the end of Emit()
+   * i.e. not from methods which can be called during a signal Emit(), such as Disconnect().
+   * @since_tizen 2.4
+   */
+  void CleanupConnections();
+
+  BaseSignal( const BaseSignal& );                   ///< undefined copy constructor, signals don't support copying.
+  BaseSignal& operator=( const BaseSignal& );        ///< undefined assignment operator
+
+private:
+
+  Dali::Vector< SignalConnection* > mSignalConnections;   ///< Array of connections
+
+  bool mEmittingFlag; ///< Used to guard against nested Emit() calls
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_BASE_SIGNAL_H__
diff --git a/dali/public-api/signals/callback.cpp b/dali/public-api/signals/callback.cpp
new file mode 100644 (file)
index 0000000..841b1df
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/callback.h>
+
+
+namespace Dali
+{
+
+// CallbackBase
+
+CallbackBase::CallbackBase()
+: mImpl( NULL ),
+  mFunction( NULL )
+{
+}
+
+CallbackBase::~CallbackBase()
+{
+  Reset();
+}
+
+CallbackBase::CallbackBase( Function function )
+: mImpl( NULL ),
+  mFunction( function )
+{
+}
+
+CallbackBase::CallbackBase( void* object, MemberFunction function, Dispatcher dispatcher )
+: mMemberFunction( function )
+{
+  mImpl = new CallbackBase::Impl;
+  mImpl->mObjectPointer = object;
+  mImpl->mMemberFunctionDispatcher = dispatcher;
+  mImpl->mDestructorDispatcher = NULL; // object is not owned
+}
+
+CallbackBase::CallbackBase( void* object, MemberFunction function, Dispatcher dispatcher, Destructor destructor )
+: mMemberFunction( function )
+{
+  mImpl = new CallbackBase::Impl;
+  mImpl->mObjectPointer = object;
+  mImpl->mMemberFunctionDispatcher = dispatcher;
+  mImpl->mDestructorDispatcher = destructor; // object is owned
+}
+
+void CallbackBase::Reset()
+{
+  if( mImpl )
+  {
+    // if destructor function is set it means we own this object
+    if ( mImpl->mObjectPointer &&
+         mImpl->mDestructorDispatcher )
+    {
+      // call the destructor dispatcher
+      (*mImpl->mDestructorDispatcher)( mImpl->mObjectPointer );
+    }
+
+    delete mImpl;
+    mImpl = NULL;
+  }
+
+  mFunction = NULL;
+}
+
+// CallbackBase::Impl
+
+CallbackBase::Impl::Impl()
+: mObjectPointer( NULL ),
+  mMemberFunctionDispatcher( NULL ),
+  mDestructorDispatcher( NULL )
+{
+}
+
+// Non-member equality operator
+
+bool operator==( const CallbackBase& lhs, const CallbackBase& rhs )
+{
+  if( lhs.mImpl )
+  {
+    // check it's the same member function / object
+    return ( lhs.mFunction == rhs.mFunction ) &&  ( lhs.mImpl->mObjectPointer == rhs.mImpl->mObjectPointer );
+  }
+  else
+  {
+    // check if it the same C function or a static member function
+    return ( lhs.mFunction == rhs.mFunction );
+  }
+}
+
+} // namespace DALI
diff --git a/dali/public-api/signals/callback.h b/dali/public-api/signals/callback.h
new file mode 100644 (file)
index 0000000..61e718e
--- /dev/null
@@ -0,0 +1,1778 @@
+#ifndef __DALI_CALLBACK_H__
+#define __DALI_CALLBACK_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/signals/functor-delegate.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+class CallbackBase;
+
+/**
+ * @brief Callback base class to hold the data for callback function and member function calls.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API CallbackBase
+{
+public:
+
+  /**
+   * @brief Default constructor
+   * @since_tizen 2.4
+   */
+  CallbackBase();
+
+  /**
+   * @brief Destructor
+   * @since_tizen 2.4
+   */
+  ~CallbackBase();
+
+  /**
+   * @brief Resets the object pointer so that we know not to call methods of this object any more.
+   * @since_tizen 2.4
+   */
+  void Reset();
+
+  /**
+   * @brief Function to call the function or member function dispatcher
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   */
+  static void Execute( CallbackBase& callback )
+  {
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code so the library containing
+    // the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      Dispatcher dispatcher = callback.mImpl->mMemberFunctionDispatcher;
+      (*dispatcher)( callback );
+    }
+    // its also possible to have a member function pointer to a CallbackProvider
+    // that has been deleted, so check if we have impl still
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      (*(callback.mFunction))();
+    }
+    else
+    {
+      DALI_ASSERT_ALWAYS( 0 && "no function to execute" );
+    }
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @return value from the function
+   */
+  template< typename R >
+  static R ExecuteReturn( CallbackBase& callback )
+  {
+    R returnVal = R();
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code so the library containing
+    // the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef R(*Dispatcher)(CallbackBase& base);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      returnVal = (*dispatcher)( callback );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      typedef R(*Function1)();
+      returnVal = (*(reinterpret_cast< Function1 >( callback.mFunction )))();
+    }
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   */
+  template< typename P1 >
+  static void Execute( CallbackBase& callback, P1 param1 )
+  {
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef void(*Dispatcher)(CallbackBase& base,P1);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      (*dispatcher)( callback, param1 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef void(*Function1)(P1);
+      (*(reinterpret_cast< Function1 >( callback.mFunction )))( param1 );
+    }
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   * @return the value from the function
+   */
+  template< typename R, typename P1 >
+  static R ExecuteReturn( CallbackBase& callback, P1 param1 )
+  {
+    R returnVal =  R();
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef R(*Dispatcher)(CallbackBase& base,P1);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      returnVal = (*dispatcher)( callback, param1 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef R(*Function1)(P1);
+      returnVal = (*(reinterpret_cast< Function1 >( callback.mFunction )))( param1 );
+    }
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site.
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   * @param[in] param2 The second parameter to pass into the function.
+   */
+  template< typename P1, typename P2 >
+  static void Execute( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef void(*Dispatcher)(CallbackBase& base,P1,P2);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      (*dispatcher)( callback, param1, param2 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef void(*Function2)(P1,P2);
+      (*(reinterpret_cast< Function2 >( callback.mFunction )))( param1, param2 );
+    }
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   * @param[in] param2 The second parameter to pass into the function.
+   * @return The return value from the function
+   */
+  template< typename R, typename P1, typename P2 >
+  static R ExecuteReturn( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    R returnVal= R();
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef R(*Dispatcher)(CallbackBase& base,P1,P2);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      returnVal = (*dispatcher)( callback, param1, param2 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef R(*Function2)(P1,P2);
+      returnVal = (*(reinterpret_cast< Function2 >( callback.mFunction )))( param1, param2 );
+    }
+
+    return returnVal;
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site.
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   * @param[in] param2 The second parameter to pass into the function.
+   * @param[in] param3 The third parameter to pass into the function.
+   */
+  template< typename P1, typename P2, typename P3 >
+  static void Execute( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef void(*Dispatcher)(CallbackBase& base,P1,P2,P3);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      (*dispatcher)( callback, param1, param2, param3 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef void(*Function2)(P1,P2,P3);
+      (*(reinterpret_cast< Function2 >( callback.mFunction )))( param1, param2, param3 );
+    }
+  }
+
+  /**
+   * @brief Function to call the function or member function dispatcher.
+   *
+   * This function template gets instantiated at the call site
+   * @since_tizen 2.4
+   * @param[in] callback The callback to call.
+   * @param[in] param1 The first parameter to pass into the function.
+   * @param[in] param2 The second parameter to pass into the function.
+   * @param[in] param3 The third parameter to pass into the function.
+   * @return The return value from the function
+   */
+  template< typename R, typename P1, typename P2, typename P3 >
+  static R ExecuteReturn( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    R returnVal= R();
+    // if we point to a function, we can call it directly
+    // otherwise call the dispatcher function that knows the real type of the object
+    // Note that this template dispatcher lives in client code (where the callback was created)
+    // so the library containing the code has to be loaded, otherwise we crash boom bang
+    if( callback.mImpl && callback.mImpl->mObjectPointer )
+    {
+      typedef R(*Dispatcher)(CallbackBase& base,P1,P2,P3);
+      Dispatcher dispatcher = reinterpret_cast< Dispatcher >( callback.mImpl->mMemberFunctionDispatcher );
+      returnVal = (*dispatcher)( callback, param1, param2, param3 );
+    }
+    else if( !callback.mImpl && callback.mFunction )
+    {
+      // convert function type
+      typedef R(*Function2)(P1,P2,P3);
+      returnVal = (*(reinterpret_cast< Function2 >( callback.mFunction )))( param1, param2, param3 );
+    }
+
+    return returnVal;
+  }
+
+protected: // Constructors for deriving classes
+
+  /**
+   * @brief Function with static linkage
+   * @since_tizen 2.4
+   */
+  typedef void(*Function)(void);
+
+  /**
+   * @brief Member function
+   * @since_tizen 2.4
+   */
+  typedef void (CallbackBase::*MemberFunction)( void );
+
+  /**
+   * @brief Used to call the correct member function
+   * @since_tizen 2.4
+   */
+  typedef void (*Dispatcher)( CallbackBase& base );
+
+  /**
+   * @brief Used to destroy mObjectPointer (NULL if not mObjectPointer is not owned)
+   * @since_tizen 2.4
+   */
+  typedef void(*Destructor)(void* object);
+
+  /**
+   * @brief Copy constructor operator not declared.
+   * @since_tizen 2.4
+   */
+  CallbackBase( const CallbackBase& rhs );
+  /**
+   * @brief assignment operator not declared.
+   * @since_tizen 2.4
+   */
+  const CallbackBase& operator=( const CallbackBase& rhs );
+
+  /**
+   * @brief Constructor for function with static linkage.
+   *
+   * @since_tizen 2.4
+   * @param[in] function The function to call.
+   */
+  CallbackBase( Function function );
+
+  /**
+   * @brief Constructor for member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to call (not owned).
+   * @param[in] function The member function of the object.
+   * @param[in] dispatcher Used to call the actual object.
+   */
+  CallbackBase( void* object, MemberFunction function, Dispatcher dispatcher );
+
+  /**
+   * @brief Constructor for member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to call (owned).
+   * @param[in] function The member function of the object.
+   * @param dispatcher Used to call the actual object.
+   * @param destructor Used to delete the owned object.
+   */
+  CallbackBase( void* object, MemberFunction function, Dispatcher dispatcher, Destructor destructor );
+
+public: // Data for deriving classes & Dispatchers
+
+  /**
+   * @brief struct to hold the extra data needed for member functions.
+   * @since_tizen 2.4
+   */
+  struct Impl
+  {
+    Impl();                               ///< Default constructor
+
+    void* mObjectPointer;                 ///< Object whose member function will be called. Not owned if mDestructorDispatcher is NULL.
+    Dispatcher mMemberFunctionDispatcher; ///< Dispatcher for member functions
+    Destructor mDestructorDispatcher;     ///< Destructor for owned objects. NULL if mDestructorDispatcher is not owned.
+  };
+  Impl* mImpl;                            ///< Implementation pointer
+
+  union
+  {
+    MemberFunction mMemberFunction;       ///< Pointer to member function
+    Function mFunction;                   ///< Static function
+  };
+};
+
+/**
+ * @brief Non-member equality operator
+ * @since_tizen 2.4
+ */
+bool operator==( const CallbackBase& lhs, const CallbackBase& rhs );
+
+/**
+ * @brief Dispatcher to delete an object.
+ * @since_tizen 2.4
+ */
+template< class T >
+struct Destroyer
+{
+  /**
+   * @brief Dispatcher to delete an object.
+   * @since_tizen 2.4
+   */
+  static void Delete( void* object )
+  {
+    // CallbackBase owns the object but we're the only one who knows the real type so need
+    // to delete by "downcasting" from void* to the correct type
+    delete reinterpret_cast< T* >( object );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T >
+struct Dispatcher0
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   */
+  static void Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)();
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1 >
+struct Dispatcher1
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(P1);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)( param1 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2 >
+struct Dispatcher2
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(P1, P2);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)( param1, param2 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename P3 >
+struct Dispatcher3
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(P1, P2, P3);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)( param1, param2, param3 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename R >
+struct DispatcherReturn0
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @return the value.
+   */
+  static R Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef R(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    return (object->*function)();
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1 >
+struct DispatcherReturn1
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef R(T::*MemberFunction)(P1);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    return (object->*function)( param1 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2 >
+struct DispatcherReturn2
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef R(T::*MemberFunction)(P1, P2);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    return (object->*function)( param1, param2 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call the actual member function.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2, typename P3 >
+struct DispatcherReturn3
+{
+  /**
+   * @brief Call an actual member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef R(T::*MemberFunction)(P1, P2, P3);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    return (object->*function)( param1, param2, param3 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T >
+struct FunctorDispatcher0
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   */
+  static void Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    (*object)();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1 >
+struct FunctorDispatcher1
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    (*object)( param1 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2 >
+struct FunctorDispatcher2
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    (*object)( param1, param2 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename P3 >
+struct FunctorDispatcher3
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    (*object)( param1, param2, param3 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename R >
+struct FunctorDispatcherReturn0
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @return the value.
+   */
+  static R Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    return (*object)();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1 >
+struct FunctorDispatcherReturn1
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    return (*object)( param1 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2 >
+struct FunctorDispatcherReturn2
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    return (*object)( param1, param2 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2, typename P3 >
+struct FunctorDispatcherReturn3
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    return (*object)( param1, param2, param3 );
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ * This variant calls a specific void() member function.
+ * @since_tizen 2.4
+ */
+template< class T >
+struct VoidFunctorDispatcher0
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   */
+  static void Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, ignoring any signal parameters
+ * @since_tizen 2.4
+ */
+template< class T, typename P1 >
+struct VoidFunctorDispatcher1
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, ignoring any signal parameters
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2 >
+struct VoidFunctorDispatcher2
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, ignoring any signal parameters
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename P3 >
+struct VoidFunctorDispatcher3
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   */
+  static void Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, and returns a default-constructed value
+ * @since_tizen 2.4
+ */
+template< class T, typename R >
+struct VoidFunctorDispatcherReturn0
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @return the value.
+   */
+  static R Dispatch( CallbackBase& callback )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+    return R();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, and returns a default-constructed value
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1 >
+struct VoidFunctorDispatcherReturn1
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+    return R();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, and returns a default-constructed value
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2 >
+struct VoidFunctorDispatcherReturn2
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+    return R();
+  }
+};
+
+/**
+ * @brief Dispatcher to call a functor.
+ *
+ * This variant calls a void() member, and returns a default-constructed value
+ * @since_tizen 2.4
+ */
+template< class T, typename R, typename P1, typename P2, typename P3 >
+struct VoidFunctorDispatcherReturn3
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback information.
+   * @param[in] param1 The first parameter to pass to the real member function.
+   * @param[in] param2 The second parameter to pass to the real member function.
+   * @param[in] param3 The third parameter to pass to the real member function.
+   * @return The return value from the function
+   */
+  static R Dispatch( CallbackBase& callback, P1 param1, P2 param2, P3 param3 )
+  {
+    // "downcast" the object and function type back to the correct ones
+    T* object = reinterpret_cast< T* >( callback.mImpl->mObjectPointer );
+    typedef void(T::*MemberFunction)(void);
+    MemberFunction function = reinterpret_cast< MemberFunction >( callback.mMemberFunction );
+    (object->*function)(/*ignore params*/);
+    return R();
+  }
+};
+
+/**
+ * @brief Thin template to provide type safety for member function callbacks.
+ *
+ * version with two parameters and return value
+ * @since_tizen 2.4
+ */
+template< class T >
+class Callback : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   *
+   * @since_tizen 2.4
+   */
+  Callback()
+  : CallbackBase()
+  {
+  }
+
+  /**
+   * @brief Constructor for member function.
+   *
+   * Copies the function object.
+   * @since_tizen 2.4
+   * @param[in] object The object to call.
+   * @param[in] memberFunction The member function of the object.
+   */
+  Callback( T* object, void(T::*memberFunction)(void) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &Dispatcher0<T>::Dispatch ) ) { }
+  template< typename P1 >
+  Callback( T* object, void(T::*memberFunction)(P1) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &Dispatcher1<T,P1>::Dispatch ) ) { }
+  template< typename P1, typename P2 >
+  Callback( T* object, void(T::*memberFunction)(P1, P2) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &Dispatcher2<T,P1,P2>::Dispatch ) ) { }
+  template< typename P1, typename P2, typename P3 >
+  Callback( T* object, void(T::*memberFunction)(P1, P2, P3) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &Dispatcher3<T,P1,P2,P3>::Dispatch ) ) { }
+  template< typename R >
+  Callback( T* object, R(T::*memberFunction)(void) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &DispatcherReturn0<T,R>::Dispatch ) ) { }
+  template< typename R, typename P1 >
+  Callback( T* object, R(T::*memberFunction)(P1) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &DispatcherReturn1<T,R,P1>::Dispatch ) ) { }
+  template< typename R, typename P1, typename P2 >
+  Callback( T* object, R(T::*memberFunction)(P1, P2) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &DispatcherReturn2<T,R,P1,P2>::Dispatch ) ) { }
+  template< typename R, typename P1, typename P2, typename P3 >
+  Callback( T* object, R(T::*memberFunction)(P1, P2, P3) )
+  : CallbackBase( object,
+                  reinterpret_cast< CallbackBase::MemberFunction >( memberFunction ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &DispatcherReturn3<T,R,P1,P2,P3>::Dispatch ) ) { }
+
+};
+
+/**
+ * @brief Specializations for static function callbacks.
+ * @since_tizen 2.4
+ */
+class CallbackFunction : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  CallbackFunction()
+  : CallbackBase()
+  {
+  }
+
+  /**
+   * @brief Constructors for functions with static linkage.
+   *
+   * @since_tizen 2.4
+   * @param[in] function The function to call.
+   */
+  CallbackFunction( void(*function)() )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename R >
+  CallbackFunction( R(*function)() )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1 >
+  CallbackFunction( void(*function)(P1) )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1, typename R >
+  CallbackFunction( R(*function)(P1)  )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1, typename P2 >
+  CallbackFunction( void(*function)(P1,P2)  )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1, typename P2, typename R >
+  CallbackFunction( R(*function)(P1,P2) )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1, typename P2, typename P3 >
+  CallbackFunction( void(*function)(P1,P2,P3)  )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+  template< typename P1, typename P2, typename P3, typename R >
+  CallbackFunction( R(*function)(P1,P2,P3) )
+  : CallbackBase( reinterpret_cast< CallbackBase::Function >( function ) )
+  { }
+
+};
+
+/**
+ * @brief Specializations for function object callbacks.
+ * @since_tizen 2.4
+ */
+template< class T >
+class CallbackFunctor0 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctor0( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcher0<T>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+class CallbackFunctorDelegate0 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object A newly allocated object (ownership is transferred).
+   */
+  CallbackFunctorDelegate0( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcher0<FunctorDelegate>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature.
+ * @since_tizen 2.4
+ */
+template< class T, typename P1 >
+class CallbackFunctor1 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctor1( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcher1<T,P1>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods.
+ * @since_tizen 2.4
+ */
+template< typename P1 >
+class CallbackFunctorDelegate1 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegate1( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcher1<FunctorDelegate,P1>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2 >
+class CallbackFunctor2 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctor2( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcher2<T,P1,P2>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename P1, typename P2 >
+class CallbackFunctorDelegate2 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegate2( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcher2<FunctorDelegate,P1,P2>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename P3 >
+class CallbackFunctor3 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctor3( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcher3<T,P1,P2,P3>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename P1, typename P2, typename P3 >
+class CallbackFunctorDelegate3 : public CallbackBase
+{
+public:
+
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegate3( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcher3<FunctorDelegate,P1,P2,P3>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename R >
+class CallbackFunctorReturn0 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorReturn0( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcherReturn0<T,R>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename R >
+class CallbackFunctorDelegateReturn0 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegateReturn0( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcherReturn0<FunctorDelegate,R>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename R >
+class CallbackFunctorReturn1 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorReturn1( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcherReturn1<T,R,P1>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename P1, typename R >
+class CallbackFunctorDelegateReturn1 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegateReturn1( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcherReturn1<FunctorDelegate,R,P1>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename R >
+class CallbackFunctorReturn2 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorReturn2( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcherReturn2<T,R,P1,P2>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename P1, typename P2, typename R >
+class CallbackFunctorDelegateReturn2 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegateReturn2( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcherReturn2<FunctorDelegate,R,P1,P2>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for matching callbacks to signal signature
+ * @since_tizen 2.4
+ */
+template< class T, typename P1, typename P2, typename P3, typename R >
+class CallbackFunctorReturn3 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorReturn3( const T& object )
+  : CallbackBase( reinterpret_cast< void* >( new T( object ) ), // copy the object
+                  NULL, // uses operator() instead of member function
+                  reinterpret_cast< CallbackBase::Dispatcher >( &FunctorDispatcherReturn3<T,R,P1,P2,P3>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<T>::Delete ) ) { }
+};
+
+/**
+ * @brief Function object callback for connecting void() methods
+ * @since_tizen 2.4
+ */
+template< typename P1, typename P2, typename P3, typename R >
+class CallbackFunctorDelegateReturn3 : public CallbackBase
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * This variant calls a void() member, ignoring any signal parameters.
+   * @since_tizen 2.4
+   * @param[in] object The object to copy.
+   */
+  CallbackFunctorDelegateReturn3( FunctorDelegate* object )
+  : CallbackBase( reinterpret_cast< void* >( object ), // transfer ownership
+                  reinterpret_cast< CallbackBase::MemberFunction >( &FunctorDelegate::Execute ),
+                  reinterpret_cast< CallbackBase::Dispatcher >( &VoidFunctorDispatcherReturn3<FunctorDelegate,R,P1,P2,P3>::Dispatch ),
+                  reinterpret_cast< CallbackBase::Destructor >( &Destroyer<FunctorDelegate>::Delete ) ) { }
+};
+
+// Callback creation thin templates
+
+/**
+ * @brief Creates a callback from a C function or static member function with no parameters.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+inline CallbackBase* MakeCallback( void(*function)(void) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with one parameter.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename P1 >
+inline CallbackBase* MakeCallback( void(*function)(P1) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with no parameters and a return type.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename R >
+inline CallbackBase* MakeCallback( R(*function)(void) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with one parameter and a return type.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename R, typename P1 >
+inline CallbackBase* MakeCallback( R(*function)(P1) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with two parameters.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename P1, typename P2 >
+inline CallbackBase* MakeCallback( void(*function)(P1,P2) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with two parameters and a return type.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename R, typename P1, typename P2 >
+inline CallbackBase* MakeCallback( R(*function)(P1,P2) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with three parameters.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename P1, typename P2, typename P3 >
+inline CallbackBase* MakeCallback( void(*function)(P1,P2,P3) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a C function or static member function with three parameters and a return type.
+ *
+ * @since_tizen 2.4
+ * @param[in] function The function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< typename R, typename P1, typename P2, typename P3 >
+inline CallbackBase* MakeCallback( R(*function)(P1,P2,P3) )
+{
+  return new CallbackFunction( function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with no parameters.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T >
+inline CallbackBase* MakeCallback( T* object, void(T::*function)(void) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with one parameter.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1 >
+inline CallbackBase* MakeCallback( T* object, void(T::*function)(P1) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with two parameters.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1, typename P2 >
+inline CallbackBase* MakeCallback( T* object, void(T::*function)(P1,P2) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with three parameters.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1, typename P2, typename P3 >
+inline CallbackBase* MakeCallback( T* object, void(T::*function)(P1,P2,P3) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with no parameters and a return type.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename R >
+inline CallbackBase* MakeCallback( T* object, R(T::*function)() )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with one parameter and a return type.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1, typename R >
+inline CallbackBase* MakeCallback( T* object, R(T::*function)(P1) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with two parameters and a return type.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1, typename P2, typename R >
+inline CallbackBase* MakeCallback( T* object, R(T::*function)(P1,P2) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class member function with three parameters and a return type.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, typename P1, typename P2, typename P3, typename R >
+inline CallbackBase* MakeCallback( T* object, R(T::*function)(P1,P2,P3) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @brief Creates a callback from a class's parent member function with no parameters.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, class Base >
+inline CallbackBase* MakeCallback( T* object, void(Base::*function)(void) )
+{
+  return new Callback< T >( object, function );
+}
+/**
+ * @brief Creates a callback from a class's parent member function with no parameters.
+ *
+ * requires the function to be member of the same class
+ * @since_tizen 2.4
+ * @param[in] object The object to call.
+ * @param[in] function The member function to call.
+ * @return a newly allocated Callback object, ownership transferred to caller
+ */
+template< class T, class Base >
+inline CallbackBase* MakeCallback( T& object, void(Base::*function)(void) )
+{
+  return new Callback< T >( object, function );
+}
+
+/**
+ * @}
+ */
+} // namespace DALI
+
+#endif // __DALI_CALLBACK_H__
diff --git a/dali/public-api/signals/connection-tracker-interface.cpp b/dali/public-api/signals/connection-tracker-interface.cpp
new file mode 100644 (file)
index 0000000..a100088
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/signals/connection-tracker-interface.h>
+
+namespace Dali
+{
+
+ConnectionTrackerInterface::ConnectionTrackerInterface()
+{
+}
+
+ConnectionTrackerInterface::~ConnectionTrackerInterface()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/connection-tracker-interface.h b/dali/public-api/signals/connection-tracker-interface.h
new file mode 100644 (file)
index 0000000..25575c1
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef __DALI_CONNECTION_TRACKER_INTERFACE_H__
+#define __DALI_CONNECTION_TRACKER_INTERFACE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/signals/signal-slot-observers.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+/**
+ * @brief Interface used to track connections between signals and slots.
+ *
+ * Performs automatic connection and disconnection when either the slot or signal dies.
+ *
+ * @code
+ * class MyApp : public ConnectionTracker
+ * {
+ *   Button.ClickedSignal().Connect( this, &MyApp::OnPress );
+ *
+ *   void OnPress()
+ *   {
+ *     std::cout << "hello world" << std::endl;
+ *   }
+ * }
+ * @endcode
+ *
+ * When MyApp is destroyed, it automatically disconnects from Button.ClickSignal.
+ * It provides a signal observer interface, to observer when signals are destroyed
+ * e.g. if Button object is destroyed while it is still connected.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ConnectionTrackerInterface : public SignalObserver
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  ConnectionTrackerInterface();
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~ConnectionTrackerInterface();
+
+  /**
+   * @brief Called when a signal is connected.
+   *
+   * @since_tizen 2.4
+   * @param[in] slotObserver The slot observer i.e. a signal. Ownership is not passed.
+   * @param[in] callback The call back. Ownership is not passed.
+   */
+  virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback ) = 0;
+
+private:
+
+  ConnectionTrackerInterface( const ConnectionTrackerInterface& );            ///< undefined copy constructor
+  ConnectionTrackerInterface& operator=( const ConnectionTrackerInterface& ); ///< undefined assignment operator
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONNECTION_TRACKER_INTERFACE_H__
diff --git a/dali/public-api/signals/connection-tracker.cpp b/dali/public-api/signals/connection-tracker.cpp
new file mode 100644 (file)
index 0000000..fd7514e
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/connection-tracker.h>
+
+#include <dali/public-api/signals/callback.h>
+#include <dali/public-api/signals/signal-slot-observers.h>
+#include <dali/public-api/signals/signal-slot-connections.h>
+
+namespace Dali
+{
+
+ConnectionTracker::ConnectionTracker()
+{
+}
+
+ConnectionTracker::~ConnectionTracker()
+{
+  DisconnectAll();
+}
+
+void ConnectionTracker::DisconnectAll()
+{
+  std::size_t size = mConnections.Size();
+
+  for( std::size_t i = 0; i< size; ++i )
+  {
+    SlotConnection* connection = mConnections[i];
+
+    // Tell the signal that the slot is disconnected
+    connection->GetSlotObserver()->SlotDisconnected( connection->GetCallback() );
+
+    delete connection;
+  }
+
+  mConnections.Clear();
+}
+
+void ConnectionTracker::SignalConnected( SlotObserver* slotObserver, CallbackBase* callback )
+{
+  SlotConnection* connection = new SlotConnection( slotObserver, callback );
+  mConnections.PushBack( connection );
+}
+
+void ConnectionTracker::SignalDisconnected( SlotObserver* signal, CallbackBase* callback )
+{
+  std::size_t size = mConnections.Size();
+
+  for( std::size_t i = 0; i< size; ++i )
+  {
+    SlotConnection* connection = mConnections[i];
+
+    // Pointer comparison i.e. SignalConnection contains pointer to same callback instance
+    if( connection->GetCallback() == callback )
+    {
+      // Remove from connection list
+      mConnections.Erase( mConnections.Begin() + i );
+
+      // Delete connection
+      delete connection;
+
+      // Disconnection complete
+      return;
+    }
+  }
+
+  DALI_ASSERT_ALWAYS( false && "Callback lost in SignalDisconnected()" );
+}
+
+std::size_t ConnectionTracker::GetConnectionCount() const
+{
+  return mConnections.Size();
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/connection-tracker.h b/dali/public-api/signals/connection-tracker.h
new file mode 100644 (file)
index 0000000..3f8d5e8
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef __DALI_CONNECTION_TRACKER_H__
+#define __DALI_CONNECTION_TRACKER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/common/dali-vector.h>
+#include <dali/public-api/signals/connection-tracker-interface.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+class CallbackBase;
+class SlotObserver;
+class SlotConnection;
+
+/**
+ * @brief Connection tracker concrete implementation
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API ConnectionTracker : public ConnectionTrackerInterface
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  ConnectionTracker();
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~ConnectionTracker();
+
+  /**
+   * @brief Disconnect all signals from this object.
+   * @since_tizen 2.4
+   */
+  void DisconnectAll();
+
+  /**
+   * @copydoc ConnectionTrackerInterface::SignalConnected
+   */
+  virtual void SignalConnected( SlotObserver* slotObserver, CallbackBase* callback );
+
+  /**
+   * @copydoc ConnectionTrackerInterface::SignalDisconnected
+   */
+  virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback );
+
+  /**
+   * @brief returns the connection count
+   * @since_tizen 2.4
+   * @return the connection count
+   */
+  std::size_t GetConnectionCount() const;
+
+private:
+
+  ConnectionTracker( const ConnectionTracker& );            ///< undefined copy constructor
+  ConnectionTracker& operator=( const ConnectionTracker& ); ///< undefined assignment operator
+
+private:
+
+  Dali::Vector< SlotConnection* > mConnections; ///< Vector of connection pointers
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_CONNECTION_TRACKER_H__
diff --git a/dali/public-api/signals/dali-signal.h b/dali/public-api/signals/dali-signal.h
new file mode 100644 (file)
index 0000000..f432ab2
--- /dev/null
@@ -0,0 +1,1491 @@
+#ifndef __DALI_SIGNAL_H__
+#define __DALI_SIGNAL_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+/**
+ * @brief The class should implement Dali::ConnectionTrackerInterface, or inherit from Dali::ConnectionTracker.
+ * This enforces automatic disconnection when an object is destroyed, so you don't have
+ * to manually disconnect from signals.
+ *
+ * Alternatively, you can use a Dali::SlotDelegate if you don't want to inherit.
+ *
+ * E.g:
+ * @code
+ * class MyClass : public ConnectionTracker
+ * {
+ *
+ *   void Callback( Actor actor, const TouchEvent& event )
+ *   {
+ *     ...
+ *   }
+ *
+ *   void Init()
+ *   {
+ *     Actor actor = Actor::New();
+ *
+ *     actor.TouchedSignal().Connect( this, &MyClass::Callback );
+ *   }
+ *
+ *   ~MyClass()
+ *   {
+ *     // ConnectionTracker base class automatically disconnects
+ *   }
+ * }
+ * @endcode
+ * @since_tizen 2.4
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/signals/callback.h>
+#include <dali/public-api/signals/signal-slot-connections.h>
+#include <dali/public-api/signals/slot-delegate.h>
+#include <dali/public-api/signals/base-signal.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+/**
+ * @brief Base Template class to provide signals.
+ *
+ * To create a signal for this class, you first have to define a typedef within your handle's scope:
+ * @code
+ * class MyHandle : public Handle
+ * {
+ * public:
+ *
+ *   // Typedefs
+ *
+ *   typedef Signal< void ()> VoidSignalType;         ///< For signals that require no parameters and no return value
+ *   typedef Signal< bool ()> BoolSignalType;         ///< For signals that do not need parameters but require a boolean return
+ *   typedef Signal< void ( float )> ParamSignalType; ///< For signals that need a float as a parameter but no return value
+ *
+ *   ...
+ *
+ * public:
+ *
+ *   // Signals
+ *
+ *   VoidSignalType&  VoidSignal();
+ *   BoolSignalType&  BoolSignal();
+ *   ParamSignalType& ParamSignal();
+ *
+ *   ...
+ * };
+ * @endcode
+ * The methods are required in the handle class so that the application writer can retrieve the Signal in order to connect/disconnect.
+ *
+ * In the implementation class, the members should be defined and the methods should be provided to retrieve the signal itself.
+ * These will be called by the equivalent methods in the MyHandle class.
+ * @code
+ * class MyObject : public Object
+ * {
+ *   ...
+ *
+ * public:
+ *
+ *   MyHandle::VoidSignalType&  VoidSignal()
+ *   {
+ *     return mVoidSignal;
+ *   }
+ *
+ *   MyHandle::BoolSignalType&  BoolSignal()
+ *   {
+ *     return mBoolSignal;
+ *   }
+ *
+ *   MyHandle::ParamSignalType& ParamSignal()
+ *   {
+ *     return mParamSignal;
+ *   }
+ *
+ * private:
+ *
+ *   // Signals
+ *   MyHandle::VoidSignalType   mVoidSignal;
+ *   MyHandle::BoolSignalType   mBoolSignal;
+ *   MyHandle::ParamSignalType  mParamSignal;
+ *
+ *   ...
+ * };
+ * @endcode
+ * @since_tizen 2.4
+ */
+template< typename _Signature >
+class Signal
+{
+};
+
+/**
+ * @brief A template for Signals with no parameters or return value.
+ * @since_tizen 2.4
+ */
+template <>
+class Signal< void () >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( void (*func)() )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( void (*func)() )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, void (X::*func)() )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, void (X::*func)() )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, void (X::*func)() )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, void (X::*func)() )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctor0< X >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegate0( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   * @since_tizen 2.4
+   */
+  void Emit()
+  {
+    mImpl.Emit();
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< The base signal implementation
+};
+
+/**
+ * @brief A template for Signals with no parameters and a return value.
+ * @since_tizen 2.4
+ */
+template < typename Ret >
+class Signal< Ret() >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( Ret (*func)() )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( Ret (*func)() )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, Ret (X::*func)() )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, Ret (X::*func)() )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, Ret (X::*func)() )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, Ret (X::*func)() )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorReturn0< X, Ret >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegateReturn0< Ret >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @return The value returned by the last callback, or a default constructed value if no callbacks are connected.
+   */
+  Ret Emit()
+  {
+    return mImpl.EmitReturn< Ret >();
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 1 parameter.
+ * @since_tizen 2.4
+ */
+template < typename Arg0 >
+class Signal< void ( Arg0 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( void (*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( void (*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, void (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, void (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctor1< X, Arg0 >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegate1< Arg0 >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   */
+  void Emit( Arg0 arg0 )
+  {
+    mImpl.Emit< Arg0 >( arg0 );
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 1 parameter and a return value.
+ * @since_tizen 2.4
+ */
+template < typename Ret, typename Arg0 >
+class Signal< Ret( Arg0 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( Ret (*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( Ret (*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, Ret (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, Ret (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorReturn1< X, Arg0, Ret >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegateReturn1< Arg0, Ret >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   * @return The value returned by the last callback, or a default constructed value if no callbacks are connected.
+   */
+  Ret Emit( Arg0 arg0 )
+  {
+    return mImpl.EmitReturn< Ret,Arg0 >(arg0);
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 2 parameters.
+ *
+ * @since_tizen 2.4
+ */
+template < typename Arg0, typename Arg1 >
+class Signal< void ( Arg0, Arg1 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   *
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   *
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( void (*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( void (*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, void (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, void (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctor2< X, Arg0, Arg1 >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegate2< Arg0, Arg1 >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   * @param[in] arg1 The second value to pass to callbacks.
+   */
+  void Emit( Arg0 arg0, Arg1 arg1 )
+  {
+    mImpl.Emit< Arg0,Arg1 >( arg0, arg1 );
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 2 parameters and a return value.
+ * @since_tizen 2.4
+ */
+template < typename Ret, typename Arg0, typename Arg1 >
+class Signal< Ret( Arg0, Arg1 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( Ret (*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( Ret (*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, Ret (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, Ret (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0, Arg1 arg1 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorReturn2< X, Arg0, Arg1, Ret >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegateReturn2< Arg0, Arg1, Ret >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   * @param[in] arg1 The second value to pass to callbacks.
+   * @return The value returned by the last callback, or a default constructed value if no callbacks are connected.
+   */
+  Ret Emit( Arg0 arg0, Arg1 arg1 )
+  {
+    return mImpl.EmitReturn< Ret,Arg0,Arg1 >( arg0, arg1 );
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 3 parameters.
+ * @since_tizen 2.4
+ */
+template < typename Arg0, typename Arg1, typename Arg2 >
+class Signal< void ( Arg0, Arg1, Arg2 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( void (*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( void (*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, void (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, void (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, void (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctor3< X, Arg0, Arg1, Arg2 >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegate3< Arg0, Arg1, Arg2 >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   * @param[in] arg1 The second value to pass to callbacks.
+   * @param[in] arg2 The third value to pass to callbacks.
+   */
+  void Emit( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
+  {
+    mImpl.Emit< Arg0,Arg1,Arg2 >( arg0, arg1, arg2 );
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @brief A template for Signals with 2 parameters and a return value.
+ * @since_tizen 2.4
+ */
+template < typename Ret, typename Arg0, typename Arg1, typename Arg2 >
+class Signal< Ret( Arg0, Arg1, Arg2 ) >
+{
+public:
+
+  /**
+   * @brief Default constructor.
+   * @since_tizen 2.4
+   */
+  Signal()
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   * @since_tizen 2.4
+   */
+  ~Signal()
+  {
+  }
+
+  /**
+   * @brief Query whether there are any connected slots.
+   *
+   * @since_tizen 2.4
+   * @return True if there are any slots connected to the signal.
+   */
+  bool Empty() const
+  {
+    return mImpl.Empty();
+  }
+
+  /**
+   * @brief Query the number of slots.
+   *
+   * @since_tizen 2.4
+   * @return The number of slots connected to this signal.
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mImpl.GetConnectionCount();
+  }
+
+  /**
+   * @brief Connect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to connect.
+   */
+  void Connect( Ret (*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Disconnect a function.
+   *
+   * @since_tizen 2.4
+   * @param[in] func The function to disconnect.
+   */
+  void Disconnect( Ret (*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( MakeCallback( func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( X* obj, Ret (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] obj An object which must implement the ConnectionTrackerInterface.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( X* obj, Ret (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( obj, MakeCallback( obj, func ) );
+  }
+
+  /**
+   * @brief Connect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to connect.
+   */
+  template<class X>
+  void Connect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnConnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Disconnect a member function.
+   *
+   * @since_tizen 2.4
+   * @param[in] delegate A slot delegate.
+   * @param[in] func The member function to disconnect.
+   */
+  template<class X>
+  void Disconnect( SlotDelegate<X>& delegate, Ret (X::*func)( Arg0 arg0, Arg1 arg1, Arg2 arg2 ) )
+  {
+    mImpl.OnDisconnect( delegate.GetConnectionTracker(), MakeCallback( delegate.GetSlot(), func ) );
+  }
+
+  /**
+   * @brief Connect a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] func The function object to copy.
+   */
+  template<class X>
+  void Connect( ConnectionTrackerInterface* connectionTracker, const X& func )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorReturn3< X, Arg0, Arg1, Arg2, Ret >( func ) );
+  }
+
+  /**
+   * @brief Connect a function object using FunctorDelegate.
+   *
+   * @since_tizen 2.4
+   * @param[in] connectionTracker A connection tracker which can be used to disconnect.
+   * @param[in] delegate A newly allocated FunctorDelegate (ownership is taken).
+   */
+  void Connect( ConnectionTrackerInterface* connectionTracker, FunctorDelegate* delegate )
+  {
+    mImpl.OnConnect( connectionTracker, new CallbackFunctorDelegateReturn3< Arg0, Arg1, Arg2, Ret >( delegate ) );
+  }
+
+  /**
+   * @brief Emit the signal.
+   *
+   * @since_tizen 2.4
+   * @param[in] arg0 The first value to pass to callbacks.
+   * @param[in] arg1 The second value to pass to callbacks.
+   * @param[in] arg2 The third value to pass to callbacks.
+   * @return The value returned by the last callback, or a default constructed value if no callbacks are connected.
+   */
+  Ret Emit( Arg0 arg0, Arg1 arg1, Arg2 arg2 )
+  {
+    return mImpl.EmitReturn< Ret,Arg0,Arg1,Arg2 >( arg0, arg1, arg2 );
+  }
+
+private:
+
+  Signal( const Signal& );                   ///< undefined copy constructor, signals don't support copying.
+  Signal& operator=( const Signal& );        ///< undefined assignment operator
+
+private:
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  BaseSignal mImpl; ///< Implementation
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SIGNAL_H__
diff --git a/dali/public-api/signals/functor-delegate.cpp b/dali/public-api/signals/functor-delegate.cpp
new file mode 100644 (file)
index 0000000..b8baee1
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/functor-delegate.h>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/compile-time-assert.h>
+
+namespace Dali
+{
+namespace
+{
+/**
+ * our implementation currently relies on C function pointer to be the size of void*
+ * in FunctorDispatcher we pass the C function as void* as the code is common between member
+ * functions and regular functions.
+ * If this assert fails, please implement the template specialisation for C functions.
+ */
+#if !defined(EMSCRIPTEN)
+DALI_COMPILE_TIME_ASSERT( sizeof(void*) == sizeof( &FunctorDispatcher<void>::Dispatch ) );
+#endif
+}
+
+FunctorDelegate::~FunctorDelegate()
+{
+  if( mFunctorPointer )
+  {
+    (*mDestructorDispatcher)( mFunctorPointer );
+  }
+}
+
+void FunctorDelegate::Execute()
+{
+  if( mFunctorPointer )
+  {
+    Dispatcher dispatcher = mMemberFunctionDispatcher;
+    (*dispatcher)( mFunctorPointer );
+  }
+}
+
+FunctorDelegate::FunctorDelegate( void* objectPtr, Dispatcher dispatcher, Destructor destructor )
+: mFunctorPointer( objectPtr ),
+  mMemberFunctionDispatcher( dispatcher ),
+  mDestructorDispatcher( destructor )
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/functor-delegate.h b/dali/public-api/signals/functor-delegate.h
new file mode 100644 (file)
index 0000000..1d838a6
--- /dev/null
@@ -0,0 +1,154 @@
+#ifndef __DALI_FUNCTOR_DELEGATE_H__
+#define __DALI_FUNCTOR_DELEGATE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+/**
+ * @brief Dispatcher to call a functor
+ * @since_tizen 2.4
+ */
+template< typename T >
+struct FunctorDispatcher
+{
+  /**
+   * @brief Call a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] functorPtr The functor to call.
+   */
+  static void Dispatch( void* functorPtr )
+  {
+    // "downcast" the functor type back to the correct one
+    T* functor = reinterpret_cast< T* >( functorPtr );
+    (*functor)();
+  }
+};
+
+/**
+ * @brief Dispatcher to delete a functor object
+ * @since_tizen 2.4
+ */
+template< typename T >
+struct FunctorDestroyer
+{
+  /**
+   * @brief Dispatcher to delete an object
+   * @since_tizen 2.4
+   */
+  static void Delete( void* functorPtr )
+  {
+    // FunctorDelegate owns the object but we're the only one who knows the real type so need
+    // to delete by "downcasting" from void* to the correct type
+    delete reinterpret_cast< T* >( functorPtr );
+  }
+};
+
+/**
+ * @brief Used to connect a void() functor to a signal via BaseObject::SignalConnect()
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API FunctorDelegate
+{
+public:
+
+  /**
+   * @brief Constructor which copies a function object.
+   *
+   * @since_tizen 2.4
+   * @param[in] functor The functor object to copy, either a class with operator() or a C function
+   * @return A pointer to the new function object
+   */
+  template< typename T >
+  static FunctorDelegate* New( const T& functor )
+  {
+    return new FunctorDelegate( reinterpret_cast< void* >( new T( functor ) ), // heap allocate the functor
+                                reinterpret_cast< FunctorDelegate::Dispatcher >( &FunctorDispatcher<T>::Dispatch ),
+                                reinterpret_cast< FunctorDelegate::Destructor >( &FunctorDestroyer<T>::Delete ) );
+  }
+
+  /**
+   * @brief Non-virtual destructor; not intended as a base class.
+   * @since_tizen 2.4
+   */
+  ~FunctorDelegate();
+
+  /**
+   * @brief Function to call the function or member function dispatcher
+   * @since_tizen 2.4
+   */
+  void Execute();
+
+private:
+
+  /**
+   * @brief Used to call the correct function.
+   * @since_tizen 2.4
+   */
+  typedef void (*Dispatcher)( void* objectPtr );
+
+  /**
+   * @brief Used to destroy mObjectPointer.
+   * @since_tizen 2.4
+   */
+  typedef void(*Destructor)( void* objectPtr );
+
+  /**
+   * @brief Not defined
+   * @since_tizen 2.4
+   */
+  FunctorDelegate( const FunctorDelegate& rhs );
+
+  /**
+   * @brief Not defined
+   * @since_tizen 2.4
+   */
+  const FunctorDelegate& operator=( const FunctorDelegate& rhs );
+
+  /**
+   * @brief Private constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] functorPtr A newly allocated functor object (takes ownership)
+   * @param dispatcher Used to call the actual function.
+   * @param destructor Used to delete the owned functor object.
+   */
+  FunctorDelegate( void* functorPtr, Dispatcher dispatcher, Destructor destructor );
+
+public: // Data for deriving classes & Dispatchers
+
+  void* mFunctorPointer;                ///< Functor that will be called
+  Dispatcher mMemberFunctionDispatcher; ///< Dispatcher for member functions
+  Destructor mDestructorDispatcher;     ///< Destructor for owned objects
+};
+
+/**
+ * @}
+ */
+} // namespace DALI
+
+#endif // __DALI_FUNCTOR_DELEGATE_H__
diff --git a/dali/public-api/signals/signal-slot-connections.cpp b/dali/public-api/signals/signal-slot-connections.cpp
new file mode 100644 (file)
index 0000000..a4bb208
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/signal-slot-connections.h>
+
+// EXTERNAL INCLUDES
+#include <cstddef>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/signals/callback.h>
+
+namespace Dali
+{
+
+SlotConnection::SlotConnection( SlotObserver* slotObserver, CallbackBase* callback )
+: mSlotObserver( slotObserver ),
+  mCallback( callback )
+{
+}
+
+SlotConnection::~SlotConnection()
+{
+}
+
+CallbackBase* SlotConnection::GetCallback()
+{
+  return mCallback;
+}
+
+SlotObserver* SlotConnection::GetSlotObserver()
+{
+  return mSlotObserver;
+}
+
+SignalConnection::SignalConnection( CallbackBase* callback )
+: mSignalObserver( NULL ),
+  mCallback( callback )
+{
+}
+
+SignalConnection::SignalConnection( SignalObserver* signalObserver, CallbackBase* callback )
+: mSignalObserver( signalObserver ),
+  mCallback( callback )
+{
+}
+
+SignalConnection::~SignalConnection()
+{
+  // signal connections have ownership of the callback.
+  delete mCallback;
+}
+
+void SignalConnection::Disconnect( SlotObserver* slotObserver )
+{
+  if( mSignalObserver )
+  {
+    // tell the slot the signal wants to disconnect
+    mSignalObserver->SignalDisconnected( slotObserver, mCallback );
+    mSignalObserver = NULL;
+  }
+
+  // we own the callback, SignalObserver is expected to delete the SlotConnection on Disconnected so its pointer to our mCallback is no longer used
+  delete mCallback;
+  mCallback = NULL;
+}
+
+CallbackBase* SignalConnection::GetCallback()
+{
+  return mCallback;
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/signal-slot-connections.h b/dali/public-api/signals/signal-slot-connections.h
new file mode 100644 (file)
index 0000000..342bec7
--- /dev/null
@@ -0,0 +1,165 @@
+#ifndef __DALI_SIGNAL_SLOT_CONNECTIONS_H__
+#define __DALI_SIGNAL_SLOT_CONNECTIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/signals/signal-slot-observers.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+class CallbackBase;
+
+/**
+ * @brief Slot connection is the connection information held by a connection tracker.
+ *
+ * A slot can have zero to many connection objects, depending
+ * on how many signals it is connected to.
+ *
+ * A connection contains:
+ * - Callback (slot)
+ * - SlotObserver -interface provided by the signal
+ *
+ * It holds a pointer to the callback, but does not own it.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API SlotConnection
+{
+public:
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] slotObserver The slot observer.
+   * @param[in] callback A callback object (not owned).
+   */
+  SlotConnection(SlotObserver* slotObserver, CallbackBase* callback);
+
+  /**
+   * @brief Non-virtual destructor, not intended as a base class.
+   * @since_tizen 2.4
+   */
+  ~SlotConnection();
+
+  /**
+   * @brief Retrieve the callback.
+   *
+   * @since_tizen 2.4
+   * @return A pointer to the callback.
+   */
+  CallbackBase* GetCallback();
+
+  /**
+   * @brief Retrieve the slot observer.
+   *
+   * @since_tizen 2.4
+   * @return A pointer to the slot observer.
+   */
+  SlotObserver* GetSlotObserver();
+
+private:
+
+  SlotConnection( const SlotConnection& );            ///< undefined copy constructor
+  SlotConnection& operator=( const SlotConnection& ); ///< undefined assignment operator
+
+private:
+
+  SlotObserver* mSlotObserver; ///< a pointer to the slot observer (not owned)
+  CallbackBase* mCallback;     ///< The callback. This is not owned, the corresponding SignalConnection has ownership.
+};
+
+/**
+ * @brief SignalConnection is the connection information held by the signal.
+ *
+ * A signal can have zero to many connections, depending on how
+ * many slots are connected to this signal.
+ *
+ * A connection contains:
+ * - Callback (slot)
+ * - SignalObserver - interface provided by a slot owning object.
+ *
+ * It takes ownership of the callback, and will delete it when
+ * the connection is destroyed.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API SignalConnection
+{
+public:
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback which should be a C function.
+   */
+  SignalConnection( CallbackBase* callback );
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] signalObserver The signal observer.
+   * @param[in] callback Ownership of this callback object is taken.
+   */
+  SignalConnection( SignalObserver* signalObserver, CallbackBase* callback );
+
+  /**
+   * @brief Non-virtual destructor, not intended as a base class.
+   * @since_tizen 2.4
+   */
+  ~SignalConnection();
+
+  /**
+   * @brief Disconnect the signal from the slot.
+   *
+   * @since_tizen 2.4
+   * @param[in] slotObserver The signal disconnecting from the slot.
+   */
+  void Disconnect( SlotObserver* slotObserver );
+
+  /**
+   * @brief Retrieve the callback.
+   *
+   * @since_tizen 2.4
+   * @return A pointer to the callback.
+   */
+  CallbackBase* GetCallback();
+
+private:
+
+  SignalConnection( const SignalConnection& );            ///< undefined copy constructor
+  SignalConnection& operator=( const SignalConnection& ); ///< undefined assignment operator
+
+private:
+
+  SignalObserver* mSignalObserver; ///< a pointer to the signal observer (not owned)
+  CallbackBase* mCallback;         ///< The callback, has ownership.
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SIGNAL_SLOT_CONNECTIONS_H__
diff --git a/dali/public-api/signals/signal-slot-observers.cpp b/dali/public-api/signals/signal-slot-observers.cpp
new file mode 100644 (file)
index 0000000..148b56d
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/public-api/signals/signal-slot-observers.h>
+
+namespace Dali
+{
+
+SignalObserver::SignalObserver()
+{
+}
+
+SignalObserver::~SignalObserver()
+{
+}
+
+SlotObserver::SlotObserver()
+{
+}
+
+SlotObserver::~SlotObserver()
+{
+}
+
+} // namespace Dali
diff --git a/dali/public-api/signals/signal-slot-observers.h b/dali/public-api/signals/signal-slot-observers.h
new file mode 100644 (file)
index 0000000..eef3178
--- /dev/null
@@ -0,0 +1,102 @@
+#ifndef __DALI_SIGNAL_SLOT_OBSERVERS_H__
+#define __DALI_SIGNAL_SLOT_OBSERVERS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+class SlotObserver;
+class CallbackBase;
+
+/**
+ * @brief Abstract interface used by a signal to inform a slot it is disconnecting.
+ *
+ * This will happen if the object owning the signal is destroyed.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API SignalObserver
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  SignalObserver();
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~SignalObserver();
+
+  /**
+   * @brief This method is called when the signal is disconnecting.
+   *
+   * @since_tizen 2.4
+   * @param[in] slotObserver The signal that has disconnected.
+   * @param[in] callback The callback attached to the signal disconnected.
+   */
+  virtual void SignalDisconnected( SlotObserver* slotObserver, CallbackBase* callback ) = 0;
+};
+
+/**
+ * @brief Abstract Interface used by a slot to inform a signal it is disconnecting.
+ *
+ * This is used by the slot if wants to disconnect or is deleted.
+ * @since_tizen 2.4
+ */
+class DALI_IMPORT_API SlotObserver
+{
+public:
+
+  /**
+   * @brief Constructor.
+   * @since_tizen 2.4
+   */
+  SlotObserver();
+
+  /**
+   * @brief Virtual destructor.
+   * @since_tizen 2.4
+   */
+  virtual ~SlotObserver();
+
+  /**
+   * @brief This method is called when the slot is disconnecting.
+   *
+   * @since_tizen 2.4
+   * @param[in] callback The callback attached to the signal disconnected.
+   */
+  virtual void SlotDisconnected( CallbackBase* callback ) = 0;
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SIGNAL_SLOT_OBSERVERS_H__
diff --git a/dali/public-api/signals/slot-delegate.h b/dali/public-api/signals/slot-delegate.h
new file mode 100644 (file)
index 0000000..81f1813
--- /dev/null
@@ -0,0 +1,158 @@
+#ifndef __DALI_SLOT_DELEGATE_H__
+#define __DALI_SLOT_DELEGATE_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/common/dali-common.h>
+#include <dali/public-api/signals/connection-tracker.h>
+
+namespace Dali
+{
+/**
+ * @addtogroup dali_core_signals
+ * @{
+ */
+
+/**
+ * @brief SlotDelegates can be used to connect member functions to signals, without inheriting from SlotDelegateInterface.
+ *
+ * Note that the object providing the member function is expected to own the SlotDelegate; therefore when the object
+ * is destroyed, the SlotDelegate destructor will automatically disconnect.
+ *
+ * @code
+ *
+ * class Example // This does not inherit from SlotDelegateInterface!
+ * {
+ * public:
+ *
+ *   Example()
+ *   : mSlotDelegate( this )
+ *   {
+ *   }
+ *
+ *   ~Example()
+ *   {
+ *     // mSlotDelegate disconnects automatically here
+ *   }
+ *
+ *   void Animate()
+ *   {
+ *     Animation animation = Animation::New( 1.0f );
+ *     animation.FinishedSignal().Connect( mSlotDelegate, &Example::OnAnimationFinished );
+ *     animation.Play(); // fire & forget
+ *   }
+ *
+ *   void OnAnimationFinished( Animation& animation )
+ *   {
+ *     std::cout << "Animation Finished!" << std::endl;
+ *   }
+ *
+ * private:
+ *
+ *  SlotDelegate<Example> mSlotDelegate;
+ *
+ * };
+ *
+ * @endcode
+ * @since_tizen 2.4
+ */
+template <typename Slot>
+class SlotDelegate
+{
+public:
+
+  /**
+   * @brief Constructor.
+   *
+   * @since_tizen 2.4
+   * @param[in] slot The object with a callback.
+   */
+  SlotDelegate( Slot* slot )
+  : mSlot( slot )
+  {
+  }
+
+  /**
+   * @brief Non-virtual destructor.
+   *
+   * @since_tizen 2.4
+   */
+  ~SlotDelegate()
+  {
+  }
+
+  /**
+   * @brief Disconnect all signals from this object.
+   *
+   * @since_tizen 2.4
+   */
+  void DisconnectAll()
+  {
+    mConnectionTracker.DisconnectAll();
+  }
+
+  /**
+   * @copydoc ConnectionTracker::GetConnectionCount
+   */
+  std::size_t GetConnectionCount() const
+  {
+    return mConnectionTracker.GetConnectionCount();
+  }
+
+  /**
+   * @brief Retrieve the slot object.
+   *
+   * @since_tizen 2.4
+   * @return The object with a callback.
+   */
+  Slot* GetSlot()
+  {
+    return mSlot;
+  }
+
+  /**
+   * @brief Retrieve the connection tracker component.
+   *
+   * @since_tizen 2.4
+   * @return The connection tracker component.
+   */
+  ConnectionTracker* GetConnectionTracker()
+  {
+    return &mConnectionTracker;
+  }
+
+private:
+
+  SlotDelegate( const SlotDelegate& );            ///< undefined copy constructor
+  SlotDelegate& operator=( const SlotDelegate& ); ///< undefined assignment operator
+
+private:
+
+  Slot* mSlot; ///< The slot object
+
+  // Use composition instead of inheritance (virtual methods don't mix well with templates)
+  ConnectionTracker mConnectionTracker; ///< A connection tracker
+};
+
+/**
+ * @}
+ */
+} // namespace Dali
+
+#endif // __DALI_SLOT_DELEGATE_H__
diff --git a/dali/public-api/size-negotiation/relayout-container.h b/dali/public-api/size-negotiation/relayout-container.h
new file mode 100644 (file)
index 0000000..5442a60
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef __DALI_RELAYOUT_CONTAINER_H__
+#define __DALI_RELAYOUT_CONTAINER_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/public-api/actors/actor.h>
+#include <dali/public-api/math/vector2.h>
+
+namespace Dali
+{
+
+class RelayoutContainer;
+typedef RelayoutContainer* RelayoutContainerPtr;
+
+
+/**
+ * @brief Interface to encapsulate information required for relayout
+ * @since_tizen 2.4
+ */
+class RelayoutContainer
+{
+public:
+
+  /**
+   * @brief Default constructor
+   *
+   * @since_tizen 2.4
+   */
+  RelayoutContainer() {}
+
+  /**
+   * @brief Virtual destructor
+   * @since_tizen 2.4
+   */
+  virtual ~RelayoutContainer() {}
+
+  /**
+   * @brief Add relayout information to the container if it does'nt already exist
+   *
+   * @since_tizen 2.4
+   * @param actor The actor to relayout
+   * @param size The size to relayout
+   */
+  virtual void Add( const Actor& actor, const Vector2& size ) = 0;
+
+};
+
+} // namespace Dali
+
+#endif // __DALI_RELAYOUT_CONTAINER_H__
diff --git a/doc/dali_doc.h b/doc/dali_doc.h
new file mode 100644 (file)
index 0000000..628da4d
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __DALI_DOC_H__
+#define __DALI_DOC_H__
+
+/**
+ * @defgroup dali_core DALi Core
+ * 
+ * @brief This module provides scene graph-based rendering, animation, and event handling.
+ * It is a base module and forms the biggest part of DALi.
+ *
+ * @ingroup dali
+ * @{
+ *   @defgroup dali_core_actors Actors
+ *   @brief Actor is the primary object for interaction in DALi applications.
+
+ *   @defgroup dali_core_animation Animation
+ *   @brief Animation allows your objects to move around / change their properties for a specified duration.
+
+ *   @defgroup dali_core_common Common
+ *   @brief Common classes for using DALi.
+
+ *   @defgroup dali_core_events Events
+ *   @brief Input events and gestures supported by DALi.
+
+ *   @defgroup dali_core_images Images
+ *   @brief Classes for handling resource images.
+
+ *   @defgroup dali_core_math Math
+ *   @brief Basic math classes.
+
+ *   @defgroup dali_core_object Object
+ *   @brief Classes for the handle/body pattern and property system.
+
+ *   @defgroup dali_core_rendering_effects Rendering & Effects
+ *   @brief Render task and shader effect classes.
+
+ *   @defgroup dali_core_signals Signals
+ *   @brief Classes for the signal and slot structure.
+ * @}
+ */
+
+#endif  /* __DALI_DOC_H__ */
diff --git a/docs/README b/docs/README
new file mode 100644 (file)
index 0000000..106805c
--- /dev/null
@@ -0,0 +1,4 @@
+To build the documentation type doxygen docs/dali_internal.doxy
+To view the output: firefox docs/generated/html/index.html
+
+Refer to dali-toolkit repository for public API and programming guide documentation.
diff --git a/docs/api_footer.html b/docs/api_footer.html
new file mode 100644 (file)
index 0000000..5fb656d
--- /dev/null
@@ -0,0 +1,2 @@
+<hr>\r
+<a href="http://www.samsung.com">Copyright (c) 2008-2011 Samsung Electronics, Co., Ltd.</a></body></html>\r
diff --git a/docs/coding-convention.html b/docs/coding-convention.html
new file mode 100644 (file)
index 0000000..79bbf03
--- /dev/null
@@ -0,0 +1,332 @@
+<HTML>
+<HEAD>
+<TITLE>Dali C++ Coding Conventions</TITLE>
+<!--
+green code for good examples, same formatting as <pre> tag
+red code for bad examples, same formatting as <pre> tag
+details hidden by default
+-->
+<style type="text/css">
+code.good { color:green; white-space:pre; }
+code.bad { color:red; white-space:pre; }
+article.detail { display:block; }
+</style>
+
+<script type="text/javascript">
+function toggleVisibility( button, obj )
+{
+  // must have button and object
+  if( !button || !obj )
+    return;
+  var e=document.getElementById( obj );
+  if( !e )
+    return;
+
+  // initially display property seems to be empty, then none
+  if( e.style.display == "" || e.style.display == "none" )
+  {
+    // paragraph shown
+    button.value="Hide";
+    e.style.display="block";
+  }
+  else
+  {
+    // paragraph hidden
+    button.value="Show";
+    e.style.display="none";
+  }
+}
+</script>
+
+</HEAD>
+<BODY>
+
+<H1>General</H1>
+  <P>
+    Here's a few pragmatic programmer guidelines to follow (<A HREF="http://www.codinghorror.com/blog/files/Pragmatic%20Quick%20Reference.htm">Web version</A>)
+    <H3>Details <input type="button" value="Hide" onclick="toggleVisibility( this, 'general_details' );"/></H3>
+    <ARTICLE class="detail" id="general_details">
+      <UL>
+      <LI><B>Care About the Software, Care about your API users and end users</B><BR>
+            Why spend your life developing software unless you care about doing it well?
+            Turn off the autopilot and take control. Constantly critique and appraise your work.
+      <LI><B>Don't Live with Broken Windows</B><BR>
+            Fix bad designs, wrong decisions, and poor code when you see them.
+            You can't force change on people. Instead, show them how the future might be and help them participate in creating it.
+      <LI><B>Remember the Big Picture</B><BR>
+            Don't get so engrossed in the details that you forget to check what's happening around you.
+      <LI><B>DRY - Don't Repeat Yourself</B><BR>
+            Every piece of knowledge must have a single, unambiguous, authoritative representation within a system.
+      <LI><B>Eliminate Effects Between Unrelated Things</B><BR>
+            Design components that are self-contained. independent, and have a single, well-defined purpose.
+      <LI><B>There Are No Final Decisions</B><BR>
+            No decision is cast in stone. Instead, consider each as being written in the sand at the beach, and plan for change.
+      <LI><B>Fix the Problem, Not the Blame</B><BR>
+            It doesn't really matter whether the bug is your fault or someone else's—it is still your problem, and it still needs to be fixed.
+      <LI><B>You Can't Write Perfect Software</B><BR>
+            Software can't be perfect. Protect your code and users from the inevitable errors.
+      <LI><B>Design with Contracts</B><BR>
+            Use contracts to document and verify that code does no more and no less than it claims to do.
+      <LI><B>Crash Early</B><BR>
+            A dead program normally does a lot less damage than a crippled one.
+      <LI><B>Use Assertions to Prevent the Impossible</B><BR>
+            Assertions validate your assumptions. Use them to protect your code from an uncertain world.
+      <LI><B>Use Exceptions for Exceptional Problems</B><BR>
+            Exceptions can suffer from all the readability and maintainability problems of classic spaghetti code. Reserve exceptions for exceptional things.
+      <LI><B>Minimize Coupling Between Modules</B><BR>
+            Avoid coupling by writing "shy" code and applying the Law of Demeter.
+      <LI><B>Put Abstractions in Code, Details in Metadata</B><BR>
+            Program for the general case, and put the specifics outside the compiled code base.
+      <LI><B>Always Design for Concurrency</B><BR>
+            Allow for concurrency, and you'll design cleaner interfaces with fewer assumptions.
+      <LI><B>Don't Program by Coincidence</B><BR>
+            Rely only on reliable things. Beware of accidental complexity, and don't confuse a happy coincidence with a purposeful plan.
+      <LI><B>Test Your Estimates</B><BR>
+            Mathematical analysis of algorithms doesn't tell you everything. Try timing your code in its target environment.
+      <LI><B>Refactor Early, Refactor Often</B><BR>
+            Just as you might weed and rearrange a garden, rewrite, rework, and re-architect code when it needs it. Fix the root of the problem.
+      <LI><B>Design to Test</B><BR>
+            Start thinking about testing before you write a line of code.
+      <LI><B>Abstractions Live Longer than Details</B><BR>
+            Invest in the abstraction, not the implementation. Abstractions can survive the barrage of changes from different implementations and new technologies.
+      <LI><B>Coding Ain't Done 'Til All the Tests Run</B><BR>
+            'Nuff said.
+      <LI><B>Use Saboteurs to Test Your Testing</B><BR>
+            Introduce bugs on purpose in a separate copy of the source to verify that testing will catch them.
+      <LI><B>Find Bugs Once</B><BR>
+            Once a human tester finds a bug, it should be the last time a human tester finds that bug. Automatic tests should check for it from then on.
+      <LI><B>Sign Your Work</B><BR>
+            Craftsmen of an earlier age were proud to sign their work. You should be, too.
+      </UL>
+    </ARTICLE>
+  </P>
+
+  <H2>Avoid Tight Coupling</H2>
+    <P>
+      Always choose the loosest possible coupling between entities. In C++ the tightest coupling is Friend, second is Inheritance,
+      then Containment and last is Usage through reference, pointer or handle.
+    <H3>Details <input type="button" value="Hide" onclick="toggleVisibility( this, 'coupling_details' );"/></H3>
+    <ARTICLE class="detail" id="coupling_details">
+      <UL>
+        <LI>Friend defines a "must-know" about details of implementation, don't use it unless your happy stating that Xxx really <B>must</B> know about Yyy implementation. and Yyy can never change without informing Xxx.
+        <LI>Inheritance defines a "is-a" relationship, don't use it unless you really can naturally say Xxx is-a Yyy. Most of the cases containment through interface is what you
+        <LI>Containment defines a "owns-a" relationship, use it when you have a natural Xxx owns-a Yyy relationship.
+      </UL>
+      Most of the time containment through interface and normal usage is what you should go for.
+      Strong ownership always beats sharing through reference counting. Reference counting means "part owns".
+      You would not want to part own anything in real life, so why do that in software? sooner or later it will leak,
+    </ARTICLE>
+    </P>
+
+  Two key principles to follow:
+  <H2>Open Closed Principle</H2>
+    <P>
+      Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.
+      That is, such an entity can allow its behaviour to be modified without altering its source code. Techniqu
+    </P>
+
+  <H2>Dependency Inversion Principle</H2>
+    <P>
+      High-level modules should not depend on low-level modules. Both should depend on abstractions.
+      Abstractions should not depend upon details. Details should depend upon abstractions.
+    </P>
+
+<H1>General conventions</H1>
+  <H2>Type casting <input type="button" value="Hide" onclick="toggleVisibility( this, 'ccasts_details' );"/></H2>
+    <ARTICLE class="detail" id="ccasts_details">
+      <SUMMARY>
+        <B>Never use C-Style Casts</B><BR>
+        The C-style cast - "(type) expr" used to convert one fundamental type to another is subject to implementation-defined effects.
+        For scalar types it can result in silent truncation of the value. For pointers and references, it does not check the
+        compatibility of the value with the target type.<BR>
+        <B>Don't cast away const, use mutable keyword instead</B><BR>
+        <B>Don't reinterpret_cast, fix the design instead</B><BR>
+        <B>Remember that reference cast will throw an error if cast fails</B><BR>
+        <B>Avoid using pointer or reference casts. They have been referred to as the goto of OO programming, fix the design instead</B><BR>
+      </SUMMARY>
+      <CODE class="good">
+        X* ptr = static_cast<X*>( y_ptr ); // ok, compiler checks whether types are compatible
+      </CODE>
+      <CODE class="bad">
+        (Foo*) ptr; // bad! C-cast is not guaranteed to check and never complains
+      </CODE>
+    </ARTICLE>
+
+<H1>Classes</H1>
+  <SUMMARY>
+    A class interface should be complete and minimal. Class should encapsulate one thing and one thing only.
+    A complete interface allows clients to do anything they may reasonably want to do.
+    On the other hand, a minimal interface will contain as few functions as possible.
+    Class methods must be defined in the same order as they are declared. This helps navigating through code.
+  </SUMMARY>
+  <H2>Compulsory member functions <input type="button" value="Hide" onclick="toggleVisibility( this, 'implicit_method_details' );"/></H2>
+    <ARTICLE class="detail" id="implicit_method_details">
+      <SUMMARY>
+        Every class must define default constructor, copy constructor, assignment operator and destructor.
+        If you dont declare them, compiler will and the compiler generated versions are usually not good or safe enough.
+        If your class does not support copying, then declare copy constructor and assignment operator as private and don't define them.
+      </SUMMARY>
+      <P>
+        If for example the assignment operator is not needed for a particular class, then it
+        must be declared private and not defined. Any attempt to invoke the operator will result
+        in a compile-time error. On the contrary, if the assignment operator is not declared, then
+        when it is invoked, a compiler-generated form will be created and subsequently executed.
+        This could lead to unexpected results. The same goes with default constructor and copy constructor.
+      </P>
+      <CODE class="good">
+        class X
+        {
+          X();                      // default constructor
+          X( const X& );            // copy constructor
+          X& operator=( const X& ); // copy assignment operator
+          ~X();                     // destructor
+        };
+      </CODE>
+    </ARTICLE>
+  <H2>Class types <input type="button" value="Hide" onclick="toggleVisibility( this, 'class_types_details' );"/></H2>
+    <ARTICLE class="detail" id="class_types_details">
+      <SUMMARY>
+        Classes can have either <B>Value</B> semantics or <B>Pointer</B> semantics. Not both.
+        It must be clearly documented whether a class follows value or pointer semantics and this also
+        sets requirements on the class interface.
+      </SUMMARY>
+      <P>
+        Classes with <B>Value</B> semantics are passed as value types. These classes provide a copy constructor,
+        a default constructor and assignment operator so that they can be copied and also stored on STL containers.
+      </P>
+      <P>
+        Classes with <B>Pointer</B> semantics are always passed through pointers, references or smart pointers.
+        These classes are ususally compound types that cannot be easily copied and thus prevent copy constructor,
+        and assignment operator. That can be only stored on STL containers through smart pointers.
+      </P>
+    </ARTICLE>
+  <H2>Access Rights <input type="button" value="Hide" onclick="toggleVisibility( this, 'access_details' );"/></H2>
+    <ARTICLE class="detail" id="access_details">
+      <P>
+        Public and protected data should only be used in structs, not classes.
+        Roughly two types of classes exist: those that essentially aggregate data and those that provide
+        an abstraction while maintaining a well-defined state or invariant.
+      </P>
+      <P>
+        A structure should be used to model an entity that does not require an invariant (Plain Old Data)
+        A class should be used to model an entity that maintains an invariant.
+        <B>Rationale:</B> A class is able to maintain its invariant by controlling access to its data. However,
+        a class cannot control access to its members if those members non-private.
+        Hence all data in a class should be private.
+      </P>
+    </ARTICLE>
+  <H2>Constructors <input type="button" value="Hide" onclick="toggleVisibility( this, 'constructor_details' );"/></H2>
+    <ARTICLE class="detail" id="constructor_details">
+      <P>
+        Virtual function calls are not allowed from constructor
+        Rationale: Virtual functions are resolved statically (not dynamically) in constructor
+      </P>
+      <P>
+        Member initialization order must be the same in which they are declared in the class.
+        Note: Since base class members are initialized before derived class members, base class
+              initializers should appear at the beginning of the member initialization list.
+        <B>Rationale:</B> Members of a class are initialized in the order in which they are declared—not
+        the order in which they appear in the initialization list.
+      </P>
+      <P>
+        Constructor body should not throw an exception, keep constructor simple and trivial.
+        If constructor fails, objects lifecycle never started, destructor will not be called.
+      </P>
+      <P>
+        Declare all single argument constructors as explicit thus preventing their use as implicit type convertors.
+        <CODE class="good">
+          class C
+          {
+          public:
+            explicit C( int );         // good, explicit
+            C( int, int );             // ok more than one non-default argument
+          };
+        </CODE>
+        <CODE class="bad">
+          class C
+          {
+          public:
+            C( double );               // bad, can be used in implicit conversion
+            C( float f, int i=0 );     // bad, implicit conversion constructor
+            C( int i=0, float f=0.0 ); // bad, default constructor, but also a conversion constructor
+          };
+        </CODE>
+      </P>
+    </ARTICLE>
+  <H2>Destructor <input type="button" value="Hide" onclick="toggleVisibility( this, 'destructor_details' );"/></H2>
+    <ARTICLE class="detail" id="destructor_details">
+      <P>
+        All classes should define a destructor, either:
+        <UL>
+          <LI>public for value types
+          <LI>public and virtual for base classes with virtual methods
+          <LI>protected and virtual for base classes to prevent deletion (and ownership) through base class
+        </UL>
+        This prevents undefined behavior. If an application attempts to delete a derived class object
+        through a base class pointer, the result is undefined if the base class destructor is non-virtual.
+      </P>
+      <P>
+        Virtual function calls are not allowed from inside the destructor.
+        Rationale: A class's virtual functions are resolved statically (not dynamically) in its destructor
+      </P>
+      <P>
+        All resources acquired by a class shall be released by the class's destructor.
+      </P>
+      <P>
+        Destructor is not allowed to throw an exception, avoid doing complicated things in destructor.
+      </P>
+    </ARTICLE>
+  <H2>Methods <input type="button" value="Hide" onclick="toggleVisibility( this, 'method_details' );"/></H2>
+    <ARTICLE class="detail" id="method_details">
+      <P>
+        Don't shortcut, like use the returned reference of getter to assign a new value. If a Setter is missing, add it!
+        <CODE class="bad">
+            initial.GetPosition() = Position(10, 10); // bad!, If GetPosition is one day changed to return copy
+                                                      // of Position this code silently changes to a no-op.
+        </CODE>
+        <CODE class="good">
+            initial.SetPosition( Position( 10, 10 ) );
+        </CODE>
+      </P>
+      <P>
+        Code that is not used (commented out) should be deleted.
+        Rationale: No dead code should be left to confuse other people.
+        Exception: Code that is simply part of an explanation may appear in comments.
+      </P>
+      <P>
+      </P>
+    </ARTICLE>
+
+  <H2>Inline member functions <input type="button" value="Hide" onclick="toggleVisibility( this, 'inline_details' );"/></H2>
+    <ARTICLE class="detail" id="inline_details">
+      <P>
+
+        GCC automatically inlines member functions defined within the class body of C++ programs even if they are not explicitly declared inline.
+        <CODE class="bad">
+               class Color
+               {
+                       inline float& GetRed()  { return mRed;   }              // inline keyword not needed
+                       inline float& GetGreen(){ return mGreen; }
+               };
+        </CODE>
+        <CODE class="good">
+               class Color
+               {
+                       float& GetRed()   { return mRed;   }
+                       float& GetGreen(){ return mGreen; }
+               };
+        </CODE>
+      </P>
+      <P>
+       If there are a lot of inlines, they should be in a .inl file.
+       Remember the inline keyword is just a hint to the compiler. Whether
+       a function will be inlined or not is down to the compiler and its flags.
+      </P>
+      <P>
+      </P>
+    </ARTICLE>
+
+  <P>Thats all folks, if you read this far you are now all equipped to write good code :) !! </P>
+
+</BODY>
+</HTML>
diff --git a/docs/coding-style.html b/docs/coding-style.html
new file mode 100644 (file)
index 0000000..4a67b58
--- /dev/null
@@ -0,0 +1,989 @@
+<HTML>
+<HEAD>
+<TITLE>Dali C++ Coding Style</TITLE>
+<!--
+green code for good examples, same formatting as <pre> tag
+red code for bad examples, same formatting as <pre> tag
+details hidden by default
+-->
+<style type="text/css">
+code.good { color:green; white-space:pre; }
+code.bad { color:red; white-space:pre; }
+article.detail { display:block; }
+</style>
+
+<script type="text/javascript">
+function toggleVisibility( button, obj )
+{
+  // must have button and object
+  if( !button || !obj )
+    return;
+  var e=document.getElementById( obj );
+  if( !e )
+    return;
+
+  // initially display property seems to be empty, then none
+  if( e.style.display == "" || e.style.display == "none" )
+  {
+    // paragraph shown
+    button.value="Hide";
+    e.style.display="block";
+  }
+  else
+  {
+    // paragraph hidden
+    button.value="Show";
+    e.style.display="none";
+  }
+}
+</script>
+
+</HEAD>
+<BODY>
+
+<H1>Naming</H1>
+  <P>
+    The most important consistency rules are those that govern
+    naming. The style of a name immediately informs us what sort of
+    thing the named entity is: a type, a variable, a function, a
+    constant, a macro, etc., without requiring us to search for the
+    declaration of that entity. The pattern-matching engine in our
+    brains relies a great deal on these naming rules.
+  </P>
+  <P>
+    Consistency is more important than individual preferences so regardless of
+    whether you find them sensible or not, the rules are the rules.
+  </P>
+
+  <ARTICLE>
+    <H2>General Naming Rules</H2>
+      <SUMMARY>
+        Function names, variable names, and filenames should be
+        descriptive; eschew abbreviation.  Types and variables should be
+        nouns, while functions should be "command" verbs.
+      </SUMMARY>
+      <H3>How to Name <input type="button" value="Hide" onclick="toggleVisibility( this, 'how_to_name' );"/></H3>
+      <ARTICLE class="detail" id="how_to_name">
+        <P>
+          Give as descriptive a name as possible, within reason. Do
+          not worry about saving horizontal space as it is far more
+          important to make your code immediately understandable by a
+          new reader. Examples of well-chosen names:
+        </P>
+        <CODE class="good">
+          int numberOfErrors;              // Good.
+          int countCompletedConnections;   // Good.
+        </CODE>
+        <P>
+          Poorly-chosen names use ambiguous abbreviations or arbitrary
+          characters that do not convey meaning:
+        </P>
+        <CODE class="bad">
+          int n;                           // Bad - meaningless.
+          int nerr;                        // Bad - ambiguous abbreviation.
+          int n_comp_conns;                // Bad - ambiguous abbreviation.
+        </CODE>
+        <P>
+          Type and variable names should typically be nouns: e.g.,
+          <code>FileOpener</code>,
+          <code>NumErrors</code>.
+        </P>
+        <P>
+          Function names should typically be imperative (that is they should be commands):
+                 e.g., <code>OpenFile()</code>, <code>set_num_errors()</code>.  There is an exception for
+          accessors, which should be named the same as the variable they access.
+        </P>
+      </ARTICLE>
+
+      <H3>Abbreviations <input type="button" value="Hide" onclick="toggleVisibility( this, 'abbreviations' );"/></H3>
+      <ARTICLE class="detail" id="abbreviations">
+        <P>
+          Do not use abbreviations unless they are extremely well
+          known outside your project. For example:
+        </P>
+        <CODE class="good">
+          // Good
+          // These show proper names with no abbreviations.
+          int numberOfDnsConnections;  // Most people know what "DNS" stands for.
+          int priceCountReader;   // OK, price count. Makes sense.
+        </CODE>
+        <CODE class="bad">
+          // Bad!
+          // Abbreviations can be confusing or ambiguous outside a small group.
+          int wgcconnections;  // Only your group knows what this stands for.
+          int pcreader;        // Lots of things can be abbreviated "pc".
+        </CODE>
+        <P>
+          Never abbreviate by leaving out letters:
+        </P>
+        <CODE class="good">
+          int error_count;  // Good.
+        </CODE>
+        <CODE class="bad">
+          int error_cnt;    // Bad.
+        </CODE>
+      </ARTICLE>
+  </ARTICLE>
+
+  <ARTICLE>
+    <H2>File Names</H2>
+    <SUMMARY>
+      Filenames should be all lowercase and can include underscores dashes (<code>-</code>).
+      Do not use underscores in filenames (<code>_</code>).
+    </SUMMARY>
+    <H3>Examples <input type="button" value="Hide" onclick="toggleVisibility( this, 'file_name_examples' );"/></H3>
+    <ARTICLE class="detail" id="file_name_examples">
+      <P>
+        Examples of acceptable file names:
+      </P>
+      <P>
+        <CODE class="good">
+          my-useful-class.cpp
+          myusefulclass.cpp
+          myusefulclass-test.cpp
+        </CODE>
+      </P>
+      <P>
+        C++ files should end in <code>.cpp</code> and header files
+        should end in <code>.h</code>.
+      </P>
+      <P>
+        Do not use filenames that already exist
+        in <code>/usr/include</code>, such as <code>db.h</code>.
+      </P>
+      <P>
+        In general, make your filenames very specific.  For example,
+        use <code>http-server-logs.h</code> rather than <code>logs.h</code>.
+               A class called <code>FooBar</code> should be declared in file
+               called <code>foobar.h</code> and defined in <code>foobar.cpp</code>.
+      </P>
+      <P>
+        Inline functions must be in a <code>.h</code> file. If your
+        inline functions are very short, they should go directly into your
+        <code>.h</code> file. However, if your inline functions
+        include a lot of code, they may go into a third file that
+        ends in <code>-inl.h</code>.  In a class with a lot of inline
+        code, your class could have three files:
+      </P>
+      <CODE class="good">
+        foobar.h      // The class declaration.
+        foobar.cpp     // The class definition.
+        foobar-inl.h  // Inline functions that include lots of code.
+      </CODE>
+    </ARTICLE>
+  </ARTICLE>
+
+  <ARTICLE>
+    <H2>Type Names</H2>
+    <SUMMARY>
+      Type names start with a capital letter and have a capital
+      letter for each new word, with no underscores:
+      <code>MyExcitingClass</code>, <code>MyExcitingEnum</code>.
+      All type names are declared inside a namespace so no prefixing is used.
+    </SUMMARY>
+    <H3>Examples <input type="button" value="Hide" onclick="toggleVisibility( this, 'type_name_examples' );"/></H3>
+    <ARTICLE class="detail" id="type_name_examples">
+      <p>
+        The names of all types; classes, structs, typedefs have the same naming convention -
+        CamelCase with a leading capital letter, with no underscores. Enumerated type constants use the same convention as class constants, i.e. all uppercase with underscores.
+        For example:
+      </p>
+      <CODE class="good">
+        // classes and structs
+        class UrlTable { ... };
+        class UrlTableTester { ... };
+        struct UrlTableProperties { ... };
+
+        // typedefs
+        typedef hash_map<UrlTableProperties *, string> PropertiesMap;
+
+        // enums
+        enum UrlTableErrors
+        {
+          OK = 0,
+          OUT_OF_MEMORY = 1,
+          MALFORMED_INPUT = 2,
+        }
+      </CODE>
+    </ARTICLE>
+  </ARTICLE>
+
+  <ARTICLE>
+    <H2>Variable Names</H2>
+    <SUMMARY>
+      Variable names should use camel case, with an initial lower case letter.
+      Local variable names start with a lowercase letter. For example: <code>myExcitingLocalVariable</code>,
+      Class member variables have prefix m. For example: <code>mMember</code>.
+      The only exception to this rule is for public member variables in public structs where the prefix m is not required.
+      Such member variables should also start with a lowercase letter.
+      Avoid underscore characters in mixed case names.
+      Constants should be all upper case, with underscores between words.
+      Global variables should be avoided, however, if one is needed, prefix it with <code>g</code>.
+    </SUMMARY>
+    <H3>Examples <input type="button" value="Hide" onclick="toggleVisibility( this, 'variable_name_examples' );"/></H3>
+    <ARTICLE class="detail" id="variable_name_examples">
+      <p>
+        For example:
+      </p>
+      <CODE class="good">
+        void SomeFunction()
+        {
+          string tableName;  // OK - starts lowercase
+          string tablename;  // OK - all lowercase.
+        }
+      </CODE>
+      <CODE class="bad">
+        string TableName;   // Bad - starts with capital.
+      </CODE>
+      <CODE class="good">
+        class Foo
+        {
+        public:
+          string mTable;     // OK
+          string mTableName; // OK.
+        };
+      </CODE>
+      <CODE class="good">
+        struct Foo
+        {
+          string table;     // OK
+          string tableName; // OK.
+        };
+      </CODE>
+      <CODE class="good">
+        const int DAYS_IN_A_WEEK = 7;
+      </CODE>
+      <CODE class="bad">
+        const int DaysInAWeek = 7; // Bad - constants should not use camel case.
+        const int DAYSINAWEEK = 7; // Bad - without underscore, words run together.
+      </CODE>
+    </ARTICLE>
+  </ARTICLE>
+
+  <ARTICLE>
+    <H2>Function Names</H2>
+    <SUMMARY>
+      Regular function names are written in camel case starting with a
+      capital letter and no underscores; accessors and mutators match
+      the name of the variable with Get or Set as prefix.
+    </SUMMARY>
+    <H3>Examples <input type="button" value="Hide" onclick="toggleVisibility( this, 'function_name_examples' );"/></H3>
+    <ARTICLE class="detail" id="function_name_examples">
+      <CODE class="good">
+        void MyExcitingFunction();
+        void MyExcitingMethod();
+
+        class MyClass
+        {
+        public:
+          ...
+          int GetNumEntries() const { return mNumEntries; }
+          void SetNumEntries( int numEntries ) { mNumEntries = numEntries; }
+
+        private:
+          int mNumEntries;
+        };
+      </CODE>
+
+      <CODE class="bad">
+        void my_boring_function(); // bad - uses underscores and no camel case.
+      </CODE>
+
+    </ARTICLE>
+  </ARTICLE>
+
+  <ARTICLE>
+    <H2>Macro Names</H2>
+    <SUMMARY>
+      Macros should not be used for programming, code should always be readable without preprocessor.
+      Only allowed cases for macros are include guards, debug tracing and compile time feature flags
+      <b>inside</b> .cpp files when no other variation mechanism is not possible. Always prefer variation
+      through design and template mechanisms rather than <i>#define</i>.
+      If you need to use macros, they're like this: <code>MY_MACRO_THAT_SCARES_SMALL_CHILDREN</code>.
+    </SUMMARY>
+    <H3>Examples <input type="button" value="Hide" onclick="toggleVisibility( this, 'macro_name_examples' );"/></H3>
+    <ARTICLE class="detail" id="macro_name_examples">
+      <CODE class="good">
+        #define DEBUG_TRACE( __FILE__, __LINE__ ) ...
+        #ifndef __ACTOR_H__
+        #define __ACTOR_H__
+        ...
+        #endif // __ACTOR_H__
+      </CODE>
+    </ARTICLE>
+  </ARTICLE>
+
+<H1>Comments</H1>
+  <SUMMARY>
+    Comments are absolutely vital to keeping our code readable.
+    The following rules describe what you should comment and where.
+    But remember: while comments are very important, the best code is self-documenting.
+    Giving sensible names to types and variables is much better than using obscure
+    names that you must then explain through comments.
+    When writing your comments, write for your audience: the next
+    contributor who will need to understand your code.
+  </SUMMARY>
+  <H2>Comment Rules <input type="button" value="Hide" onclick="toggleVisibility( this, 'comments_details' );"/></H2>
+  <ARTICLE class="detail" id="comments_details">
+    <H3>Comment Style</H3>
+      <SUMMARY>
+        API documentation must use doxygen comments:   /** */ or /// <BR>
+        Internal comments can use <CODE>//</CODE> or <CODE>/* */</CODE> syntax, as long
+        as you are consistent.
+      </SUMMARY>
+    <H3>File Comments</H3>
+      <SUMMARY>
+        Start each header file with a guard macro.<BR>
+        This should match the name of the class which is defined in the file,
+        including the namespace.<BR>
+        For example, a class in the Dali namespace called Actor would have the guard:<BR><BR> __DALI_ACTOR_H__<BR><BR>
+        An Actor class in the Dali::Internal namespace would have the guard:<BR><BR> __DALI_INTERNAL_ACTOR_H__<BR><BR>
+        The copyright & legal notice should follow the guard macro (inside the #ifdef), since this will improve build times.<BR><BR>
+        Start each source file with the copyright & legal notice.
+      </SUMMARY>
+    <H3>Class Comments</H3>
+      <SUMMARY>
+        Every class definition should have an accompanying comment that
+        describes what it is for and how it should be used. It should have
+        a brief description, followed by a newline and a broader description.
+      </SUMMARY>
+      <CODE class="good">
+        /**
+         * @brief Iterates over the contents of a GargantuanTable.
+         *
+         * Example usage:
+         *    GargantuanTableIterator* iter = table-&gt;NewIterator();
+         *    for( iter-&gt;Seek("foo"); !iter-&gt;done(); iter-&gt;Next() )
+         *    {
+         *      process( iter-&gt;key(), iter-&gt;value() );
+         *    }
+         *    delete iter;
+         */
+        class GargantuanTableIterator
+        {
+          ...
+        };
+      </CODE>
+      <P>
+        Document the synchronization assumptions the class makes, if
+        any. If an instance of the class can be accessed by multiple
+        threads, take extra care to document the rules and invariants
+        surrounding multithreaded use.
+      </P>
+    <H3>Function Comments</H3>
+      <SUMMARY>
+        Every function declaration in a header file must have a brief comment
+        that describes what the function does, followed by a newline. It may
+        be followed by a detailed description on how to use it.
+        These comments should be descriptive ("Opens the file") rather than
+        imperative ("Open the file"); the
+        comment describes the function, it does not tell the function what to do.
+        Each parameter must be documented, as must any return value.
+      </SUMMARY>
+      <P>
+        Types of things to mention in comments at the function
+        declaration:
+      </P>
+      <UL>
+        <LI> What the inputs and outputs are.</LI>
+        <LI> For class member functions:  whether the object
+              remembers reference arguments beyond the
+              duration of the method call, and whether it will
+              free them or not. </LI>
+        <LI> If the function allocates memory that the caller
+              must free. </LI>
+        <LI> Whether any of the arguments can be <CODE>NULL</CODE> </LI>
+        <LI> If there are any performance implications of how a function is used.</LI>
+        <LI> If the function is re-entrant.  What are its synchronization assumptions? </LI>
+      </UL>
+        <CODE class="good">
+          /**
+           * @brief Get the iterator for this data table.
+           *
+           * It is the client's responsibility to delete the iterator,
+           * and it must not use the iterator once the GargantuanTable object
+           * on which the iterator was created has been deleted.
+           *
+           * The iterator is initially positioned at the beginning of the table.
+           *
+           * This method is equivalent to:
+           *    Iterator* iter = table->NewIterator();
+           *    iter->Seek( "" );
+           *    return iter;
+           * If you are going to immediately seek to another place in the
+           * returned iterator, it will be faster to use NewIterator()
+           * and avoid the extra seek.
+           * @return an iterator for this table.
+           */
+          Iterator* GetIterator() const;
+        </CODE>
+        <P>
+          When commenting constructors and destructors, remember that
+          the person reading your code knows what constructors and
+          destructors are for, so comments that just say something like
+          "destroys this object" are not useful.
+        </P>
+    <H3>Variable Comments</H3>
+      <SUMMARY>
+        In general the actual name of the variable should be descriptive
+        enough to give a good idea of what the variable is used for. In
+        certain cases, more comments are required - use Doxygen formatting.
+      </SUMMARY>
+      <CODE class="good">
+        private:
+          /**
+           * @brief Keeps track of the total number of entries in the table.
+           *
+           * Used to ensure we do not go over the limit. -1 means
+           * that we don't yet know how many entries the table has.
+           */
+          int mNumTotalEntries;
+
+          float mDuration; ///< Duration in seconds.
+      </CODE>
+
+    <H3> Duplicate documentation</H3>
+    <SUMMARY>
+        Try to avoid duplicate documentation by using the @copydoc command.
+    </SUMMARY>
+    <P>
+       @copydoc copies a documentation block from the object specified by
+       link-object and pastes it at the location of the command.
+       This command can be useful to avoid cases where a documentation block
+       would otherwise have to be duplicated or it can be used to extend the
+       documentation of an inherited member.
+    </P>
+    <CODE class="good">
+     /**
+      * @copydoc MyClass::myfunction()
+      * More documentation.
+      */
+    </CODE>
+     <P>
+       If the member is overloaded, you should specify the argument types
+       explicitly (without spaces!), like in the following:
+     </P>
+     <CODE class="good">
+      /** @copydoc MyClass::myfunction(type1,type2) */
+     </CODE>
+    <H3>Punctuation, Spelling and Grammar</H3>
+      <SUMMARY>
+        Pay attention to punctuation, spelling, and grammar; it is
+        easier to read well-written comments than badly written ones.
+      </SUMMARY>
+      <P>
+        Comments should usually be written as complete
+        sentences with proper capitalization and periods at the end.
+        Shorter comments, such as comments at the end of a line of
+        code, can sometimes be less formal, but you should be
+        consistent with your style.  Complete sentences are more
+        readable, and they provide some assurance that the comment is
+        complete and not an unfinished thought.
+      </P>
+    <H3>TODO Comments</H3>
+      <SUMMARY>
+        Use <code>TODO</code> comments for code that is temporary, a
+        short-term solution, or good-enough but not perfect.
+      </SUMMARY>
+    <H3>Deprecation Comments</H3>
+      <SUMMARY>
+        Mark deprecated interface points with <code>@deprecated</code> comments.
+      </SUMMARY>
+  </ARTICLE>
+
+<H1>Formatting</H1>
+
+  <SUMMARY>
+    A project is much easier to follow if everyone uses the same style.
+    It is important that all contributors follow the style rules so that
+    they can all read and understand everyone's code easily.
+  </SUMMARY>
+
+  <H2>Formatting Rules <input type="button" value="Hide" onclick="toggleVisibility( this, 'formatting_rules' );"/></H2>
+  <ARTICLE class="detail" id="formatting_rules">
+    <H3>Basic Rules</H3>
+    <UL>
+      <LI>Use only spaces, and indent 2 spaces at a time</LI>
+      <LI>Avoid unnecessary trailing whitescape</LI>
+      <LI>Avoid overly long lines, modern screens and editors can handle upto 120 characters</LI>
+      <LI>Use UTF-8 formatting for non-ASCII characters</LI>
+      <LI>Anything enclosed in parentheses should also have a space inside the parentheses. </LI>
+      <LI>Braces must each be in a line on their own.</LI>
+    </UL>
+    <P>
+    Hex encoding is also OK, and encouraged where it enhances
+    readability &#8212; for example, <code>"\xEF\xBB\xBF"</code> is the
+    Unicode zero-width no-break space character, which would be
+    invisible if included in the source as straight UTF-8.
+    </P>
+
+    <H3>Class Format</H3>
+      <SUMMARY>
+        Sections in <code>public</code>, <code>protected</code> and
+        <code>private</code> order.
+        Typedefs and Enums first, Constructor(s) & Destructors & public API next, then virtual methods and implementation details last.
+      </SUMMARY>
+      <CODE class="good">
+        /**
+         * @brief Class purpose.
+         *
+         * Long description.
+         */
+        class MyClass : public Base
+        {
+        public: // API
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation
+           */
+          MyClass();  // 2 space indent.
+
+          /**
+           * @brief Short description.
+           *
+           * @param[in] var Description
+           */
+          explicit MyClass( int var );
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation
+           */
+          virtual ~MyClass();
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation
+           */
+          void SomeFunction();
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation
+           */
+          void SomeFunctionThatDoesNothing();
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation
+           * @param[in] var Parameter description
+           */
+          void SetSomeVar( int var )
+
+          /**
+           * @brief Short description.
+           *
+           * Documentation.
+           * @return value description.
+           */
+          int GetSomeVar() const
+
+        private: // Implementation
+
+          MyClass( MyClass& aRHs ); ///< no copying
+          MyClass& operator=( const MyClass& aRHs );  ///< no copying.
+          bool SomeInternalFunction();
+
+          int mSomeVar;       ///< short description.
+          int mSomeOtherVar;  ///< short description.
+        };
+      </CODE>
+
+    <H3>Constructor Initializer Lists</H3>
+      <SUMMARY>
+        Constructor initializer lists can be all on one line or with subsequent lines indented.
+        Always initialize things in declaration order, base class first!!
+      </SUMMARY>
+      <CODE class="good">
+        // When it all fits on one line:
+        MyClass::MyClass( int var ) : Base( var), mSomeVar( var ), mSomeOtherVar( var + 1 )
+        {
+        }
+
+        // When it requires multiple lines, indent, putting the colon on
+        // the first initializer line:
+        MyClass::MyClass( int var )
+        : Base( var ),
+          mSomeVar( var ),
+          mSomeOtherVar( var + 1 )
+        {
+          DoSomething();
+        }
+      </CODE>
+
+    <H3>Namespace Formatting</H3>
+      <SUMMARY>
+        The contents of namespaces are not indented.
+      </SUMMARY>
+      <CODE class="good">
+        namespace
+        {
+
+        void Foo()
+        {  // Correct.  No extra indentation within namespace.
+          ...
+        }
+
+        }  // namespace
+      </CODE>
+      <P>
+        When declaring nested namespaces, put each namespace on its own line.
+      </P>
+      <CODE class="good">
+        /**
+         * @brief description of namespace
+         */
+        namespace Foo
+        {
+
+        /**
+         * @brief description of namespace
+         */
+        namespace Bar
+        {
+      </CODE>
+
+    <H3>Function Declarations and Definitions</H3>
+      <SUMMARY>
+        Return type on the same line as function name, parameters on the same line if they fit.
+        All parameters should be named, with identical names in the declaration and definition.
+      </SUMMARY>
+      <CODE class="good">
+        ReturnType ClassName::FunctionName( Type parameterName1, Type parameterName2 )
+        {
+          DoSomething();
+        }
+      </CODE>
+      <P>
+        If you have too much text to fit on one line:
+      </P>
+      <CODE class="good">
+        ReturnType ClassName::ReallyLongFunctionName( Type parameterName1,
+                                                      Type parameterName2,
+                                                      Type parameterName3 )
+        {
+          DoSomething();
+        }
+      </CODE>
+      <P>
+        or if you cannot fit even the first parameter:
+      </P>
+      <CODE class="good">
+        ReturnType LongClassName::ReallyReallyReallyLongFunctionName(
+          Type parameterName1,  // 2 space indent
+          Type parameterName2,
+          Type parameterName3 )
+        {
+          DoSomething();  // 2 space indent
+          ...
+        }
+      </CODE>
+      <P>
+        <code>const</code> keyword should be on the same line as the last parameter:
+      </P>
+      <CODE class="good">
+        // Everything in this function signature fits on a single line
+        ReturnType FunctionName( Type parameter ) const
+        {
+          ...
+        }
+
+        // This function signature requires multiple lines, but
+        // the const keyword is on the line with the last parameter.
+        ReturnType ReallyLongFunctionName( Type parameter1,
+                                           Type parameter2 ) const
+        {
+          ...
+        }
+      </CODE>
+      <P>
+        If some parameters are unused, comment out the variable name in the function definition:
+      </P>
+      <CODE class="good">
+        // Always have named parameters in interfaces.
+        class Shape
+        {
+        public:
+          virtual void Rotate( double radians ) = 0;
+        }
+
+        // Always have named parameters in the declaration.
+        class Circle : public Shape
+        {
+        public:
+          virtual void Rotate( double radians );
+        }
+
+        // Comment out unused named parameters in definitions.
+        void Circle::Rotate( double /*radians*/ )
+        {
+        }
+      </CODE>
+      <CODE class="bad">
+        // Bad - if someone wants to implement later, it's not clear what the
+        // variable means.
+        void Circle::Rotate( double )
+        {
+        }
+      </CODE>
+
+    <H3>Function Calls</H3>
+      <SUMMARY>
+        On one line if it fits; otherwise, wrap arguments at the parenthesis. Put one space inside the parentheses, none outside.
+      </SUMMARY>
+      <BODY>
+        <CODE class="good">
+          bool retval = DoSomething( argument1, argument2, argument3 );
+        </CODE>
+        <P>
+          If the arguments do not all fit on one line, they should be
+          broken up onto multiple lines, with each subsequent line
+          aligned with the first argument:
+        </P>
+        <CODE class="good">
+          bool retval = DoSomething( aVeryVeryVeryVeryLongArgument1,
+                                     argument2, argument3 );
+        </CODE>
+        <P>
+          If the function has many arguments, consider having one per
+          line if this makes the code more readable:
+        </P>
+        <CODE class="good">
+          bool retval = DoSomething( argument1,
+                                     argument2,
+                                     argument3,
+                                     argument4 );
+        </CODE>
+        <P>
+          If the function signature is so long that it cannot fit,
+          place all arguments on subsequent lines:
+        </P>
+        <CODE class="good">
+          if( ... )
+          {
+            DoSomethingThatRequiresALongFunctionName(
+              aVeryLongArgument1,  // indent
+              argument2,
+              argument3,
+              argument4 );
+          }
+        </CODE>
+
+    <H3>Conditionals</H3>
+      <SUMMARY>
+        The <code>if</code> statement should be followed only by the conditional, with a space inside the parentheses, not outside. The following clause must always be surrounded by braces on separate lines.
+        The <code>else</code> keyword belongs on its own line, and the following clause must always be
+        surrounded by braces.
+      </SUMMARY>
+      <CODE class="good">
+        if( condition ) // space inside parentheses
+        {
+          ...
+        }
+        else
+        {
+          ...
+        }
+      </CODE>
+      <CODE class="bad">
+        if(condition)     // Bad - space missing inside parentheses
+        if(condition){    // Doubly bad. Mis-aligned parentheses are harder to read.
+      </CODE>
+      <P>
+        Must always have curly braces for the clauses, and they must always be on a line
+        on their own:
+      </P>
+      <CODE class="good">
+        if( condition )
+        {
+          DoSomething();  // 2 space indent.
+        }
+        else
+        {
+          DoSomethingElse(); // 2 space indent.
+        }
+      </CODE>
+
+    <H3>Loops and Switch Statements</H3>
+      <SUMMARY>
+        Switch statements use braces for blocks. Empty loop bodies must use
+        <code>{}</code> or <code>continue</code>.
+        Switch statements should always have a <code>default</code> case
+        unless they switch on an <code>enum</code> type,
+        for which the compiler will ensure all values are handled.
+
+        If the default case should never execute, simply <code>assert</code>.
+        Put one space inside the parentheses, none outside.
+      </SUMMARY>
+      <P>
+        <code>case</code> blocks in <code>switch</code> statements must have
+        curly braces.
+        They should be placed as shown below.
+      </P>
+
+      <CODE class="good">
+        switch( var )
+        {
+          case 0: // 2 space indent
+          {
+            ...      // 2 space indent
+            break;
+          }
+          case 1:
+          {
+            ...
+            break;
+          }
+          default:
+          {
+            DALI_ASSERT_ALWAYS( false );
+          }
+        }
+      </CODE>
+      <P>
+        Empty loop bodies should use <code>{}</code> or
+        <code>continue</code>, but not a single semicolon.
+      </P>
+      <CODE class="good">
+        while( condition )
+        {
+          // Repeat test until it returns false.
+        }
+
+        for( int i = 0; i < someNumber; ++i )
+        {
+        }  // Good - empty body, clearly separated.
+
+        while( condition )
+          continue;  // Good - continue indicates no logic.
+
+      </CODE>
+      <CODE class="bad">
+        while( condition );  // Bad - looks like part of do/while loop.
+      </CODE>
+    <H3>Pointer and Reference Expressions</H3>
+      <SUMMARY>
+        No spaces around period or arrow.  Pointer operators do not have trailing spaces.
+      </SUMMARY>
+      <P>
+        The following are examples of correctly-formatted pointer and
+        reference expressions:
+      </P>
+      <CODE class="good">
+        x = *p;
+        p = &amp;x;
+        x = r.y;
+        x = r-&gt;y;
+      </CODE>
+      <P>
+        When declaring a pointer variable or argument, you may place
+        the asterisk adjacent to either the type or to the variable
+        name, however, placing with the type is preferred.
+      </P>
+      <CODE class="good">
+        // These are fine, space preceding.
+        char *c;
+        const string &amp;str;
+
+        // These are fine, space following.
+        char* c;    // but remember to do each variable on its own line or "char* c, *d, *e, ...;"!
+        const string&amp; str;
+      </CODE>
+      <CODE class="bad">
+        char * c;  // Bad - spaces on both sides of *
+        const string &amp; str;  // Bad - spaces on both sides of &amp;
+      </CODE>
+      <P>
+        You should do this consistently within a single file,
+        so, when modifying an existing file, use the style in that file.
+      </P>
+
+    <H3>Boolean Expressions</H3>
+      <SUMMARY>
+        When you have a boolean expression that is long, be consistent in
+        how you break up the lines.
+      </SUMMARY>
+      <P>
+        In this example, the logical AND operator is always at the end
+        of the lines:
+      </P>
+      <CODE class="good">
+        if( thisOneThing &gt; thisOtherThing &amp;&amp;
+            aThirdThing == aFourthThing &amp;&amp;
+            yetAnother &amp;&amp; lastOne )
+        {
+          ...
+        }
+      </CODE>
+
+    <H3>Return Values</H3>
+      <SUMMARY>
+        Do not needlessly surround the <code>return</code> expression with parentheses.
+      </SUMMARY>
+      <CODE class="good">
+        return result;                   // No parentheses in the simple case.
+        return ( someLongCondition &amp;&amp;    // Parentheses ok to make a complex
+                 anotherCondition );     //     expression more readable.
+      </CODE>
+      <CODE class="bad">
+        return (value);                // You wouldn't write var = (value);
+        return(result);                // return is not a function!
+      </CODE>
+    <H3>Variable and Array Initialization</H3>
+      <SUMMARY>
+        Your choice of <code>=</code> or <code>()</code>.
+      </SUMMARY>
+      <P>
+        You may choose between <code>=</code> and <code>()</code>; the
+        following are all correct:
+      </P>
+      <CODE class="good">
+        int x = 3;
+        int x( 3 );
+        string name( "Some Name" );
+        string name = "Some Name";
+      </CODE>
+
+    <H3>Preprocessor Directives</H3>
+      <SUMMARY>
+        Preprocessor directives should not be indented but should
+        instead start at the beginning of the line.
+      </SUMMARY>
+      <P>
+        Even when pre-processor directives are within the body of
+        indented code, the directives should start at the beginning of
+        the line.
+      </P>
+      <CODE class="good">
+        // Good - directives at beginning of line
+          if( lopsidedScore )
+          {
+        #if DISASTER_PENDING      // Correct -- Starts at beginning of line
+            DropEverything();
+        #endif
+            BackToNormal();
+          }
+      </CODE>
+      <CODE class="bad">
+        // Bad - indented directives
+          if( lopsidedScore )
+          {
+            #if DISASTER_PENDING  // Wrong!  The "#if" should be at beginning of line
+            DropEverything();
+            #endif                // Wrong!  Do not indent "#endif"
+            BackToNormal();
+          }
+      </CODE>
+
+  </ARTICLE>
+
+  <P>Thats all folks, if you read this far you are now all equipped to write good code :) !! </P>
+
+</BODY>
+</HTML>
diff --git a/docs/dali_internal.doxy b/docs/dali_internal.doxy
new file mode 100644 (file)
index 0000000..08fc7ab
--- /dev/null
@@ -0,0 +1,1550 @@
+# Doxyfile 1.5.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file 
+# that follow. The default is UTF-8 which is also the encoding used for all 
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
+# iconv built into libc) for the transcoding. See 
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
+# by quotes) that should identify the project.
+
+PROJECT_NAME           = Dali
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
+# This could be handy for archiving the generated documentation or 
+# if some version control system is used.
+
+PROJECT_NUMBER         = 
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
+# base path where the generated documentation will be put. 
+# If a relative path is entered, it will be relative to the location 
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = docs/generated
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
+# 4096 sub-directories (in 2 levels) under the output directory of each output 
+# format and will distribute the generated files over these directories. 
+# Enabling this option can be useful when feeding doxygen a huge amount of 
+# source files, where putting all generated files in the same directory would 
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = YES
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
+# documentation generated by doxygen is written. Doxygen will use this 
+# information to generate all constant output in the proper language. 
+# The default language is English, other supported languages are: 
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
+# Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, 
+# Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), 
+# Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, 
+# Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, Slovene, 
+# Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
+# include brief member descriptions after the members that are listed in 
+# the file and class documentation (similar to JavaDoc). 
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
+# the brief description of a member or function before the detailed description. 
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator 
+# that is used to form the text in various listings. Each string 
+# in this list, if found as the leading text of the brief description, will be 
+# stripped from the text and the result after processing the whole list, is 
+# used as the annotated text. Otherwise, the brief description is used as-is. 
+# If left blank, the following values are used ("$name" is automatically 
+# replaced with the name of the entity): "The $name class" "The $name widget" 
+# "The $name file" "is" "provides" "specifies" "contains" 
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       = "The $name class" \
+                         "The $name widget" \
+                         "The $name file" \
+                         is \
+                         provides \
+                         specifies \
+                         contains \
+                         represents \
+                         a \
+                         an \
+                         the
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
+# Doxygen will generate a detailed section even if there is only a brief 
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
+# inherited members of a class in the documentation of that class as if those 
+# members were ordinary class members. Constructors, destructors and assignment 
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
+# path before files name in the file list and in the header files. If set 
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
+# can be used to strip a user-defined part of the path. Stripping is 
+# only done if one of the specified strings matches the left-hand part of 
+# the path. The tag can be used to show relative paths in the file list. 
+# If left blank the directory from which doxygen is run is used as the 
+# path to strip.
+
+STRIP_FROM_PATH        = .
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
+# the path mentioned in the documentation of a class, which tells 
+# the reader which header file to include in order to use a class. 
+# If left blank only the name of the header file containing the class 
+# definition is used. Otherwise one should specify the include paths that 
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    = 
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
+# (but less readable) file names. This can be useful is your file systems 
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
+# will interpret the first line (until the first dot) of a JavaDoc-style 
+# comment as the brief description. If set to NO, the JavaDoc 
+# comments will behave just like regular Qt-style comments 
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
+# interpret the first line (until the first dot) of a Qt-style 
+# comment as the brief description. If set to NO, the comments 
+# will behave just like regular Qt-style comments (thus requiring 
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = YES
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
+# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
+# comments) as a brief description. This used to be the default behaviour. 
+# The new default is to treat a multi-line C++ comment block as a detailed 
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP         = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
+# member inherits the documentation from any documented member that it 
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
+# a new page for each member. If set to NO, the documentation of a member will 
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 2
+
+# This tag can be used to specify a number of aliases that acts 
+# as commands in the documentation. An alias has the form "name=value". 
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
+# put the command \sideeffect (or @sideeffect) in the documentation, which 
+# will result in a user-defined paragraph with heading "Side Effects:". 
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                = 
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
+# sources only. Doxygen will then generate output that is more tailored for C. 
+# For instance, some of the names that are used will be different. The list 
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Java. For instance, namespaces will be presented as packages, qualified 
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
+# sources only. Doxygen will then generate output that is more tailored for 
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
+# sources. Doxygen will then generate output that is tailored for 
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses. 
+# With this tag you can assign which parser to use for a given extension. 
+# Doxygen has a built-in mapping, but you can override or extend it using this tag. 
+# The format is ext=language, where ext is a file extension, and language is one of 
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 
+# use: inc=Fortran f=C
+
+EXTENSION_MAPPING      = 
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
+# to include (a tag file for) the STL sources as input, then you should 
+# set this tag to YES in order to let doxygen match functions declarations and 
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
+# func(std::string) {}). This also make the inheritance and collaboration 
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to 
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
+# Doxygen will parse them like normal C++ but will assume all classes use public 
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter 
+# and setter methods for a property. Setting this option to YES (the default) 
+# will make doxygen to replace the get and set methods by a property in the 
+# documentation. This will only work if the methods are indeed getting or 
+# setting a simple type. If this is not the case, or you want to show the 
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
+# tag is set to YES, then doxygen will reuse the documentation of the first 
+# member in the group (if any) for the other members of the group. By default 
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
+# the same type (for instance a group of public functions) to be put as a 
+# subgroup of that type (e.g. under the Public Functions section). Set it to 
+# NO to prevent subgrouping. Alternatively, this can be done per class using 
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
+# is documented as struct, union, or enum with the name of the typedef. So 
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
+# with name TypeT. When disabled the typedef will appear as a member of a file, 
+# namespace, or class. And the struct will be named TypeS. This can typically 
+# be useful for C code in case the coding convention dictates that all compound 
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
+# determine which symbols to keep in memory and which to flush to disk. 
+# When the cache is full, less often used symbols will be written to disk. 
+# For small to medium size projects (<1000 input files) the default value is 
+# probably good enough. For larger projects a too small cache size can cause 
+# doxygen to be busy swapping symbols to and from disk most of the time 
+# causing a significant performance penality. 
+# If the system has enough physical memory increasing the cache will improve the 
+# performance by keeping more symbols in memory. Note that the value works on 
+# a logarithmic scale so increasing the size by one will rougly double the 
+# memory usage. The cache size is given by this formula: 
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
+# documentation are documented, even if no documentation was available. 
+# Private class members and static file members will be hidden unless 
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file 
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
+# defined locally in source files will be included in the documentation. 
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local 
+# methods, which are defined in the implementation section but not in 
+# the interface are included in the documentation. 
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be 
+# extracted and appear in the documentation as a namespace called 
+# 'anonymous_namespace{file}', where file will be replaced with the base 
+# name of the file that contains the anonymous namespace. By default 
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
+# undocumented members of documented classes, files or namespaces. 
+# If set to NO (the default) these members will be included in the 
+# various overviews, but no documentation section is generated. 
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
+# undocumented classes that are normally visible in the class hierarchy. 
+# If set to NO (the default) these classes will be included in the various 
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
+# friend (class|struct|union) declarations. 
+# If set to NO (the default) these declarations will be included in the 
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
+# documentation blocks found inside the body of a function. 
+# If set to NO (the default) these blocks will be appended to the 
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation 
+# that is typed after a \internal command is included. If the tag is set 
+# to NO (the default) then the documentation will be excluded. 
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
+# file names in lower-case letters. If set to YES upper-case letters are also 
+# allowed. This is useful if you have classes or files whose names only differ 
+# in case and if your file system supports case sensitive file names. Windows 
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
+# will show members with their full class and namespace scopes in the 
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
+# will put a list of the files that are included by a file in the documentation 
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
+# will sort the (detailed) documentation of file and class members 
+# alphabetically by member name. If set to NO the members will appear in 
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
+# brief documentation of file, namespace and class members alphabetically 
+# by member name. If set to NO (the default) the members will appear in 
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
+# hierarchy of group names into alphabetical order. If set to NO (the default) 
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
+# sorted by fully-qualified names, including namespaces. If set to 
+# NO (the default), the class list will be sorted only by class name, 
+# not including the namespace part. 
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
+# Note: This option applies only to the class list, not to the 
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or 
+# disable (NO) the todo list. This list is created by putting \todo 
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or 
+# disable (NO) the test list. This list is created by putting \test 
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or 
+# disable (NO) the bug list. This list is created by putting \bug 
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
+# disable (NO) the deprecated list. This list is created by putting 
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional 
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       = 
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
+# the initial value of a variable or define consists of for it to appear in 
+# the documentation. If the initializer consists of more lines than specified 
+# here it will be hidden. Use a value of 0 to hide initializers completely. 
+# The appearance of the initializer of individual variables and defines in the 
+# documentation can be controlled using \showinitializer or \hideinitializer 
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
+# at the bottom of the documentation of classes and structs. If set to YES the 
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories 
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
+# This will remove the Files entry from the Quick Index and from the 
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
+# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
+# doxygen should invoke to get the current version for each file (typically from 
+# the version control system). Doxygen will invoke the program by executing (via 
+# popen()) the command <command> <input-file>, where <command> is the value of 
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
+# provided by doxygen. Whatever the program writes to standard output 
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    = 
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 
+# doxygen. The layout file controls the global structure of the generated output files 
+# in an output format independent way. The create the layout file that represents 
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name 
+# of the layout file.
+
+LAYOUT_FILE            = 
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated 
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are 
+# generated by doxygen. Possible values are YES and NO. If left blank 
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
+# potential errors in the documentation, such as not documenting some 
+# parameters in a documented function, or documenting parameters that 
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for 
+# functions that are documented, but have no documentation for their parameters 
+# or return value. If set to NO (the default) doxygen will only warn about 
+# wrong or incomplete parameter documentation, but not about the absence of 
+# documentation.
+
+WARN_NO_PARAMDOC       = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that 
+# doxygen can produce. The string should contain the $file, $line, and $text 
+# tags, which will be replaced by the file and line number from which the 
+# warning originated and the warning text. Optionally the format may contain 
+# $version, which will be replaced by the version of the file (if it could 
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning 
+# and error messages should be written. If left blank the output is written 
+# to stderr.
+
+WARN_LOGFILE           = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain 
+# documented source files. You may enter file names like "myfile.cpp" or 
+# directories like "/usr/src/myproject". Separate the files or directories 
+# with spaces.
+
+INPUT                  = dali/ \
+                         dali/public-api
+
+# This tag can be used to specify the character encoding of the source files 
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
+# also the default input encoding. Doxygen uses libiconv (or the iconv built 
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for 
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the 
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank the following patterns are tested: 
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS          = *.c \
+                         *.cc \
+                         *.cxx \
+                         *.cpp \
+                         *.c++ \
+                         *.d \
+                         *.java \
+                         *.ii \
+                         *.ixx \
+                         *.ipp \
+                         *.i++ \
+                         *.inl \
+                         *.h \
+                         *.hh \
+                         *.hxx \
+                         *.hpp \
+                         *.h++ \
+                         *.idl \
+                         *.odl \
+                         *.cs \
+                         *.php \
+                         *.php3 \
+                         *.inc \
+                         *.m \
+                         *.mm \
+                         *.dox \
+                         *.py \
+                         *.f90 \
+                         *.f \
+                         *.vhd \
+                         *.vhdl
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
+# should be searched for input files as well. Possible values are YES and NO. 
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should 
+# excluded from the INPUT source files. This way you can easily exclude a 
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE                = build \
+                         dali/platform-abstraction/
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
+# directories that are symbolic links (a Unix filesystem feature) are excluded 
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the 
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
+# certain files from those directories. Note that the wildcards are matched 
+# against the file with absolute path, so to exclude all test directories 
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       = 
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
+# (namespaces, classes, functions, etc.) that should be excluded from the 
+# output. The symbol name can be a fully qualified name, a word, or if the 
+# wildcard * is used, a substring. Examples: ANamespace, AClass, 
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        = 
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or 
+# directories that contain example code fragments that are included (see 
+# the \include command).
+
+EXAMPLE_PATH           = examples \
+                         docs
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
+# and *.h) to filter out the source-files in the directories. If left 
+# blank all files are included.
+
+EXAMPLE_PATTERNS       = *
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
+# searched for input files to be used with the \include or \dontinclude 
+# commands irrespective of the value of the RECURSIVE tag. 
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = YES
+
+# The IMAGE_PATH tag can be used to specify one or more files or 
+# directories that contain image that are included in the documentation (see 
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should 
+# invoke to filter for each input file. Doxygen will invoke the filter program 
+# by executing (via popen()) the command <filter> <input-file>, where <filter> 
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
+# input file. Doxygen will then use the output that the filter program writes 
+# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
+# ignored.
+
+INPUT_FILTER           = 
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
+# basis.  Doxygen will compare the file name with each pattern and apply the 
+# filter if there is a match.  The filters are a list of the form: 
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
+# is applied to all files.
+
+FILTER_PATTERNS        = 
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
+# INPUT_FILTER) will be used to filter the input files when producing source 
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
+# be generated. Documented entities will be cross-referenced with these sources. 
+# Note: To get rid of all source code in the generated output, make sure also 
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body 
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
+# doxygen to hide any special comment blocks from generated source code 
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES 
+# then for each documented function all documented 
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES 
+# then for each documented function all documented entities 
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
+# link to the source code.  Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code 
+# will point to the HTML generated by the htags(1) tool instead of doxygen 
+# built-in source browser. The htags tool is part of GNU's global source 
+# tagging system (see http://www.gnu.org/software/global/global.html). You 
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
+# will generate a verbatim copy of the header file for each class for 
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
+# of all compounds will be generated. Enable this if the project 
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all 
+# classes will be put under the same header in the alphabetical index. 
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard header.
+
+HTML_HEADER            = 
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
+# each generated HTML page. If it is left blank doxygen will generate a 
+# standard footer.
+
+HTML_FOOTER            = docs/api_footer.html
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
+# style sheet that is used by each HTML page. It can be used to 
+# fine-tune the look of the HTML output. If the tag is left blank doxygen 
+# will generate a default style sheet. Note that doxygen will try to copy 
+# the style sheet file to the HTML output directory, so don't put your own 
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        = 
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
+# files or namespaces will be aligned in HTML using tables. If set to 
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
+# documentation will contain sections that can be hidden and shown after the 
+# page has loaded. For this to work a browser that supports 
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files 
+# will be generated that can be used as input for Apple's Xcode 3 
+# integrated development environment, introduced with OSX 10.5 (Leopard). 
+# To create a documentation set, doxygen will generate a Makefile in the 
+# HTML output directory. Running make will produce the docset in that 
+# directory and running "make install" will install the docset in 
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
+# it at startup. 
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
+# feed. A documentation feed provides an umbrella under which multiple 
+# documentation sets from a single provider (such as a company or product suite) 
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
+# should uniquely identify the documentation set bundle. This should be a 
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
+# will be generated that can be used as input for tools like the 
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
+# be used to specify the file name of the resulting .chm file. You 
+# can add a path in front of the file if the result should not be 
+# written to the html output directory.
+
+CHM_FILE               = dali.chm
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
+# be used to specify the location (absolute path including file name) of 
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
+# controls if a separate .chi index file is generated (YES) or that 
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
+# content.
+
+CHM_INDEX_ENCODING     = 
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
+# controls whether a binary table of contents is generated (YES) or a 
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members 
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 
+# are set, an additional index file will be generated that can be used as input for 
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 
+# HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
+# be used to specify the file name of the resulting .qch file. 
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               = 
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = 
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
+# Qt Help Project output. For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 
+# For more information please see 
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   = 
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  = 
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 
+# filter section matches. 
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  = 
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
+# be used to specify the location of Qt's qhelpgenerator. 
+# If non-empty doxygen will try to run qhelpgenerator on the generated 
+# .qhp file.
+
+QHG_LOCATION           = 
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
+# top of each HTML page. The value NO (the default) enables the index and 
+# the value YES disables it.
+
+DISABLE_INDEX          = NO
+
+# This tag can be used to set the number of enum values (range [1..20]) 
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
+# structure should be generated to display hierarchical information. 
+# If the tag value is set to FRAME, a side panel will be generated 
+# containing a tree-like index structure (just like the one that 
+# is generated for HTML Help). For this to work a browser that supports 
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, 
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are 
+# probably better off using the HTML help feature. Other possible values 
+# for this tag are: HIERARCHIES, which will generate the Groups, Directories, 
+# and Class Hierarchy pages using a tree view instead of an ordered list; 
+# ALL, which combines the behavior of FRAME and HIERARCHIES; and NONE, which 
+# disables this behavior completely. For backwards compatibility with previous 
+# releases of Doxygen, the values YES and NO are equivalent to FRAME and NONE 
+# respectively.
+
+GENERATE_TREEVIEW      = NONE
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
+# used to set the initial width (in pixels) of the frame in which the tree 
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# Use this tag to change the font size of Latex formulas included 
+# as images in the HTML documentation. The default is 10. Note that 
+# when you change the font size after a successful doxygen run you need 
+# to manually remove any form_*.png images from the HTML output directory 
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
+# generate Latex output.
+
+GENERATE_LATEX         = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
+# generate index for LaTeX. If left blank `makeindex' will be used as the 
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
+# LaTeX documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used 
+# by the printer. Possible values are: a4, a4wide, letter, legal and 
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         = 
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
+# the generated latex document. The header should contain everything until 
+# the first chapter. If it is left blank doxygen will generate a 
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           = 
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
+# contain links (just like the HTML output) instead of page references 
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
+# plain latex in the generated Makefile. Set this option to YES to get a 
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
+# command to the generated LaTeX files. This will instruct LaTeX to keep 
+# running if errors occur, instead of asking the user for help. 
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
+# include the index chapters (such as File Index, Compound Index, etc.) 
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
+# The RTF output is optimized for Word 97 and may not look very pretty with 
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
+# RTF documents. This may be useful for small projects and may help to 
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
+# will contain hyperlink fields. The RTF file will 
+# contain links (just like the HTML output) instead of page references. 
+# This makes the output suitable for online browsing using WORD or other 
+# programs which support those fields. 
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's 
+# config file, i.e. a series of assignments. You only have to provide 
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    = 
+
+# Set optional variables used in the generation of an rtf document. 
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    = 
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to 
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
+# then it will generate one additional man file for each entity 
+# documented in the real man page(s). These additional files 
+# only source the real man page, but without them the man command 
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will 
+# generate an XML file that captures the structure of 
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_SCHEMA             = 
+
+# The XML_DTD tag can be used to specify an XML DTD, 
+# which can be used by a validating XML parser to check the 
+# syntax of the XML files.
+
+XML_DTD                = 
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
+# dump the program listings (including syntax highlighting 
+# and cross-referencing information) to the XML output. Note that 
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
+# generate an AutoGen Definitions (see autogen.sf.net) file 
+# that captures the structure of the code including all 
+# documentation. Note that this feature is still experimental 
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
+# generate a Perl module file that captures the structure of 
+# the code including all documentation. Note that this 
+# feature is still experimental and incomplete at the 
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
+# nicely formatted so it can be parsed by a human reader.  This is useful 
+# if you want to understand what is going on.  On the other hand, if this 
+# tag is set to NO the size of the Perl module output will be much smaller 
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file 
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
+# This is useful so different doxyrules.make files included by the same 
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX = 
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor   
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
+# evaluate all C-preprocessor directives found in the sources and include 
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
+# names in the source code. If set to NO (the default) only conditional 
+# compilation will be performed. Macro expansion can be done in a controlled 
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
+# then the macro expansion is limited to the macros specified with the 
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that 
+# contain include files that are not input files but should be processed by 
+# the preprocessor.
+
+INCLUDE_PATH           = 
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
+# patterns (like *.h and *.hpp) to filter out the header-files in the 
+# directories. If left blank, the patterns specified with FILE_PATTERNS will 
+# be used.
+
+INCLUDE_FILE_PATTERNS  = 
+
+# The PREDEFINED tag can be used to specify one or more macro names that 
+# are defined before the preprocessor is started (similar to the -D option of 
+# gcc). The argument of the tag is a list of macros of the form: name 
+# or name=definition (no spaces). If the definition and the = are 
+# omitted =1 is assumed. To prevent a macro definition from being 
+# undefined via #undef or recursively expanded use the := operator 
+# instead of the = operator.
+
+PREDEFINED             = 
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
+# this tag can be used to specify a list of macro names that should be expanded. 
+# The macro definition that is found in the sources will be used. 
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED      = 
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
+# doxygen's preprocessor will remove all function-like macros that are alone 
+# on a line, have an all uppercase name, and do not end with a semicolon. Such 
+# function macros are typically used for boiler-plate code, and will confuse 
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references   
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles. 
+# Optionally an initial location of the external documentation 
+# can be added for each tagfile. The format of a tag file without 
+# this location is as follows: 
+#   TAGFILES = file1 file2 ... 
+# Adding location for the tag files is done as follows: 
+#   TAGFILES = file1=loc1 "file2 = loc2" ... 
+# where "loc1" and "loc2" can be relative or absolute paths or 
+# URLs. If a location is present for each tag, the installdox tool 
+# does not have to be run to correct the links. 
+# Note that each tag file must have a unique name 
+# (where the name does NOT include the path) 
+# If a tag file is not located in the directory in which doxygen 
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               = 
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       = 
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
+# in the class index. If set to NO only the inherited external classes 
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
+# in the modules index. If set to NO, only the current project's groups will 
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script 
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool   
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
+# or super classes. Setting the tag to NO turns the diagrams off. Note that 
+# this option is superseded by the HAVE_DOT option below. This is only a 
+# fallback. It is recommended to install and use dot, since it yields more 
+# powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc 
+# command. Doxygen will then run the mscgen tool (see 
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
+# the mscgen tool resides. If left empty the tool is assumed to be found in the 
+# default search path.
+
+MSCGEN_PATH            = 
+
+# If set to YES, the inheritance and collaboration graphs will hide 
+# inheritance and usage relations if the target is undocumented 
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
+# available from the path. This tool is part of Graphviz, a graph visualization 
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# By default doxygen will write a font called FreeSans.ttf to the output 
+# directory and reference it in all dot files that doxygen generates. This 
+# font does not include all possible unicode characters however, so when you need 
+# these (or just want a differently looking font) you can specify the font name 
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
+# which can be done by putting it in a standard location or by setting the 
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
+# containing the font.
+
+DOT_FONTNAME           = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the output directory to look for the 
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
+# different font using DOT_FONTNAME you can set the path where dot 
+# can find it using this tag.
+
+DOT_FONTPATH           = 
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect inheritance relations. Setting this tag to YES will force the 
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for each documented class showing the direct and 
+# indirect implementation dependencies (inheritance, containment, and 
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
+# collaboration diagrams in a style similar to the OMG's Unified Modeling 
+# Language.
+
+UML_LOOK               = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the 
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
+# tags are set to YES then doxygen will generate a graph for each documented 
+# file showing the direct and indirect include dependencies of the file with 
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
+# documented header file showing the documented files that directly or 
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
+# doxygen will generate a call dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable call graphs 
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
+# doxygen will generate a caller dependency graph for every global function 
+# or class method. Note that enabling this option will significantly increase 
+# the time of a run. So in most cases it will be better to enable caller 
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
+# then doxygen will show the dependencies a directory has on other directories 
+# in a graphical way. The dependency relations are determined by the #include 
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
+# generated by dot. Possible values are png, jpg, or gif 
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT       = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be 
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               = 
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that 
+# contain dot files that are included in the documentation (see the 
+# \dotfile command).
+
+DOTFILE_DIRS           = 
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
+# nodes that will be shown in the graph. If the number of nodes in a graph 
+# becomes larger than this value, doxygen will truncate the graph, which is 
+# visualized by representing a node as a red box. Note that doxygen if the 
+# number of direct children of the root node in a graph is already larger than 
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 500
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
+# graphs generated by dot. A depth value of 3 means that only nodes reachable 
+# from the root by following a path via at most 3 edges will be shown. Nodes 
+# that lay further from the root node will be omitted. Note that setting this 
+# option to 1 or 2 may greatly reduce the computation time needed for large 
+# code bases. Also note that the size of a graph can be further restricted by 
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 8
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
+# background. This is disabled by default, because dot on Windows does not 
+# seem to support this out of the box. Warning: Depending on the platform used, 
+# enabling this option may lead to badly anti-aliased labels on the edges of 
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
+# files in one run (i.e. multiple -o and -T options on the command line). This 
+# makes dot run faster, but since only newer versions of dot (>1.8.10) 
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
+# generate a legend page explaining the meaning of the various boxes and 
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
+# remove the intermediate dot files that are used to generate 
+# the various graphs.
+
+DOT_CLEANUP            = YES
+
+#---------------------------------------------------------------------------
+# Options related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be 
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE           = NO
diff --git a/docs/templates/example-class-internal.cpp b/docs/templates/example-class-internal.cpp
new file mode 100644 (file)
index 0000000..eecf5cb
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// Class header
+#include "example-class-internal.h"
+
+// System includes
+#include <algorithm>
+
+// Dali includes
+#include "actor.h"
+
+namespace // unnamed namespace start
+{
+
+const int gExampleConstant = 0;
+
+void ExampleNonMemberFunction()
+{
+}
+
+} // unnamed namespace end
+
+namespace Dali
+{
+
+namespace Internal
+{
+
+ExampleClass::ExampleClass()
+{
+}
+
+ExampleClass::ExampleClass(const string& name)
+: mName(name)
+{
+}
+
+ExampleClass::~ExampleClass()
+{
+}
+
+void ExampleClass::SetName(const string& name)
+{
+  mName = name;
+
+  // Notify derived classes
+  OnNameSet();
+}
+
+void ExampleClass::HelperMember(ExampleEnum exampleParam)
+{
+  // TODO
+}
+
+} // namespace Internal
+
+} // namespace Dali
diff --git a/docs/templates/example-class-internal.h b/docs/templates/example-class-internal.h
new file mode 100644 (file)
index 0000000..4e54729
--- /dev/null
@@ -0,0 +1,155 @@
+#ifndef __DALI_INTERNAL_EXAMPLE_CLASS_H__
+#define __DALI_INTERNAL_EXAMPLE_CLASS_H__
+
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <list>
+#include <string>
+
+// INTERNAL INCLUDES
+#include <dali/public-api/core/actors/actor.h>
+
+namespace Dali
+{
+
+// Forward declarations for the Dali namespace
+class XXXX;
+
+namespace Internal
+{
+
+// Forward declarations for the Dali::Internal namespace
+class YYYY;
+
+/**
+ * TODO - Rewrite this comment, to explain the purpose of your class
+ */
+class ExampleClass : public ExampleBaseClass
+{
+public: // Types
+
+  typedef std::list<XXXX> ExampleContainer;
+
+  enum ExampleEnum
+  {
+    FirstValue  = 0, ///< First value description
+    SecondValue = 1  ///< Second value description
+  };
+
+public: // Construction
+
+  /**
+   * Create an ExampleClass.
+   */
+  ExampleClass();
+
+  /**
+   * Create an ExampleClass with a name.
+   * @param[in] The name of the example class.
+   */
+  ExampleClass(const std::string& name);
+
+  /**
+   * Virtual destructor; ExampleClass is intended as a base class.
+   */
+  virtual ~ExampleClass();
+
+public: // Public members
+
+  /**
+   * Set the name of an ExampleClass.
+   * @pre TODO - Edit this example comment.
+   * @param[in] The new name.
+   * @post TODO - Edit this example comment.
+   */
+  void SetName();
+
+  /**
+   * Retreive the name of an ExampleClass.
+   * @pre TODO - Edit this example comment.
+   * @return The name of the example class.
+   * @post TODO - Edit this example comment.
+   */
+  std::string GetName() const { return mName; }
+
+protected: // Protected members
+
+  /**
+   * Example helper method, which is accessible by derived classes.
+   * @param [in] exampleParam An an example parameter.
+   */
+  void HelperMember(ExampleEnum exampleParam);
+
+private: // Private members
+
+  /**
+   * Undefined copy constructor; declaring this prevents accidental copying.
+   * @param[in] A reference to the ExampleClass to copy.
+   */
+  ExampleClass(const ExampleClass&);
+
+  /**
+   * Undefined assignment operator; declaring this prevents accidental copying.
+   * @param[in] A reference to the ExampleClass to copy.
+   * @return A reference to the copied ExampleClass.
+   */
+  ExampleClass& operator=(const ExampleClass& rhs);
+
+  /**
+   * Example pure virtual member.
+   * The intention here is to avoid making the public SetName() virtual.
+   * When the name changes, derived classes receive this notification.
+   */
+  virtual void OnNameSet() = 0;
+
+protected: // Protected data
+
+  ExampleContainer mContainer;
+
+private: // Private data
+
+  std::string mName;
+};
+
+} // namespace Internal
+
+// Helpers for public-api forwarding methods
+
+inline Internal::ExampleClass& GetImplementation(Dali::ExampleClass& example)
+{
+  DALI_ASSERT(example);
+
+  BaseObject& handle = example.GetBaseObject();
+
+  return static_cast<Internal::ExampleClass&>(handle);
+}
+
+inline const Internal::ExampleClass& GetImplementation(const Dali::ExampleClass& example)
+{
+  DALI_ASSERT(example);
+
+  const BaseObject& handle = example.GetBaseObject();
+
+  return static_cast<const Internal::ExampleClass&>(handle);
+}
+
+} // namespace Dali
+
+#endif // __DALI_INTERNAL_EXAMPLE_CLASS_H__
+
diff --git a/packaging/dali.spec b/packaging/dali.spec
new file mode 100644 (file)
index 0000000..b8946b0
--- /dev/null
@@ -0,0 +1,137 @@
+Name:       dali
+Summary:    The OpenGLES Canvas Core Library
+Version:    1.0.49
+Release:    1
+Group:      System/Libraries
+License:    Apache-2.0 and BSD-2.0 and MIT
+URL:        https://review.tizen.org/git/?p=platform/core/uifw/dali-core.git;a=summary
+Source0:    %{name}-%{version}.tar.gz
+
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+BuildRequires:  pkgconfig
+BuildRequires:  gawk
+
+%description
+The OpenGLES Canvas Core Library provides a 3D scene graph
+
+##############################
+# devel
+##############################
+%package devel
+Summary:    Development components for the OpenGLES Canvas Core Library
+Group:      Development/Building
+Requires:   %{name} = %{version}-%{release}
+Requires:   %{name}-integration-devel = %{version}-%{release}
+
+%description devel
+Development components for the OpenGLES Canvas Core Library - public headers and package config
+
+##############################
+# integration-devel
+##############################
+%package integration-devel
+Summary:    Integration development package for the OpenGLES Canvas
+Group:      Development/Building
+Requires:   %{name} = %{version}-%{release}
+
+%description integration-devel
+Integration development package for the OpenGLES Canvas - headers for integrating with an adaptor/platform abstraction library.
+
+##############################
+# Preparation
+##############################
+%prep
+%setup -q
+%define dali_data_rw_dir /opt/usr/share/dali/
+%define dali_data_ro_dir /usr/share/dali/
+%define dev_include_path %{_includedir}
+
+##############################
+# Build
+##############################
+%build
+PREFIX="/usr"
+CXXFLAGS+=" -Wall -g -Os -DNDEBUG -fPIC -fvisibility-inlines-hidden -fdata-sections -ffunction-sections "
+LDFLAGS+=" -Wl,--rpath=$PREFIX/lib -Wl,--as-needed -Wl,--gc-sections -lgcc_s -lgcc -lpthread -Wl,-Bsymbolic-functions "
+
+%ifarch %{arm}
+CXXFLAGS+=" -D_ARCH_ARM_ -mfpu=neon"
+%endif
+
+libtoolize --force
+cd %{_builddir}/%{name}-%{version}/build/tizen
+autoreconf --install
+DALI_DATA_RW_DIR="%{dali_data_rw_dir}"
+DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+export DALI_DATA_RW_DIR
+export DALI_DATA_RO_DIR
+
+CFLAGS="${CFLAGS:-%optflags}" ; export CFLAGS;
+CXXFLAGS="${CXXFLAGS:-%optflags}" ; export CXXFLAGS;
+LDFLAGS="${LDFLAGS:-%optflags}" ; export LDFLAGS;
+./configure \
+      --program-prefix=%{?_program_prefix} \
+      --prefix=%{_prefix} \
+      --exec-prefix=%{_exec_prefix} \
+      --bindir=%{_bindir} \
+      --sbindir=%{_sbindir} \
+      --sysconfdir=%{_sysconfdir} \
+      --datadir=%{_datadir} \
+      --includedir=%{_includedir} \
+      --libdir=%{_libdir} \
+      --libexecdir=%{_libexecdir} \
+      --localstatedir=%{_localstatedir} \
+      --sharedstatedir=%{_sharedstatedir} \
+      --mandir=%{_mandir} \
+      --infodir=%{_infodir}
+
+make %{?jobs:-j%jobs}
+
+##############################
+# Installation
+##############################
+%install
+rm -rf %{buildroot}
+cd build/tizen
+%make_install DALI_DATA_RW_DIR="%{dali_data_rw_dir}" DALI_DATA_RO_DIR="%{dali_data_ro_dir}"
+
+# LICENSE
+mkdir -p %{buildroot}/usr/share/license
+cp -af %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{name}
+
+
+##############################
+# Post Install
+##############################
+%post
+/sbin/ldconfig
+exit 0
+
+##############################
+# Post Uninstall
+##############################
+%postun
+/sbin/ldconfig
+exit 0
+
+##############################
+# Files in Binary Packages
+##############################
+
+%files
+%manifest dali.manifest
+%defattr(-,root,root,-)
+%{_libdir}/lib%{name}-core.so*
+%defattr(-,app,app,-)
+%{_datadir}/license/%{name}
+
+%files devel
+%defattr(-,root,root,-)
+%{_libdir}/pkgconfig/*.pc
+%{dev_include_path}/%{name}/public-api/*
+%{dev_include_path}/%{name}/devel-api/*
+
+%files integration-devel
+%defattr(-,root,root,-)
+%{_includedir}/%{name}/integration-api/*